React¶
React integration with Litestar Vite provides a modern development experience with Hot Module Replacement (HMR) and optimized production builds.
Quick Start¶
litestar assets init --template react
This creates a React 18+ project with TypeScript support.
Project Structure¶
React applications use SPA mode - Vite serves the index.html directly:
my-app/
├── app.py # Litestar backend (API only)
├── index.html # Vite entry point (root level)
├── package.json
├── vite.config.ts
├── tsconfig.json
└── src/
├── main.tsx # React entry point
├── App.tsx # Root component
└── app.css
Backend Setup¶
In SPA mode, Litestar serves only your API endpoints. The VitePlugin handles serving the frontend automatically:
# VitePlugin with mode="spa" automatically:
# - Registers catch-all route for index.html
# - Generates typed route helpers (routes.ts) when types are enabled
vite = VitePlugin(
config=ViteConfig(
mode="spa",
dev_mode=DEV_MODE,
paths=PathConfig(root=here),
types=TypeGenConfig(), # generate_sdk=True is the default
runtime=RuntimeConfig(port=5001),
)
)
app = Litestar(route_handlers=[LibraryController], plugins=[vite], debug=True)
Key points:
mode="spa"tells Vite to serveindex.htmlfor non-API routesNo
template_configneeded - Jinja is not used in SPA modeTypeGenConfig()enables TypeScript type generation from OpenAPI
Vite Configuration¶
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import litestar from "litestar-vite-plugin"
import { defineConfig } from "vite"
export default defineConfig({
plugins: [
tailwindcss(),
react(),
litestar({
input: ["src/main.tsx"],
resourceDir: "src",
}),
],
})
Key configuration:
input- Entry point(s) for your applicationresourceDir- Source directory (explicitly set tosrc)The plugin auto-reads
assetUrl,bundleDirfrom.litestar.json(generated by Python)
HTML Entry Point¶
In SPA mode, index.html lives at the project root and uses standard Vite syntax:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>react</title>
</head>
<body>
<div id="root"></div>
<!-- Vite transforms this path based on the configured base -->
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Note
Unlike template mode, SPA mode doesn’t use Jinja helpers like {{ vite() }}.
Vite processes the HTML directly.
React Component¶
import { useState, useEffect } from "react";
function App() {
const [message, setMessage] = useState("");
useEffect(() => {
fetch("/api/summary")
.then((res) => res.json())
.then((data) => setMessage(data.headline));
}, []);
return (
<div>
<h1>React + Litestar</h1>
<p>{message}</p>
</div>
);
}
export default App;
Running¶
# Recommended: Litestar proxies Vite automatically in dev mode
litestar run --reload
# Alternative: Two-process setup
litestar assets serve # Vite dev server
litestar run --reload # Backend only (in another terminal)
Type Generation¶
With types=TypeGenConfig() enabled, run:
litestar assets generate-types
This generates TypeScript types from your OpenAPI schema. See Type Generation for more details.
See Also¶
Inertia.js - React with Inertia.js for server-side routing
Type Generation - TypeScript type generation