Migration Guide (v0.15)¶
This guide helps you upgrade to v0.15.0 from earlier versions.
Note
v0.15 includes new features and improvements with minimal breaking changes. Most applications can upgrade by updating dependencies and adding new features incrementally.
Breaking Changes¶
Configuration Structure¶
v0.15 introduces nested configuration for better organization:
Before v0.15:
ViteConfig(
bundle_dir="public",
resource_dir="resources",
hot_reload=True,
port=5173,
)
v0.15+:
from litestar_vite import ViteConfig
from litestar_vite.config import PathConfig, RuntimeConfig
ViteConfig(
paths=PathConfig(
bundle_dir="public",
resource_dir="resources",
),
runtime=RuntimeConfig(
hot_reload=True,
port=5173,
),
)
Template Engine Removal¶
The ViteTemplateEngine has been removed. Use the standard Litestar Jinja engine:
from litestar.contrib.jinja import JinjaTemplateEngine
from litestar.template.config import TemplateConfig
app = Litestar(
template_config=TemplateConfig(
engine=JinjaTemplateEngine(directory="templates")
),
plugins=[VitePlugin(...)]
)
CLI Command Group¶
Commands are now under the assets group:
litestar assets init- Initialize a new projectlitestar assets build- Build assetslitestar assets serve- Serve assetslitestar assets generate-types- Generate TypeScript typeslitestar assets doctor- Diagnose configuration issues (use--show-configto print effective configs,--fixto apply safe auto-fixes; restarting the app rewrites.litestar.jsonwhenruntime.set_environment=True)litestar assets deploy- Deploy assets to CDNlitestar assets status- Check Vite integration status
Proxy Mode Default Change¶
The proxy_mode now has smarter auto-detection:
Default is still
"vite"(whitelist mode - proxies Vite assets only)When
ExternalDevServeris configured, automatically switches to"proxy"mode
Impact:
If you were relying on implicit behavior with external dev servers (Angular CLI, Next.js), the mode now auto-configures correctly. No action needed in most cases.
To explicitly set the mode:
from litestar_vite import ViteConfig, RuntimeConfig
ViteConfig(
runtime=RuntimeConfig(
proxy_mode="vite", # Explicit whitelist mode
)
)
Mode Aliases¶
v0.15 introduces mode aliases for convenience:
Alias |
Normalized To |
Use Case |
|---|---|---|
|
|
Inertia.js SPA with server-side routing |
|
|
Static Site Generation (alias for framework mode) |
Recommended usage:
# For Inertia.js applications
ViteConfig(mode="inertia")
# For meta-frameworks (Astro, etc.)
ViteConfig(mode="framework") # or aliases: "ssr" / "ssg"
New Features¶
Vite 7.x Support¶
v0.15 adds support for Vite 7.x while maintaining compatibility with Vite 6.x.
Package.json Update:
{
"peerDependencies": {
"vite": "^6.0.0 || ^7.0.0"
}
}
Migration:
Upgrade Vite in your frontend:
# npm
npm install -D vite@^7.0.0
# yarn
yarn add -D vite@^7.0.0
# pnpm
pnpm add -D vite@^7.0.0
# bun
bun add -D vite@^7.0.0
Inertia v2 Features¶
v0.15 adds support for Inertia.js v2 features:
History Encryption¶
Enable browser history encryption globally:
from litestar_vite.inertia import InertiaConfig
InertiaConfig(
encrypt_history=True, # New in v0.15
)
This prevents sensitive data from being visible in browser history after logout. See: History Encryption
New Helper:
from litestar_vite.inertia import clear_history
@post("/logout")
async def logout(request: Request) -> InertiaRedirect:
request.session.clear()
clear_history(request) # Regenerate encryption key
return InertiaRedirect(request, redirect_to="/login")
Deferred Props with Grouping¶
The new defer() helper supports grouped deferred props:
from litestar_vite.inertia import defer, InertiaResponse
@get("/dashboard", component="Dashboard")
async def dashboard() -> InertiaResponse:
return InertiaResponse({
"user": current_user,
# Deferred props loaded after page render
"teams": defer("teams", lambda: Team.all(), group="attributes"),
"projects": defer("projects", lambda: Project.all(), group="attributes"),
"permissions": defer("permissions", lambda: Permission.all()),
})
Props in the same group are fetched together in a single request.
Merge Props¶
New merge() helper for combining data during partial reloads:
from litestar_vite.inertia import merge, InertiaResponse
@get("/posts", component="Posts")
async def list_posts(page: int = 1) -> InertiaResponse:
posts = await Post.paginate(page=page, per_page=20)
return InertiaResponse({
# Append new posts to existing list
"posts": merge("posts", posts.items),
})
Supports strategies: "append" (default), "prepend", "deep".
New Inertia Helpers¶
Helper |
Description |
|---|---|
|
Set validation errors in session |
|
Filter props to include only specified keys |
|
Filter props to exclude specified keys |
|
Create infinite scroll configuration |
Example:
from litestar_vite.inertia import error, only, scroll_props
# Validation errors
@post("/users")
async def create_user(request: Request, data: UserCreate) -> InertiaResponse:
if not data.email:
error(request, "email", "Email is required")
return InertiaRedirect(request, "/users/new")
# Prop filtering
@get("/users", component="Users")
async def list_users() -> InertiaResponse:
return InertiaResponse(
{"users": [...], "teams": [...], "stats": [...]},
prop_filter=only("users"), # Only send users prop
)
# Infinite scroll
@get("/posts", component="Posts")
async def list_posts(page: int = 1) -> InertiaResponse:
posts = await Post.paginate(page=page, per_page=20)
return InertiaResponse(
{"posts": merge("posts", posts.items)},
scroll_props=scroll_props(
current_page=page,
previous_page=page - 1 if page > 1 else None,
next_page=page + 1 if posts.has_more else None,
),
)
Automatic Pagination Support¶
v0.15 automatically detects pagination containers and generates scroll props:
from litestar_vite.inertia import InertiaResponse
@get("/posts", component="Posts")
async def list_posts(limit: int = 10, offset: int = 0) -> InertiaResponse:
# Returns OffsetPagination with items, total, limit, offset
posts = await Post.paginate(limit=limit, offset=offset)
# Automatically unwraps items and generates scroll_props
return InertiaResponse({"posts": posts})
Supports:
- litestar.pagination.OffsetPagination
- litestar.pagination.ClassicPagination
- advanced_alchemy.service.OffsetPagination
- Any object with items attribute and pagination metadata
Inertia Type Generation¶
New type generation options for Inertia page props:
InertiaTypeGenConfig:
from litestar_vite.config import InertiaConfig, InertiaTypeGenConfig
InertiaConfig(
type_gen=InertiaTypeGenConfig(
include_default_auth=True, # Include User/AuthData interfaces
include_default_flash=True, # Include FlashMessages interface
),
)
Default Types (when ``include_default_auth=True``):
export interface User {
id: string
email: string
name?: string | null
}
export interface AuthData {
isAuthenticated: boolean
user?: User
}
Extending Defaults:
// Extend via module augmentation
declare module 'litestar-vite-plugin/inertia' {
interface User {
avatarUrl?: string | null
roles: Role[]
teams: Team[]
}
}
Custom User Models:
If your user model has different required fields (e.g., uuid instead of id):
InertiaConfig(
type_gen=InertiaTypeGenConfig(
include_default_auth=False, # Disable defaults
),
)
Then define your own User interface in TypeScript:
declare module 'litestar-vite-plugin/inertia' {
interface User {
uuid: string
username: string
}
}
TypeScript Enhancements¶
Enhanced TypeGenConfig:
New options for type generation:
Option |
Type |
Description |
|---|---|---|
|
|
Generate Inertia page props types (default: |
|
|
Path for page props metadata JSON |
|
|
Path for typed routes TypeScript file |
|
|
Fallback value type for untyped dict/list in Inertia page props (default: |
|
|
Map props type names to TypeScript import paths for schemas excluded from OpenAPI |
Example:
from litestar_vite.config import TypeGenConfig
ViteConfig(
types=TypeGenConfig(
output=Path("src/generated"),
generate_page_props=True, # Enable page props generation
page_props_path=Path("src/generated/inertia-pages.json"),
routes_ts_path=Path("src/generated/routes.ts"),
),
)
TypeScript Helpers:
New TypeScript utilities in litestar-vite-plugin:
HTMX Utilities:
import {
addDirective,
registerHtmxExtension,
setHtmxDebug,
swapJson,
} from 'litestar-vite-plugin/helpers'
// Add HTMX directive
addDirective('my-directive', (element) => { ... })
// Register HTMX extension
// Note: Registration is explicit (no auto-registration)
registerHtmxExtension()
// Enable HTMX debug mode
setHtmxDebug(true)
// Swap JSON response into element
swapJson(element, { data: 'value' })
Inertia Helpers:
import { unwrapPageProps } from 'litestar-vite-plugin/inertia-helpers'
// Unwrap page props from Inertia response
const props = unwrapPageProps(pageData)
Runtime Configuration¶
New RuntimeConfig Options:
Option |
Type |
Description |
|---|---|---|
|
|
Enable HTTP/2 for proxy connections (default: |
|
|
Control dev server startup (default: |
HTTP/2 Support:
ViteConfig(
runtime=RuntimeConfig(
http2=True, # Better multiplexing for proxy requests
),
)
HTTP/2 improves proxy performance by allowing multiple requests over a single connection. WebSocket traffic (HMR) uses a separate connection and is unaffected.
SPA Configuration¶
New SPAConfig Options:
Option |
Type |
Description |
|---|---|---|
|
|
Cache transformed HTML in production (default: |
Example:
from litestar_vite.config import SPAConfig
ViteConfig(
spa=SPAConfig(
inject_csrf=True,
cache_transformed_html=True, # Cache for performance
),
)
Note: Caching is automatically disabled when inject_csrf=True because CSRF tokens are per-request.
External Dev Server Enhancements¶
Enhanced configuration for external dev servers (Angular CLI, Next.js, etc.):
Option |
Type |
Description |
|---|---|---|
|
|
URL of external dev server |
|
|
Custom command to start dev server |
|
|
Custom build command |
|
|
Enable HTTP/2 for proxy (default: |
|
|
Enable/disable external proxy (default: |
Example:
from litestar_vite.config import ExternalDevServer
ViteConfig(
runtime=RuntimeConfig(
external_dev_server=ExternalDevServer(
target="http://localhost:4200", # Angular CLI
command=["ng", "serve"],
build_command=["ng", "build"],
http2=True, # Better performance
),
),
)
New CLI Templates¶
v0.15 adds new framework templates for litestar assets init:
Template |
Description |
|---|---|
|
React with React Router 7+ |
|
React with TanStack Router |
|
Svelte 5 with Inertia.js |
Usage:
litestar assets init --template react-router myapp
litestar assets init --template react-tanstack myapp
litestar assets init --template svelte-inertia myapp
Troubleshooting¶
Common Migration Issues¶
Issue: Type Generation Not Working¶
Symptom:
Type generation doesn’t run after upgrading to v0.15.
Solution:
Check that your Python backend is exporting the new metadata files:
# Check for generated files
ls src/generated/inertia-pages.json
ls src/generated/routes.json
If missing, ensure type generation is enabled:
ViteConfig(
types=TypeGenConfig(
generate_page_props=True,
),
)
Issue: Inertia History Encryption Not Working¶
Symptom:
encrypt_history=True doesn’t encrypt history.
Solution:
History encryption is a client-side feature. Ensure you’re using Inertia.js v2:
npm install @inertiajs/react@^2.0.0 # or vue3/svelte
Then update your frontend code to support history encryption.
Issue: Pagination Auto-Detection Conflicts¶
Symptom:
Pagination container is unwrapped but you want the full object.
Solution:
Manually construct the response props:
@get("/posts", component="Posts")
async def list_posts() -> InertiaResponse:
pagination = await Post.paginate(limit=10, offset=0)
# Manually control what's sent
return InertiaResponse({
"items": pagination.items,
"total": pagination.total,
"limit": pagination.limit,
"offset": pagination.offset,
})
Issue: Unknown Mode Error¶
Symptom:
Error about unknown mode when using old mode names.
Solution:
v0.15 supports these modes: spa, template, htmx, hybrid, framework, external.
You can also use aliases: inertia (for hybrid) and ssr / ssg (for framework).
# Recommended for Inertia.js
ViteConfig(mode="inertia")
# Recommended for meta-frameworks
ViteConfig(mode="framework")
Upgrade Checklist¶
☑ |
Task |
|---|---|
☐ |
Update |
☐ |
Migrate to nested configuration ( |
☐ |
Replace |
☐ |
Update CLI commands to use |
☐ |
Upgrade Vite to 6.x or 7.x |
☐ |
Update Inertia.js to v2 (if using Inertia features) |
☐ |
Review proxy mode configuration (usually auto-detected correctly) |
☐ |
Test type generation (run |
☐ |
Run |
☐ |
Run |
Next Steps¶
Review new Inertia v2 features: Inertia.js
Explore type generation: Type Generation
Configure history encryption: History Encryption
Set up pagination: Responses
Getting Help¶
If you encounter issues during migration:
Check the GitHub Issues
Join the Litestar Discord
Review the documentation