Askr documentation
Routing & Data

Routing

Define typed routes, layouts, navigation, loaders, policies, and metadata.

Example

Register a route once and let the same registry drive browser navigation, SSR, and static generation.

import { createRouteRegistry, group, route } from '@askrjs/askr/router';

export const registry = createRouteRegistry(() => {
  group({ layout: AppLayout }, () => {
    route('/', HomePage);
  route('/projects/{projectId}', ProjectPage);
  });
});

Published props

Generated from the TypeScript declarations shipped by the installed package. Named types in the Type column define the accepted values.

LinkProps

Import from @askrjs/askr/router.

PropTypeDefaultDescription
aria-currentaria-current?: "time" | "page" | "step" | "location" | "date" | "true" | "false" | undefined;—Optional aria-current attribute for indicating current page/location. Use "page" for the current page in navigation.
aria-labelaria-label?: string | undefined;—Optional aria-label for accessibility when link text isn't descriptive enough.
childrenchildren?: RenderableChild;——
classclass?: string | undefined;——
hrefhref?: string | undefined;——
onClickonClick?: ((event: MouseEvent) => void) | undefined;——
onPressonPress?: ((event: Event) => void) | undefined;——
relrel?: string | undefined;—Optional rel attribute for link relationships. Common values: "noopener", "noreferrer", "nofollow"
targettarget?: string | undefined;—Optional target attribute. Use "_blank" for new tab/window.
toto?: RouteDestination | undefined;——

ResolveProps

Import from @askrjs/askr/router.

PropTypeDefaultDescription
childrenchildren: (value: T) => RenderableChild;——
pendingpending?: RenderableChild;——
rejectedrejected?: RenderableChild | ((error: unknown) => RenderableChild);——
valuevalue: Deferred<T>;——

Route registry

Every route in an Askr app is declared through createRouteRegistry(), which takes a definition function and returns a RouteRegistry built by calling route(), page(), group(), index(), and fallback() inside that function. The registry is an ordinary value: export it, then hand it to createSPA, hydrateSPA, createStaticGen, or renderToString, so client rendering, hydration, SSG, and SSR all read the same declaration. Because nothing is stored globally, two registries can coexist — which is what lets a static build settle its own route tree without disturbing the one the browser boots from, and what keeps a server rendering concurrent requests off shared mutable state.

Route groups

group(options, fn) nests a block of route declarations under a shared layout and shared access rules without repeating them on every child route. The layout you pass in GroupHelperOptions wraps whatever the group renders, and auth/policies on the group apply to every route declared inside its callback. Groups compose: nesting one group inside another builds up a layoutChain and a merged set of policies that Askr walks top-down when it resolves a request, so a route three groups deep still only needs to declare what's specific to it.

A navigation in Askr resolves through resolveRouteRequest(), which matches the target against the app's explicit RouteRegistry and returns either a RouteRenderResult, an AccessRedirectDecision, an AccessDenyDecision, or null if nothing matches. That result already reflects any policy checks — redirects and denials are decided before a component ever renders, not caught afterward. Each RouteContext handed through the pipeline carries an AbortSignal, so loaders and preload functions tied to a route that gets superseded by a newer navigation can be cancelled instead of racing to finish and clobber the current view.

Delivery modes

RouteMode is one of 'spa', 'ssr', or 'ssg', and it's threaded through RouteContext so a loader or a policy can behave differently depending on how the current request is being served. The same route declarations work across all three modes — you don't write separate route trees for server rendering versus the client. SSG specifically leans on the entries option in RouteOptions, which returns the list of param combinations to pre-render as static pages at build time.