Definitions and Layouts
Declare routes, nested layouts, and groups in one typed registry you can read and enumerate.
Example
const registry = createRouteRegistry(() => {
group({ layout: AppLayout }, () => {
route('/', HomePage);
route('/projects/{projectId}', ProjectPage);
});
});Route definitions
`route(path, Component, options?)` is the building block for a single URL: it returns a typed `RouteRef` you can later pass to `to()` for building destinations, and it accepts a `RouteOptions` object for loaders, policies, search-param schemas, and metadata. `page(path, Component, fn)` is the nested-route sibling — it declares a route at `path` and opens a child definition scope, so pages under it can add their own sub-routes or a layout. Both infer route params from the path string itself: writing `route('/posts/{slug}', ...)` gives the component a typed `slug: string` prop with no manual generic annotation needed.
Groups and layouts
A layout is just a component with a `children` prop, attached to a group via `GroupHelperOptions.layout` or to a page via the layout argument on `page()`. Askr stores it as a `LayoutScopeRecord` and composes it automatically at render time — you never call the layout component yourself. Layout composition happens outside the page chain: pages inside a group render first through `Outlet`, and the layout wraps that result, so a loading state or error inside a page doesn't require the layout to know anything about it.
Nested pages
`page()` lets a route own child routes: the `fn` argument is a definition callback where you call `route()` or nest further `page()` calls scoped under that parent path. Each nested route contributes to the same `RouteRecord.segments` matching logic, and Askr ranks routes by specificity so a literal segment like `/posts/new` wins over a param segment like `/posts/{id}` when both could match. `index(Component, options?)` fills the special case of "what renders at this path with nothing appended" — the default child when a parent route is visited directly.
Fallback routes
`fallback(Component)` registers the component Askr renders when no other route matches, and it's marked internally with `isFallback: true` on its `RouteRecord` so the router treats it distinctly from an ordinary catch-all. You get one fallback per scope, not one per `RouteRegistry` overall — a root-level `fallback()` is your app's 404 page, and each `page()` can additionally declare its own `fallback()` scoped to that page's own path prefix (nesting one inside a `group()` instead of directly in a page scope throws). It's meant for 404-style pages, not a general-purpose wildcard route — if you need a wildcard that still participates in normal matching and layout composition, use a `*` or `{*splat}` path segment on a regular `route()` instead.