Routes
Routes are defined with defineRoutes and registered with mesh.router. Each route has a path pattern, a component, and optional loaders, guards, and metadata.
Define Routes
ts
import { defineRoutes } from "statemesh-core/router";
const routes = defineRoutes([
{
path: "/",
component: () => import("./pages/Home"),
meta: { title: "Home" }
},
{
path: "/products",
component: () => import("./pages/Products"),
children: [
{
path: ":id",
component: () => import("./pages/ProductDetail")
}
]
},
{
path: "/checkout",
component: () => import("./pages/Checkout"),
meta: { requiresAuth: true },
rollback: true
},
{
path: "*",
component: () => import("./pages/NotFound")
}
]);Route Definition Options
| Option | Type | Description |
|---|---|---|
path | string | URL pattern. Supports :param and * catch-all. |
component | () => Promise<Component> | Lazy-loaded component |
loader | (context) => Promise<data> | Data loader. Runs before the component renders. |
beforeLoad | (context) => void | redirect() | Runs before the loader. Can redirect. |
pendingComponent | () => Promise<Component> | Component shown while the loader runs |
errorComponent | () => Promise<Component> | Component shown when the loader fails |
meta | object | (context) => object | Route metadata (title, description, etc.) |
rollback | boolean | Revert navigation on loader failure |
keepAlive | boolean | Keep the component mounted when navigating away |
dependencies | Record<string, (params, mesh) => Promise> | Parallel data dependencies |
errorRecovery | { retry, retryDelay, fallbackComponent, onError } | Auto-retry on loader failure |
offline | object | Offline support configuration |
children | RouteDefinition[] | Nested child routes |
Nested Routes
Children inherit the parent's layout. Use <Outlet /> to render the matched child:
tsx
function ProductsLayout() {
return (
<div>
<h1>Products</h1>
<Outlet /> {/* Renders ProductDetail when /products/:id */}
</div>
);
}Lazy Loading
Components are lazy-loaded by default. The component function returns a Promise:
ts
{
path: "/dashboard",
component: () => import("./pages/Dashboard") // Lazy loaded
}Path Patterns
| Pattern | Matches | Example |
|---|---|---|
/products | Exact | /products |
/products/:id | Parameter | /products/123 |
/files/* | Catch-all | /files/docs/readme.md |
* | Everything | Any unmatched path |
Register the Router
ts
const router = mesh.router(routes, {
basename: "/app",
defaultPendingMs: 200,
defaultPendingMinMs: 300,
scrollRestoration: true,
preload: "intent"
});| Option | Type | Default | Description |
|---|---|---|---|
basename | string | "/" | URL prefix for all routes |
defaultPendingMs | number | 200 | Delay before showing pending UI |
defaultPendingMinMs | number | 300 | Minimum time to show pending UI |
scrollRestoration | boolean | false | Restore scroll position on back/forward |
preload | "intent" | "none" | "none" | Preload on hover/focus |
Important Notes
TIP
Use defineRoutes to get TypeScript type checking on route definitions. It normalizes the tree and validates paths.
WARNING
Catch-all routes (*) should be defined last. They match any unmatched path.
Next Steps
- Navigation — Link, useNavigate, useParams
- Guards & Middleware — Route protection
- Data Loading — Loaders and error recovery
