Static Props¶
Applications frequently need build-time or startup-time configuration constants in the frontend — such as public feature flags, application version metadata, OAuth client IDs, or regional limits — without making an extra HTTP request on page load or maintaining duplicate .env files.
ViteConfig(static_props=...) solves this by serializing a Python dictionary (including msgspec.Struct, dataclass, or Pydantic models) into .litestar.json, generating TypeScript definitions in static-props.ts, and exposing the values through the Vite virtual module virtual:litestar-static-props.
Static Props vs. Inertia Shared Props¶
| Mechanism | Evaluation Time | Works In | Best For |
|---|---|---|---|
ViteConfig.static_props |
Startup / Build time | All modes (spa, hybrid, template, framework) |
Public feature flags, app name/version, public DSNs, static tier limits |
InertiaConfig.extra_static_page_props |
Every Inertia HTTP response | mode="hybrid" only |
Static page props consumed via Inertia usePage().props |
inertia.share(connection, key, val) |
Per-request | mode="hybrid" only |
Current authenticated user, request permissions, flash messages |
Warning
Build-Time & Startup-Only Boundary:
1. Never place secrets (database URLs, private API keys, signing secrets) in static_props — values are bundled into client-side JavaScript.
2. static_props are written to .litestar.json at Python startup (set_environment) and litestar assets generate-types, and read by litestar-vite-plugin when Vite starts or runs vite build. For values that change per-request or at runtime without rebuilding assets, use an API endpoint or Inertia's share().
Defining Static Props in Python¶
Pass any JSON-serializable dictionary or msgspec.Struct values to ViteConfig(static_props=...):
"""Build-time Static Props injected into the Vite virtual module bridge."""
from __future__ import annotations
from litestar import Litestar
from msgspec import Struct
from litestar_vite import RuntimeConfig, TypeGenConfig, ViteConfig, VitePlugin
class PublicFeatureFlags(Struct, frozen=True, gc=False):
"""Typed feature flags serialized into ``.litestar.json`` at startup."""
enable_billing_v2: bool
support_email: str
max_upload_mb: int
def create_app() -> Litestar:
"""Create a Litestar application exposing build-time static props to Vite."""
flags = PublicFeatureFlags(enable_billing_v2=True, support_email="support@example.com", max_upload_mb=50)
vite_config = ViteConfig(
mode="spa",
dev_mode=True,
static_props={"appName": "Billing Portal", "features": flags},
runtime=RuntimeConfig(start_dev_server=False),
types=TypeGenConfig(generate_sdk=False, generate_routes=True),
)
return Litestar(plugins=[VitePlugin(config=vite_config)])
def main() -> None:
"""Verify static props are normalized on ``ViteConfig``."""
app = create_app()
vite_plugin = app.plugins.get(VitePlugin)
assert vite_plugin.config.static_props["appName"] == "Billing Portal"
__all__ = ("PublicFeatureFlags", "create_app", "main")
Consuming Static Props in TypeScript¶
When TypeGenConfig runs, Litestar Vite generates src/generated/static-props.ts with strongly typed interfaces for your static_props keys and declares the virtual:litestar-static-props module:
import staticProps, { appName, features } from "virtual:litestar-static-props";
console.log(appName);
if (features.enable_billing_v2) {
console.log(`Max upload: ${features.max_upload_mb} MB`);
}
export { staticProps };
Both default import (import staticProps from "virtual:litestar-static-props") and named top-level property imports (import { appName, features } from "virtual:litestar-static-props") are supported out of the box by litestar-vite-plugin.
TypeScript Ambient Declaration¶
If your tsconfig.json does not automatically include src/generated/static-props.ts, reference the built-in virtual module types in src/env.d.ts (or src/vite-env.d.ts):