Angular¶
Litestar supports two integration approaches for Angular applications:
- Vite-Based (
angulartemplate,mode="spa") — Uses@analogjs/vite-plugin-angulardirectly withlitestar-vite-pluginfor single-port HMR and unified Vite builds. - Angular CLI (
angular-clitemplate,mode="external") — Uses the native Angular CLI (ng serve/ng buildvia@angular/build:application) withExternalDevServerprocess management andTypeGenConfig.
Comparison: Vite vs Angular CLI¶
| Feature | Option 1: Vite (@analogjs/vite-plugin-angular) |
Option 2: Angular CLI (@angular/build) |
|---|---|---|
| Scaffold Template | litestar assets init --template angular |
litestar assets init --template angular-cli |
| Operating Mode | mode="spa" |
mode="external" |
| Build Tool | Vite (litestar-vite-plugin) |
Angular CLI (angular.json + @angular/build:application) |
| Dev Server | Vite HMR proxied through Litestar (:8000) |
ng serve managed via ExternalDevServer |
| Type Generation | Automatic via litestar-vite-plugin |
Automatic via ViteConfig(types=TypeGenConfig(...)) |
| Best For | New fullstack projects wanting unified Vite tooling | Existing Angular CLI workspaces or enterprise ng pipelines |
Vite-Based Angular¶
Quick Start¶
Configuration¶
app.py
from pathlib import Path
from litestar import Litestar, get
from msgspec import Struct
from litestar_vite import PathConfig, TypeGenConfig, ViteConfig, VitePlugin
class Book(Struct):
id: int
title: str
author: str
@get("/api/books", name="books", sync_to_thread=False)
def list_books() -> list[Book]:
"""Return typed book catalog."""
return [Book(id=1, title="Async Python", author="Litestar Team")]
app = Litestar(
route_handlers=[list_books],
plugins=[
VitePlugin(
config=ViteConfig(
mode="spa",
dev_mode=True,
paths=PathConfig(resource_dir=Path("src")),
types=TypeGenConfig(generate_sdk=True, generate_routes=True),
),
),
],
)
Standalone Component with HttpClient and route¶
src/app/books.component.ts
import { Component, inject, type OnInit } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { route } from "../generated/routes";
import type { Book } from "../generated/api";
@Component({
selector: "app-books",
standalone: true,
template: `
<section>
<h2>Books</h2>
<ul>
@for (book of books; track book.id) {
<li>{{ book.title }} — {{ book.author }}</li>
}
</ul>
</section>
`,
})
export class BooksComponent implements OnInit {
private readonly http = inject(HttpClient);
books: Book[] = [];
ngOnInit(): void {
this.http.get<Book[]>(route("books")).subscribe((data) => {
this.books = data;
});
}
}
Angular CLI¶
When using Angular CLI (@angular/build:application and @angular/build:dev-server), configure mode="external" and ExternalDevServer so litestar run starts ng serve and proxies non-API traffic automatically:
app.py
from pathlib import Path
from litestar import Litestar
from litestar_vite import ExternalDevServer, PathConfig, RuntimeConfig, TypeGenConfig, ViteConfig, VitePlugin
app = Litestar(
route_handlers=[],
plugins=[
VitePlugin(
config=ViteConfig(
mode="external",
dev_mode=True,
paths=PathConfig(bundle_dir=Path("dist/browser")),
runtime=RuntimeConfig(
external_dev_server=ExternalDevServer(
target="http://127.0.0.1:4200",
command=["npx", "ng", "serve", "--port", "4200"],
build_command=["npx", "ng", "build"],
),
),
types=TypeGenConfig(
output=Path("src/generated"),
generate_sdk=True,
generate_routes=True,
),
),
),
],
)