API
Every function, component and type @k8ordo/router exports. Things used together sit side by side, and the types come last.
On this page
defineRoutes
Import from @k8ordo/router
Creates the route table. Each key is a path pattern, and each value is a page component or an object grouping pages.
defineRoutes<R extends RoutesRecord>(record: R): Routes<R>Parameters
recordRoutesRecord- The table itself. Every key is a pattern starting with
/.
Returns
Routes<R> — An object holding the table as passed and match, which matches a path against it.
Caveats
- The table is checked when this runs, and a mistake in it is a
TypeError. - Patterns are tried in the order written, and the first that fits wins.
routes.tsexport const routes = defineRoutes({
'/': Home,
'/products': {
layout: ProductsLayout,
children: { '/': ProductList, '/:id': ProductPage },
},
'/*': NotFound,
});Router
Import from @k8ordo/router
Connects the route table to the browser’s navigation and renders the page that fits the current path. Put it once, at the root of an app that renders in the browser.
<Router routes={Routes} />Parameters
routesRoutes- The route table
defineRoutesreturned.
Caveats
- It takes only navigations to paths the table answers, and leaves the rest to the browser.
- Opened at a path the table lacks, it renders nothing.
- It reads the browser’s URL when it mounts, so it cannot render on a server.
Outlet
Import from @k8ordo/router
Marks where, inside a layout, the page it wraps renders.
<Outlet />Caveats
- Rendered outside
<Router>, it throws. Under the framework, a layout renderschildreninstead.
href
Import from @k8ordo/router
Builds the URL a link points at from a pattern and its params.
href<P extends RegisteredNavigablePattern>(
pattern: P,
params?: RegisteredParams<P>,
): stringParameters
patternP- The pattern to link to. With
Registeraugmented, only the table’s linkable patterns are accepted. paramsRegisteredParams<P>- The values of the pattern’s params. Left out for a pattern without params.
Returns
string — A URL for an <a>’s href attribute, with the base path in front when the app is served below one.
Caveats
- Values are encoded with
encodeURIComponent. - A pattern with
/*, a param without a value, or a value with no URL spelling is aTypeErrorat run time.
href('/products'); // '/products'
href('/products/:id', { id: 42 }); // '/products/42'navigateTo
Import from @k8ordo/router
Builds a URL from a pattern and its params, and goes there.
navigateTo<P extends RegisteredNavigablePattern>(
pattern: P,
params?: RegisteredParams<P>,
options?: NavigateToOptions,
): NavigationResultParameters
patternP- The pattern to link to. With
Registeraugmented, only the table’s linkable patterns are accepted. paramsRegisteredParams<P>- The values of the pattern’s params. Left out for a pattern without params.
optionsNavigateToOptions- Options for the navigation; the second argument for a pattern without params.
Returns
NavigationResult — The { committed, finished } that the browser’s navigation.navigate() returns. finished resolves once the new page is on screen.
Caveats
- By default, it pushes a new history entry.
- Overtaken by another navigation,
finishedrejects with anAbortError.
await navigateTo('/products/:id', { id: '42' }).finished;
navigateTo('/products', { history: 'replace' });bindParams
Import from @k8ordo/router
Creates an href and a navigateTo that take some params from a function, for a param every link shares, such as a locale.
bindParams<const Bound extends BoundParams>(
source: () => Bound,
): BoundLinks<Bound>Parameters
source() => Bound- A function returning the params to bind, called every time
hrefornavigateTois.
Returns
BoundLinks<Bound> — An href and a navigateTo that fill in what source returns.
Caveats
- A bound param may be left out, or passed to override it.
- When the pattern names a param, the options are always the third argument; with every param bound, pass
undefinedsecond.
usePathname
Import from @k8ordo/router
Returns the path the browser is on.
usePathname(): stringReturns
string — The current path, without the base path or a trailing slash.
Caveats
- It re-renders when the path changes, and never when only the query string does.
- It changes as soon as the URL does, without waiting for the new page to be on screen.
- During a server render or hydration, it throws unless it is under
<Router>or in a page the framework renders.
useMatch
Import from @k8ordo/router
Checks whether the current path fits a pattern.
useMatch<P extends MatchablePattern>(
pattern: P,
options?: MatchOptions,
): ParamsOf<P> | nullParameters
patternP- A pattern from the table, or one followed by
/*, which means “anywhere below it”. optionsMatchOptions- With
inclusiveset totrue, a/*pattern also fits its own page.
Returns
ParamsOf<P> | null — The params when it fits, or null.
Caveats
- Built on
usePathname, it re-renders only when the path changes. - It needs no route table, so it works under the framework.
matchPath
Import from @k8ordo/router
Makes the same check as useMatch, against the path you pass.
matchPath<P extends MatchablePattern>(
pattern: P,
pathname: string,
options?: MatchOptions,
): ParamsOf<P> | nullParameters
patternP- A pattern from the table, or one followed by
/*, which means “anywhere below it”. pathnamestring- The path to check; a trailing slash is dropped before comparing.
optionsMatchOptions- With
inclusiveset totrue, a/*pattern also fits its own page.
Returns
ParamsOf<P> | null — The params when it fits, or null.
matchPath('/products/:id', '/products/42'); // { id: '42' }
matchPath('/products/*', '/products'); // null
matchPath('/products/*', '/products', { inclusive: true }); // {}usePendingPathname
Import from @k8ordo/router
Returns the path of the page being loaded.
usePendingPathname(): string | nullReturns
string | null — The path of the page being loaded, or null when none is.
Caveats
- It is set as a navigation starts, and goes back to
nullonce the new page is on screen, or when the navigation is abandoned or its load fails. - An update that changes only the query string sets nothing.
- It is
nullin a server render.
useParams
Import from @k8ordo/router
Reads a page’s params, typed by its pattern.
useParams<P extends RegisteredPattern>(pattern: P): ParamsOf<P>Parameters
patternP- The pattern of the page this component renders as.
Returns
ParamsOf<P> — The params, typed by the pattern. Every value is a string.
Caveats
- Rendered under another pattern, it throws.
- It works only under
<Router>, not under the framework.
useRoute
Import from @k8ordo/router
Returns the pattern that won and its params, untyped.
useRoute(): {
pattern: string;
params: Readonly<Record<string, string>>;
}Returns
Pick<Match, 'pattern' | 'params'> — The winning pattern and its params.
Caveats
- It throws outside
<Router>, or where no page matched.
normalizePathname
Import from @k8ordo/router
Tidies a path by the router’s own rule: trailing slashes are dropped, and / alone is kept.
normalizePathname(pathname: string): stringParameters
pathnamestring- The path to tidy.
Caveats
- Only trailing slashes go: repeated slashes inside the path and percent-encoding are left alone.
normalizePathname('/products/'); // '/products'
normalizePathname('/'); // '/'withBase
Import from @k8ordo/router
Puts the base path the app is served under in front of a path in the table’s terms.
withBase(pathname: string, base?: string): stringParameters
pathnamestring- A path in the table’s terms.
basestring- The base path. Left out, it is read from
import.meta.env.BASE_URL; code Vite does not process passes it.
Returns
string — The path with the base path in front.
Caveats
- A relative base such as
./adds and removes nothing.
withoutBase
Import from @k8ordo/router
Takes the base path the app is served under off a URL’s path.
withoutBase(pathname: string, base?: string): string | nullParameters
pathnamestring- A URL’s path.
basestring- The base path. Left out, it is read from
import.meta.env.BASE_URL; code Vite does not process passes it.
Returns
string | null — The path without the base path, or null for a path outside it.
Caveats
- A relative base such as
./adds and removes nothing.
withBase('/products', '/docs/'); // '/docs/products'
withoutBase('/docs/products', '/docs/'); // '/products'
withoutBase('/elsewhere', '/docs/'); // nullnotFound
Import from @k8ordo/router
Says, from a framework page, that its path has no page after all.
notFound(): neverCaveats
- It throws, so nothing after it runs.
- Under
@k8ordo/staticand@k8ordo/server, the nearestnot-found.tsxanswers under a 404. - Under
<Router>, it is an error like any other.
isNotFound
Import from @k8ordo/router
Checks whether a thrown value is what notFound() throws.
isNotFound(value: unknown): booleanParameters
valueunknown- The value to check.
Caveats
- It looks for a
Symbol.forbrand rather than a class, so it works even with two copies of this package loaded.
PathnameProvider
Import from @k8ordo/router
Gives usePathname its path during a server render and hydration.
<PathnameProvider pathname={string}>{children}</PathnameProvider>Parameters
pathnamestring- The path this render is for.
Caveats
<Router>and the framework’s runtime provide it themselves. An app writes it only when it builds its own host onuseInterceptedNavigation.
NavigationGeneration
Import from @k8ordo/router
A context that tells the route table’s error a new page is on screen.
<NavigationGeneration value={number}>
{children}
</NavigationGeneration>Parameters
valuenumber- The
generationuseInterceptedNavigationreturns.
Caveats
<Router>and the framework’s runtime provide it themselves.
useInterceptedNavigation
Import from @k8ordo/router
The navigation half of <Router>, on its own: it loads and applies the navigations it takes, and finishes each once the new page is on screen.
useInterceptedNavigation<T>(
handler: NavigationHandler<T>,
): { readonly generation: number }Parameters
handlerNavigationHandler<T>- The functions that decide whether to take a navigation, what to load, and how to apply it.
Returns
{ readonly generation: number } — generation, which changes each time a new page is on screen.
Caveats
- Render what
applyset throughuseDeferredValue, in the same component. handleris read at event time, so a new object on every render is fine.
Routes
Import from @k8ordo/router
The type of the route table defineRoutes returns.
type Routes<R extends RoutesRecord = RoutesRecord> = {
kind: 'routes';
record: R;
match: (
pathname: string,
accept?: (match: Match) => boolean,
) => Match | null;
};Fields
kind'routes'- Always
routes. recordR- The table passed to
defineRoutes. match(pathname, accept?) => Match | null- Matches a path, returning the
Matchornull. Whenacceptreturnsfalse, that result is passed over and the walk goes on to the next pattern.
RoutesRecord
Import from @k8ordo/router
The type of a table: keys are patterns starting with /, values are RouteNodes.
type RoutesRecord = Record<`/${string}`, RouteNode>;RouteNode
Import from @k8ordo/router
The type of a value in the table: a page component, or an object with children.
type RouteNode =
| RouteComponent
| {
layout?: RouteComponent;
error?: ErrorComponent;
loading?: ComponentType;
children: RoutesRecord;
};Fields
layoutRouteComponent- The layout wrapping the pages below.
errorErrorComponent- What renders in place of a page below that throws.
loadingComponentType- What shows while a page below suspends. It receives no props.
childrenRoutesRecord- The table of pages below; its keys continue the parent’s pattern.
RouteComponent
Import from @k8ordo/router
The type of a page or layout: a component declaring any props.
type RouteComponent = ComponentType<never>;Caveats
<Router>passes no props and the framework passesparamsand more, so it isComponentType<never>to let either render the same table.
Match
Import from @k8ordo/router
The type of what match returns.
type Match = {
pattern: string;
params: Readonly<Record<string, string>>;
stack: readonly RouteComponent[];
};Fields
patternstring- The winning pattern, spelled as in the table.
paramsReadonly<Record<string, string>>- The decoded param values.
stackreadonly RouteComponent[]- The components to render, outermost layout first and the page last.
ErrorProps
Import from @k8ordo/router
The props the route table’s error component receives.
type ErrorProps = {
readonly error: unknown;
readonly reset: () => void;
};Fields
errorunknown- What was thrown.
reset() => void- Renders the page below again, in place.
ErrorComponent
Import from @k8ordo/router
The type of the component the route table’s error names.
type ErrorComponent = ComponentType<ErrorProps>;NavigateToOptions
Import from @k8ordo/router
The type of navigateTo’s options.
type NavigateToOptions = {
history?: 'push' | 'replace';
};Fields
history'push' | 'replace''push'adds a new entry and'replace'replaces the current one. The default is'push'.
MatchOptions
Import from @k8ordo/router
The type of useMatch’s and matchPath’s options.
type MatchOptions = {
readonly inclusive?: boolean;
};Fields
inclusiveboolean- Lets a
/*pattern fit its own page too. It changes nothing for a pattern not ending in/*.
MatchablePattern
Import from @k8ordo/router
The patterns useMatch and matchPath take: one from the table, or a linkable pattern followed by /*.
type MatchablePattern =
| RegisteredPattern
| `${RegisteredNavigablePattern}/*`;BoundParams
Import from @k8ordo/router
What the function given to bindParams returns: values with one URL spelling, by param name.
type BoundParams = Readonly<Record<string, ParamValue>>;BoundLinks
Import from @k8ordo/router
The type of what bindParams returns.
type BoundLinks<Bound extends BoundParams> = {
readonly href: (pattern, params?) => string;
readonly navigateTo: (
pattern,
params?,
options?: NavigateToOptions,
) => NavigationResult;
};Fields
href(pattern, params?) => string- An
hrefthat fills in the bound params. navigateTo(pattern, params?, options?) => NavigationResult- A
navigateTothat fills in the bound params.
NavigationHandler
Import from @k8ordo/router
The type of the functions useInterceptedNavigation takes.
type NavigationHandler<T> = {
claim: (url: URL) => boolean;
load: (url: URL, signal: AbortSignal) => T | Promise<T>;
apply: (value: T) => void;
refresh?: (url: URL) => boolean;
};Fields
claim(url: URL) => boolean- Whether to take this navigation, answered synchronously during the event.
load(url: URL, signal: AbortSignal) => T | Promise<T>- Produces what to render for the URL.
signalaborts when the navigation is overtaken. apply(value: T) => void- Applies it, as an ordinary update outside any transition.
refresh(url: URL) => boolean- Whether a navigation that keeps the path should still load. Left out, it never does.
Register
Import from @k8ordo/router
The interface a route table is registered on. Add routes with declare module, and patterns are checked against the table.
declare module '@k8ordo/router' {
interface Register {
routes: typeof routes;
}
}Caveats
- Register once, in the app.
- Under
@k8ordo/staticand@k8ordo/serverit is generated into.k8ordo/register.gen.ts, withparamsandsearch, and under@k8ordo/serverrequesttoo.
RegisteredPattern
Import from @k8ordo/router
The pattern of every page in the registered table, /* patterns included. Before registering, any string starting with /.
type RegisteredPattern = Register extends {
routes: Routes<infer R>;
}
? PatternOf<R>
: `/${string}`;RegisteredNavigablePattern
Import from @k8ordo/router
The registered table’s patterns a link can point at, which leaves out those with /*. Before registering, any string starting with /.
type RegisteredNavigablePattern = Register extends {
routes: Routes<infer R>;
}
? NavigablePatternOf<R>
: `/${string}`;RegisteredParams
Import from @k8ordo/router
The params a link to pattern P takes. A param a schema typed takes that type; the others take a ParamValue or a string.
type RegisteredParams<P extends string>RegisteredPageParams
Import from @k8ordo/router
The params the page at pattern P receives: a schema’s output where one ran, and strings elsewhere.
type RegisteredPageParams<P extends string>PageProps
Import from @k8ordo/router
The props a framework page receives, by the pattern its directory stands for.
type PageProps<P extends RegisteredPattern> = {
readonly params: RegisteredPageParams<P>;
readonly pathname: string;
} & RequestProps &
SearchProps<P>;Fields
paramsRegisteredPageParams<P>- The params, typed by the schemas.
pathnamestring- The path this render is for.
requestRequest- The request; only under
@k8ordo/server. searchunknown- What a page that exports
searchreads; only on such a page.
LayoutProps
Import from @k8ordo/router
The props a framework layout receives. Its type argument must be a pattern with a page.
type LayoutProps<P extends RegisteredPattern> = {
readonly params: ParamsOf<P>;
readonly pathname: string;
readonly children: ReactNode;
} & RequestProps;Fields
paramsParamsOf<P>- The params, typed as strings even with a schema.
pathnamestring- The path this render is for.
childrenReactNode- The page the layout wraps.
requestRequest- The request; only under
@k8ordo/server.
RouteContext
Import from @k8ordo/router
The type of what a framework route.ts handler receives.
type RouteContext<P extends RegisteredPattern> = {
readonly request: Request;
readonly params: RegisteredPageParams<P>;
};Fields
requestRequest- The incoming request.
paramsRegisteredPageParams<P>- The params, typed by the schemas as a page’s are.
PatternOf
Import from @k8ordo/router
Every page pattern in table R, as written, /* patterns included.
type PatternOf<R extends RoutesRecord>NavigablePatternOf
Import from @k8ordo/router
The patterns of table R a link can point at, which leaves out those with /*.
type NavigablePatternOf<R extends RoutesRecord>NavigablePath
Import from @k8ordo/router
Path when it fits one of the table’s linkable patterns segment by segment, and never when none fits.
type NavigablePath<D, Path extends string>Caveats
- Where a pattern has a
:param, any one non-empty segment fits. - A path with a trailing slash is
never.
type A = NavigablePath<typeof routes, '/products/42'>;
// '/products/42'
type B = NavigablePath<typeof routes, '/products/42/reviews'>;
// neverParamsOf
Import from @k8ordo/router
The params derived from a pattern string, every value a string.
type ParamsOf<Pattern extends string>type Params = ParamsOf<'/:locale/products/:id'>;
// { locale: string; id: string }PathFor
Import from @k8ordo/router
The type of a path that fits the pattern, with any string where each :param is.
type PathFor<Pattern extends string>type Path = PathFor<'/:locale/products/:id'>;
// `/${string}/products/${string}`ParamValue
Import from @k8ordo/router
The values with exactly one URL spelling, which a link’s params take.
type ParamValue = string | number | bigint | boolean;StandardSchemaLike
Import from @k8ordo/router
The Standard Schema shape, which a schema from any library implementing it fits, zod and zod/mini included.
type StandardSchemaLike<Output = unknown> = {
readonly '~standard': {
readonly types?: { readonly output: Output } | undefined;
};
};SchemaOutput
Import from @k8ordo/router
The type of what a schema produces.
type SchemaOutput<Schema> =
Schema extends StandardSchemaLike<infer Output> ? Output : never;ParamsSchemaFor
Import from @k8ordo/router
A schema that can be pattern P’s paramsSchema: its output’s keys are some of the pattern’s params.
type ParamsSchemaFor<Pattern extends string> = StandardSchemaLike<
Partial<Record<keyof ParamsOf<Pattern> & string, unknown>>
>;ParsedParams
Import from @k8ordo/router
A pattern’s params after a list of schemas has run, outer layouts first and the page last. A param no schema covers stays a string.
type ParsedParams<
Pattern extends string,
Schemas extends readonly unknown[],
>ParsedParamsMap
Import from @k8ordo/router
Turns each pattern’s list of schemas into its ParsedParams; the generated Register’s params is one.
type ParsedParamsMap<
Schemas extends Record<string, readonly unknown[]>,
>Caveats
- The schema types are mostly for the generated code; what an app writes by hand is
PagePropsandLayoutProps.