Skip to content

Vite

Vite is a fast frontend build tool that compiles JavaScript, CSS, and other assets for production. FastAPI Startkit ships with first-party Vite integration through ViteProvider, supporting HMR in development and manifest-based asset fingerprinting in production.

Example App

A fully working example is available in the vite-app directory of the monorepo. It demonstrates the complete setup: ViteProvider registration, config, Vite config, and a template using vite().

Setup

Install the optional vite package to use Vite integration:

bash
pip install "fastapi-startkit[vite]"

Then add ViteProvider to your application's providers list:

python
# bootstrap/application.py
from fastapi_startkit.vite import ViteProvider

app = Application(
    base_path=...,
    providers=[
        ViteProvider,
        ...
    ],
)

Publish the default config and asset files:

bash
uv run python artisan provider:publish --provider=vite

This creates the following files in your project:

  • config/vite.py: FastAPI configuration for Vite.
  • package.json: Vite dependencies and scripts.
  • vite.config.js: Vite configuration with Tailwind CSS support.
  • resources/js/app.ts: Main entry point.
  • resources/css/app.css: Main CSS entry point.
  • resources/templates/index.html: Example template using Vite.

After publishing, install the frontend dependencies and start the development server:

bash
npm install
npm run dev

NOTE

Ensure APP_URL in your .env matches your FastAPI server URL (e.g., http://127.0.0.1:8000) so that Vite's Hot Module Replacement (HMR) can correctly communicate with the backend.

Configuration

config/vite.py uses a ViteConfig dataclass with these defaults:

python
from fastapi_startkit.vite import ViteConfig

config = ViteConfig(
    public_path="public",       # Root directory for assets
    build_directory="build",    # Subfolder inside public_path for production build
    hot_file="hot",             # Presence of this file signals dev server is running
    manifest_filename="manifest.json",
    asset_url="",               # Optional CDN prefix for asset URLs
    static_url="/build",        # URL prefix used when mounting static files
    mount_static=True,          # Auto-mount public/build as a StaticFiles route
    template=True,              # Auto-bind Jinja2 templates (default)
    templates_directory="resources/templates",  # Directory the template engine reads from
)

To use your custom configuration, pass the ViteConfig class when registering the provider. This is optional; if omitted, the provider will use the default settings.

python
from config.vite import ViteConfig

app = Application(
    providers=[
        (ViteProvider, ViteConfig),
    ],
)

Loading a Page with JS and CSS

ViteProvider automatically sets up template rendering, so you can return an HTML page directly from a route. Resolve templates from the container and return a TemplateResponse:

python
from starlette.requests import Request

async def index(request: Request):
    from fastapi_startkit import app
    templates = app().make("templates")
    return templates.TemplateResponse(request, "index.html", {"user": user})

In your template, call vite() with the entry point to inject the JS and CSS tags:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FastAPI + Vite</title>
    {{ vite('resources/js/app.ts') }}
</head>
<body>
    <h1>Hello from FastAPI + Vite</h1>
</body>
</html>

vite(), vite_asset(), and vite_react_refresh() are all available as template globals — see Template Helpers below.

Development Mode (HMR)

Start the Vite dev server:

bash
npm run dev

When the public/hot file exists, the Vite class switches to HMR mode automatically. Asset tags point to the HMR server (default: http://localhost:5173) instead of the build directory.

The hot file's content is the HMR origin URL. Vite writes it automatically; you can also create it manually:

http://localhost:5173

Production Mode

Build your assets:

bash
npm run build

Vite writes public/build/manifest.json. The framework reads this manifest at startup (cached in memory) and generates hashed asset URLs with preload tags.

Template Helpers

With Jinja2 templates registered (via ViteProvider), three globals are available:

vite(entrypoint)

Generates <script type="module"> and <link rel="stylesheet"> tags plus <link rel="modulepreload"> preloads for the given entry point:

html
{# templates/index.html #}
{{ vite('resources/js/app.tsx') }}

Multiple entry points:

html
{{ vite(['resources/js/app.tsx', 'resources/css/admin.css']) }}

vite_asset(path)

Returns the public URL for a non-entry-point asset (images, fonts, etc.):

html
<img src="{{ vite_asset('resources/images/logo.png') }}">

vite_react_refresh()

Injects the React Fast Refresh preamble. Required for React HMR. Must appear before vite():

html
{{ vite_react_refresh() }}
{{ vite('resources/js/app.tsx') }}

In production mode, vite_react_refresh() returns an empty string — safe to always include.

CSP Nonce

python
vite = app.make("vite")
nonce = vite.use_csp_nonce()   # generates a random nonce
# pass nonce to template context, set it in your CSP header

All generated script and link tags will include the nonce attribute.

Custom Asset URL Resolver

Override how asset URLs are built (e.g., to add a CDN prefix dynamically):

python
vite = app.make("vite")
vite.create_asset_paths_using(lambda path: f"https://cdn.example.com/{path}")

SRI Integrity

The manifest chunk key "integrity" is read by default and included as the integrity attribute on generated tags. Change the key or disable it:

python
vite.use_integrity_key("sri")   # use a different key
vite.use_integrity_key(False)   # disable integrity attributes