Nuxt¶
Nuxt 3+ integration with Litestar Vite for universal SSR applications.
Quick Start¶
litestar assets init --template nuxt
This creates a Nuxt 3 project with TypeScript support and SSR capabilities.
Project Structure¶
Nuxt applications use the Nuxt module for seamless integration:
my-app/
├── app.py # Litestar backend
├── package.json
├── nuxt.config.ts # Nuxt configuration with Litestar module
├── tsconfig.json
├── app.vue # Root component
├── pages/
│ └── index.vue # Pages (file-based routing)
├── composables/
│ └── useApi.ts # Composables for API calls
└── generated/ # Generated types from OpenAPI
Backend Setup¶
"""Nuxt example - shared "Library" backend for Nuxt SSR frontend.
Nuxt runs as an SSR server. In dev mode, Litestar proxies all non-API
routes to the Nuxt dev server. In production, run Nuxt and Litestar
as separate services behind a reverse proxy.
All examples in this repository expose the same backend:
- `/api/summary` - overview + featured book
- `/api/books` - list of books
- `/api/books/{book_id}` - single book
Dev mode (default):
litestar --app-dir examples/nuxt run
Production (two services behind reverse proxy):
# Terminal 1: Nuxt SSR server
litestar --app-dir examples/nuxt assets build
litestar --app-dir examples/nuxt assets serve
# Terminal 2: Litestar API server
VITE_DEV_MODE=false litestar --app-dir examples/nuxt run --port 8001
"""
import os
from pathlib import Path
from litestar import Controller, Litestar, get
from litestar.exceptions import NotFoundException
from msgspec import Struct
from litestar_vite import PathConfig, RuntimeConfig, TypeGenConfig, ViteConfig, VitePlugin
here = Path(__file__).parent
DEV_MODE = os.getenv("VITE_DEV_MODE", "true").lower() in {"true", "1", "yes"}
class Book(Struct):
id: int
title: str
author: str
year: int
tags: list[str]
class Summary(Struct):
app: str
headline: str
total_books: int
featured: Book
BOOKS: list[Book] = [
Book(id=1, title="Async Python", author="C. Developer", year=2024, tags=["python", "async"]),
Book(id=2, title="Type-Safe Web", author="J. Dev", year=2025, tags=["typescript", "api"]),
Book(id=3, title="Frontend Patterns", author="A. Designer", year=2023, tags=["frontend", "ux"]),
]
def _get_book(book_id: int) -> Book:
for book in BOOKS:
if book.id == book_id:
return book
raise NotFoundException(detail=f"Book {book_id} not found")
def _get_summary() -> Summary:
"""Build summary data."""
return Summary(
app="litestar-vite library", headline="One backend, many frontends", total_books=len(BOOKS), featured=BOOKS[0]
)
class LibraryController(Controller):
"""Library API controller."""
@get("/api/summary")
async def summary(self) -> Summary:
"""Overview endpoint used across all examples."""
return _get_summary()
@get("/api/books")
async def books(self) -> list[Book]:
"""Return all books."""
return BOOKS
@get("/api/books/{book_id:int}")
async def book_detail(self, book_id: int) -> Book:
"""Return a single book by id."""
return _get_book(book_id)
vite = VitePlugin(
config=ViteConfig(
mode="ssr", # SSR mode: proxy in dev, Node serves HTML in prod
dev_mode=DEV_MODE,
paths=PathConfig(root=here),
types=TypeGenConfig(output=Path("generated"), generate_zod=True),
# Fixed port for E2E tests - can be removed for local dev or customized for production
runtime=RuntimeConfig(port=5041),
)
)
app = Litestar(route_handlers=[LibraryController], plugins=[vite], debug=True)
Key points:
mode="framework"enables meta-framework integration mode (aliases:mode="ssr"/mode="ssg")ExternalDevServerdelegates dev server to NuxtTypeGenConfigenables type generation for Nuxt composables
Nuxt Configuration¶
import tailwindcss from "@tailwindcss/vite"
// Litestar manages the dev server port via VITE_PORT and runtime config.
// The Nuxt module reads the port automatically - no hardcoding needed.
// LITESTAR_PORT is the backend API server port (default 8000).
const LITESTAR_PORT = process.env.LITESTAR_PORT ?? "8000"
export default defineNuxtConfig({
compatibilityDate: "2024-11-01",
devtools: { enabled: true },
modules: ["litestar-vite-plugin/nuxt"],
vite: {
plugins: [tailwindcss()],
},
litestar: {
// API proxy points to the Litestar backend (apiPrefix defaults to "/api")
apiProxy: `http://127.0.0.1:${LITESTAR_PORT}`,
verbose: true,
types: {
output: "generated",
openapiPath: "generated/openapi.json",
routesPath: "generated/routes.json",
},
},
})
The Litestar module provides:
API proxy configuration (
apiProxy)Type generation integration
Automatic port coordination with Litestar backend
Runtime Configuration¶
Nuxt reads runtime configuration from VITE_PORT and LITESTAR_PORT environment variables set by Litestar:
// In composables or pages
const config = useRuntimeConfig()
const apiUrl = config.public.apiProxy // http://localhost:8000
const apiPrefix = config.public.apiPrefix // /api
API Integration¶
Using Composables¶
// composables/useApi.ts
import type { Summary } from '~/generated/types.gen'
import { route } from '~/generated/routes'
export async function useSummary() {
const { data, error } = await useFetch<Summary>(
route('summary'),
{ key: 'summary' }
)
return { data, error }
}
Server Routes (SSR)¶
For server-side API calls during SSR, create a server middleware:
// server/api/[...].ts
export default defineEventHandler((event) => {
const config = useRuntimeConfig()
return proxyRequest(event, config.public.apiProxy + event.path)
})
Client-Side Fetch¶
<script setup lang="ts">
import type { User } from '~/generated/types.gen'
import { route } from '~/generated/routes'
const { data: users } = await useFetch<User[]>(route('users:list'))
</script>
<template>
<div>
<h1>Users</h1>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</div>
</template>
Running¶
# Recommended: Litestar manages both servers
litestar run --reload
# Alternative: Run separately
litestar assets serve --production # Nuxt SSR server
litestar run --reload # Backend API (in another terminal)
Type Generation¶
With types=TypeGenConfig() enabled in Python:
litestar assets generate-types
This generates TypeScript types in generated/ (path configured in nuxt.config.ts).
Deployment¶
For production:
Build Nuxt:
litestar assets buildServe both apps:
litestar assets serve --production # Nuxt SSR server litestar run # Backend API
The --production flag runs npm run serve which starts Nuxt’s production server.
See Also¶
Type Generation - TypeScript type generation