Templates¶
Configure the root template for Inertia applications.
See also
Official Inertia.js docs: Server-Side Setup
Root Template¶
The root template is the HTML shell for your Inertia application. It’s rendered on initial page loads with page data embedded.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/static/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title inertia>react-inertia</title>
{{ vite_hmr() }}
{{ vite('resources/main.tsx') }}
</head>
<body>
<div id="app" data-page='{{ inertia | safe }}'></div>
</body>
</html>
Key features:
<title inertia>- Enables dynamic title updates via Inertia’s<Head>component{{ inertia | safe }}- JSON-encoded page props (use| safeto prevent escaping){{ vite_hmr() }}and{{ vite() }}- Vite asset injection
Template Helpers¶
These helpers are automatically available in your templates:
Helper |
Description |
|---|---|
|
Include Vite assets (JS, CSS) |
|
HMR client script (dev mode) |
|
JSON-encoded page props for |
|
Hidden CSRF input field |
|
Raw CSRF token value |
The inertia Helper¶
The {{ inertia | safe }} helper outputs JSON for the data-page attribute:
{
"component": "Dashboard",
"props": {"user": {"name": "Alice"}},
"url": "/dashboard",
"version": "abc123"
}
Important
Always use | safe with the inertia helper to prevent HTML escaping:
<div id="app" data-page='{{ inertia | safe }}'></div>
Without | safe, special characters in props will be escaped, breaking JSON parsing.
Dynamic Titles¶
Add the inertia attribute to <title> for dynamic title support:
<title inertia>Default Title</title>
Then update titles from your components using Inertia’s <Head> component:
import { Head } from '@inertiajs/react';
function Dashboard() {
return (
<>
<Head title="Dashboard - My App" />
{/* page content */}
</>
);
}
SPA Mode (No Templates)¶
In SPA mode, you don’t need Jinja templates. The index.html from
your Vite project is used directly:
ViteConfig(
mode="hybrid", # Auto-detected with inertia=True
inertia=InertiaConfig(spa_mode=True),
)
Your index.html (in resource_dir):
<!DOCTYPE html>
<html>
<head>
<script type="module" src="/resources/main.ts"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
Litestar-Vite automatically injects data-page and CSRF token.
Customizing the App Selector¶
Change the root element selector:
InertiaConfig(
app_selector="#root", # Default: "#app"
)
<div id="root" data-page='{{ inertia | safe }}'></div>
Multiple Templates¶
Use different templates for different sections:
@get("/admin/dashboard", component="Admin/Dashboard")
async def admin_dashboard() -> InertiaResponse:
return InertiaResponse(
content={...},
template_name="admin.html", # Override default
)
Template Organization¶
Recommended structure:
templates/
├── index.html # Main Inertia template
├── admin.html # Admin section template
└── partials/
└── head.html # Shared head content
Using template inheritance:
<!DOCTYPE html>
<html>
<head>
{% block head %}
{{ vite('resources/main.ts') }}
{{ vite_hmr() }}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
{% extends "base.html" %}
{% block body %}
<div id="app" data-page='{{ inertia | safe }}'></div>
{% endblock %}
See Also¶
Configuration - Template configuration options
Vite Integration - Vite asset helpers