Operating Modes¶
Every full-stack Python + JavaScript application must answer four architectural questions:
- Who owns the initial HTML shell? (Vite
index.html, Jinja2 template, or an external framework server?) - Who owns URL routing? (Client router, Litestar route handlers, or a meta-framework router?)
- How are Vite
<script>and<link>tags injected? (HTML transform pipeline, Jinja template helpers, or framework middleware?) - How does data cross from Python to the UI? (Typed OpenAPI JSON, Inertia
PageProps, or HTML fragments?)
ViteConfig(mode=...) answers all four questions with a single setting. Use the interactive diagram below to compare the primary operating modes:
Comparison Matrix¶
| Dimension | spa |
hybrid (inertia) |
template (htmx) |
framework (ssr / ssg) |
external |
|---|---|---|---|---|---|
| HTML Shell | index.html transformed by AppHandler |
index.html or Jinja transformed by InertiaPlugin |
Litestar Jinja2 templates | Meta-framework server | External CLI dev server |
| Router | Client router (React Router, Vue Router, TanStack) | Litestar route handlers + Inertia client router | Litestar route handlers (Template / ComponentResponse) |
Meta-framework file router; Litestar serves /api/* |
Angular or external router |
| Asset Tags | Automatic HTML script transform | Automatic transform + data-page JSON script |
Explicit vite_hmr() and vite() in Jinja |
Meta-framework Vite pipeline | External bundler |
| Dev Proxy | proxy_mode="vite" (Vite assets + HMR) |
proxy_mode="vite" (Vite assets + HMR) |
proxy_mode="vite" (Vite assets + HMR) |
proxy_mode="proxy" (all non-API routes) |
proxy_mode="proxy" to external target |
| Data Contract | OpenAPI SDK + route() |
Inertia PageProps + route() |
Jinja context + <litestar-island> |
OpenAPI SDK + route() |
OpenAPI SDK + route() |
Mode Aliases¶
For readability across different frontend stacks, ViteConfig.mode accepts descriptive aliases that normalize to the canonical mode:
"spa"— Single-Page Application (index.htmlcatch-all route served by Litestar)."hybrid"or"inertia"— Inertia.js server-driven SPA."template"or"htmx"— Server-rendered Jinja2 templates, HTMX partials, and<litestar-island>fragments."framework","ssr", or"ssg"— Meta-frameworks (Astro, Nuxt, SvelteKit) where Litestar proxies non-API routes in development."external"— Non-Vite build tools (such as Angular CLIng serve) managed viaRuntimeConfig(external_dev_server=ExternalDevServer(...)).
Configuring Each Mode in Python¶
docs/examples/learn/vite_config_modes.py
"""Comparison of the four ViteConfig operating modes in Litestar Vite."""
from __future__ import annotations
from pathlib import Path
from litestar_vite import InertiaConfig, PathConfig, RuntimeConfig, TypeGenConfig, ViteConfig
def build_spa_config() -> ViteConfig:
"""Configure Single-Page Application (SPA) mode with automatic OpenAPI SDK generation."""
return ViteConfig(
mode="spa",
dev_mode=True,
paths=PathConfig(resource_dir=Path("src"), bundle_dir=Path("dist")),
runtime=RuntimeConfig(start_dev_server=False),
types=TypeGenConfig(generate_sdk=True, generate_routes=True),
)
def build_hybrid_config() -> ViteConfig:
"""Configure Inertia.js v2 Hybrid mode with root HTML shell transformation."""
return ViteConfig(
mode="hybrid",
dev_mode=True,
paths=PathConfig(resource_dir=Path("resources"), bundle_dir=Path("public/build")),
inertia=InertiaConfig(root_template="index.html"),
runtime=RuntimeConfig(start_dev_server=False),
)
def build_template_config() -> ViteConfig:
"""Configure server-driven Jinja2 Template mode with Vite asset helpers."""
return ViteConfig(
mode="template",
dev_mode=True,
paths=PathConfig(resource_dir=Path("resources"), bundle_dir=Path("public/build")),
runtime=RuntimeConfig(start_dev_server=False),
)
def build_framework_config() -> ViteConfig:
"""Configure Meta-Framework mode for Astro, Nuxt, or SvelteKit."""
return ViteConfig(
mode="framework",
dev_mode=True,
runtime=RuntimeConfig(port=4321, start_dev_server=False),
types=TypeGenConfig(generate_sdk=True, generate_routes=True),
)
def main() -> None:
"""Validate all four operating mode configurations."""
assert build_spa_config().mode == "spa"
assert build_hybrid_config().mode == "hybrid"
assert build_template_config().mode == "template"
assert build_framework_config().mode == "framework"
__all__ = ("build_framework_config", "build_hybrid_config", "build_spa_config", "build_template_config", "main")
Mode Auto-Detection¶
When ViteConfig.mode is omitted (mode=None), ViteConfig.__post_init__ resolves the operating mode deterministically:
- If
inertiais enabled (InertiaConfigorinertia=True) androot_templateends with.html->mode="hybrid". - If
inertiais enabled androot_templateis a Jinja template (.j2,.jinja,.jinja2) ->mode="hybrid"with Jinja rendering. - If
Litestar(template_config=...)is registered without Inertia ->mode="template". - If an
index.htmlexists inroot_dir,resource_dir, orpublic_dir->mode="spa".
Tip
Always set mode explicitly (mode="spa", mode="hybrid", mode="template", mode="framework", or mode="external") in production applications so your intent is self-documenting and validated at startup.