Skip to content

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

OptionTypeDescription
pathstringURL 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
metaobject | (context) => objectRoute metadata (title, description, etc.)
rollbackbooleanRevert navigation on loader failure
keepAlivebooleanKeep the component mounted when navigating away
dependenciesRecord<string, (params, mesh) => Promise>Parallel data dependencies
errorRecovery{ retry, retryDelay, fallbackComponent, onError }Auto-retry on loader failure
offlineobjectOffline support configuration
childrenRouteDefinition[]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

PatternMatchesExample
/productsExact/products
/products/:idParameter/products/123
/files/*Catch-all/files/docs/readme.md
*EverythingAny unmatched path

Register the Router

ts
const router = mesh.router(routes, {
  basename: "/app",
  defaultPendingMs: 200,
  defaultPendingMinMs: 300,
  scrollRestoration: true,
  preload: "intent"
});
OptionTypeDefaultDescription
basenamestring"/"URL prefix for all routes
defaultPendingMsnumber200Delay before showing pending UI
defaultPendingMinMsnumber300Minimum time to show pending UI
scrollRestorationbooleanfalseRestore 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

Released under the MIT License.