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