Utility for writing frontend plugins for Datasette with Vite
Install this plugin in the same environment as Datasette.
datasette install datasette-viteThis plugin provides a vite_entry() function that other Datasette plugins can use to include Vite-built JavaScript and CSS assets in their pages.
Your plugin needs a Vite project alongside its Python code. Configure vite.config.ts to output a manifest and place built files in a static/ directory:
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
build: {
manifest: true,
outDir: 'dist',
rollupOptions: {
input: 'src/main.ts',
output: {
assetFileNames: 'static/[name]-[hash][extname]',
chunkFileNames: 'static/[name]-[hash].js',
entryFileNames: 'static/[name]-[hash].js',
}
}
}
})After running vite build, copy dist/.vite/manifest.json and dist/static/ into your plugin's Python package directory so they are included when your plugin is installed.
from datasette_vite import vite_entry
entry = vite_entry(
datasette=datasette,
plugin_package="my_datasette_plugin",
)
html = await entry("src/main.ts")The returned html string contains <script> and <link> tags ready to include in your page:
<link rel="stylesheet" href="/-/static-plugins/my_datasette_plugin/main-def456.css">
<script type="module" src="/-/static-plugins/my_datasette_plugin/main-abc123.js"></script>During development, pass vite_dev_path to point at a running Vite dev server instead of reading from the manifest. This enables hot module replacement:
entry = vite_entry(
datasette=datasette,
plugin_package="my_datasette_plugin",
vite_dev_path="http://localhost:5173/",
)
html = await entry("src/main.ts")This produces:
<script type="module" src="http://localhost:5173/@vite/client"></script>
<script type="module" src="http://localhost:5173/src/main.ts"></script>If your plugin needs to inject assets into existing Datasette pages (rather than owning the full template), use vite_js_urls() and vite_css_urls(). These return structured data suitable for Datasette's extra_js_urls and extra_css_urls hooks:
from datasette import hookimpl
from datasette_vite import vite_js_urls, vite_css_urls
VITE_DEV_PATH = os.environ.get("VITE_DEV_PATH")
@hookimpl
def extra_js_urls(datasette):
return vite_js_urls(
datasette=datasette,
entrypoint="src/main.ts",
plugin_package="my_datasette_plugin",
vite_dev_path=VITE_DEV_PATH,
)
@hookimpl
def extra_css_urls(datasette):
return vite_css_urls(
datasette=datasette,
entrypoint="src/main.ts",
plugin_package="my_datasette_plugin",
vite_dev_path=VITE_DEV_PATH,
)vite_js_urls() returns a list of {"url": "...", "module": True} dicts. In dev mode this includes the Vite client script; in prod mode it resolves the hashed filename from the manifest.
vite_css_urls() returns a list of CSS URL strings. In dev mode this returns [] (Vite injects CSS via JS). In prod mode it collects all CSS from the entrypoint and recursively from imported chunks.
datasette: The Datasette instance.plugin_package: The Python package name of your plugin (used to resolve the manifest location and generate static asset URLs).vite_dev_path: Optional URL to a running Vite dev server (e.g."http://localhost:5173/"). When set, assets are served from the dev server instead of from built files.manifest_dir: Optional path to the directory containingmanifest.json. Defaults to the directory of your plugin package's__init__.py.
Returns an async callable. Call it with an entrypoint path (matching a key in your Vite manifest) to get an HTML string of the corresponding <script> and <link> tags.
Returns a list of URL entries suitable for Datasette's extra_js_urls hook. Each entry is a {"url": "...", "module": True} dict.
Returns a list of CSS URL strings suitable for Datasette's extra_css_urls hook. Includes CSS from the entrypoint and recursively from imported chunks.
To set up this plugin locally, first checkout the code. You can confirm it is available like this:
cd datasette-vite
# Confirm the plugin is visible
uv run datasette pluginsTo run the tests:
uv run pytest