Routing & Navigation¶
How litestar-vite routing compares to Laravel/Ziggy and works with Inertia’s standard APIs.
See also
Official Inertia.js docs: Links | Manual Visits
Key Differences from Laravel/Ziggy¶
If you’re coming from Laravel with Ziggy, here’s what’s different:
Feature |
Laravel/Ziggy |
litestar-vite |
|---|---|---|
Route helper |
Global |
Imported |
Inertia router |
Monkey-patched with Ziggy |
Unmodified, standard Inertia |
Plain URLs |
Work but bypass types |
First-class support |
Type safety |
Optional (TypeScript) |
Full inference from Python |
The key principle: litestar-vite provides type-safe route helpers as optional utilities, not as a requirement. Inertia’s standard router APIs work perfectly with plain URL strings.
Plain URLs Work Everywhere¶
You are not required to use the route() helper. Plain URL strings work with all Inertia APIs:
import { Link } from "@inertiajs/react";
// Both are valid:
<Link href="/users">Users</Link>
<Link href={route("users")}>Users</Link>
import { router } from "@inertiajs/react";
// Both are valid:
router.visit("/users/123");
router.visit(route("user-profile", { userId: 123 }));
import { router } from "@inertiajs/react";
// All standard Inertia methods work with plain URLs:
router.get("/users");
router.post("/users", { data: { name: "John" } });
router.put("/users/123", { data: { name: "Jane" } });
router.delete("/users/123");
Using the Route Helper¶
The route() helper provides optional type safety for route names and parameters:
import { route } from "@/generated/routes";
// Type-safe route names (autocomplete + compile-time checking)
const url = route("user-profile", { userId: 123 });
// TypeScript errors on invalid routes
const url = route("invalid-route"); // Error: Route not found
// TypeScript errors on missing parameters
const url = route("user-profile"); // Error: Missing userId
Comparison Examples¶
Here’s the same navigation written two ways:
1. Plain URLs (Always Works)
import { Link } from "@inertiajs/react";
import { router } from "@inertiajs/react";
// Link
<Link href="/users/123">View User</Link>
// Programmatic navigation
router.visit("/users/123");
router.post("/users", { data: { name: "John" } });
2. With route() Helper (Type-Safe)
import { Link } from "@inertiajs/react";
import { router } from "@inertiajs/react";
import { route } from "@/generated/routes";
// Link - route() returns a string URL
<Link href={route("user-profile", { userId: 123 })}>View User</Link>
// Programmatic navigation - standard Inertia router with type-safe URLs
router.visit(route("user-profile", { userId: 123 }));
router.post(route("users"), { data: { name: "John" } });
The route() helper just returns a plain string, so it works directly with Inertia’s
standard router - no special wrappers needed.
Global Route (Ziggy-Style)¶
For a more Laravel/Ziggy-like experience, you can enable global registration of route():
from litestar_vite.config import TypeGenConfig
ViteConfig(
types=TypeGenConfig(
global_route=True, # Register route() on window
),
)
When enabled, the generated routes.ts includes:
// Automatically added at end of routes.ts
if (typeof window !== "undefined") {
window.route = route
}
Now you can use route() without imports:
// No import needed!
<Link href={window.route("user-profile", { userId: 123 })}>View User</Link>
// Or in vanilla JS
router.visit(window.route("users"));
Tip
For full TypeScript support with the global, add to your global.d.ts:
declare const route: typeof import("@/generated/routes").route
This gives you autocomplete even without importing.
Note
The default is global_route=False because explicit imports are better for:
Tree-shaking: Unused routes can be eliminated
Explicitness: Clear where
route()comes fromTesting: Easier to mock in unit tests
Interoperability¶
The route() helper returns a plain string, so it works seamlessly with:
Inertia’s
<Link>componentInertia’s
router.visit(),router.get(),router.post(), etc.Standard
fetch()callsAny function expecting a URL string
import { route } from "@/generated/routes";
const url = route("user-profile", { userId: 123 });
console.log(typeof url); // "string"
console.log(url); // "/users/123"
// Works with anything expecting a string
fetch(url);
window.location.href = url;
router.visit(url);
Migration from Laravel/Ziggy¶
If you’re migrating from Laravel with Ziggy:
Replace the global: Change
route("name")toimport { route } from "@/generated/routes"Update imports: The route helper is imported, not global
Keep your URLs: Plain URLs continue to work - you can migrate incrementally
// Before (Laravel/Ziggy - global)
router.visit(route("users.show", { user: 123 }));
// After (litestar-vite - imported)
import { route } from "@/generated/routes";
router.visit(route("user-profile", { userId: 123 }));
// Or just use plain URLs (also valid!)
router.visit("/users/123");
Route Naming Conventions¶
litestar-vite uses kebab-case for route names by default (converted from Python function names):
@get("/users/{user_id}", component="UserProfile")
async def user_profile(user_id: int) -> dict:
... # Route name: "user-profile"
@get("/users", component="Users")
async def list_users() -> dict:
... # Route name: "list-users"
This differs from Laravel’s dot notation (users.show), but you can customize route names:
@get("/users/{user_id}", component="UserProfile", name="users.show")
async def user_profile(user_id: int) -> dict:
... # Route name: "users.show" (custom)
See Also¶
Links - Link component and navigation helpers
TypeScript Integration - TypeScript integration overview
Type Generation - Route type generation config
Inertia.js Manual Visits - Official navigation docs