createRouter()
Signature
function createRouter<T extends RouteDefinition[]>( routes: T, options?: RouterOptions,): Router<T>;Parameters
routes — required
An array of route definitions. Each route has shape:
type RouteDefinition = { path: string; handler: () => Promise<unknown>; meta?: Record<string, unknown>;};| Field | Type | Description |
|---|---|---|
path | string | URL pattern. Supports literals (/about), params (:id), and a trailing wildcard (*). |
handler | () => Promise<unknown> | Called on match. Typically () => import('./page'). The resolved value is exposed on match.handler(). |
meta | Record<string, unknown> | Optional. Arbitrary data attached to the route — useful for requiresAuth, layout, page metadata, etc. Available as match.meta. |
options — optional
type RouterOptions = { base?: string; hash?: boolean; scrollBehavior?: 'auto' | 'instant' | 'smooth' | 'manual';};| Option | Default | Description |
|---|---|---|
base | '/' | Base path for all routes. Set to '/app/' if your SPA lives at example.com/app/. |
hash | false | Use #-based URLs instead of HTML5 history. Useful when deploying to environments that can’t be configured to fall back to index.html. |
scrollBehavior | 'auto' | What to do on navigation. 'manual' disables routekit scroll handling entirely. |
Returns
A Router<T> instance:
type Router<T> = { start: () => void; go: (target: string | NavigateTarget) => void; replace: (target: string | NavigateTarget) => void; back: () => void; forward: () => void; match: (url: string) => Match | null; on: <E extends RouterEvent>(event: E, handler: RouterEventHandler<E>) => () => void; url: string; // current URL (read-only) routes: T; // the route table you passed in};Examples
Minimal
import { createRouter } from 'routekit';
const router = createRouter([ { path: '/', handler: () => import('./pages/home') }, { path: '/posts/:id', handler: () => import('./pages/post') },]);
router.start();With base path
If your app is served at https://example.com/docs/:
const router = createRouter(routes, { base: '/docs/' });This is what PUBLIC_BASE_PATH in this template’s astro.config.mjs configures for Starlight — the same idea.
With route metadata
const routes = [ { path: '/admin', handler: () => import('./pages/admin'), meta: { requiresAuth: true, layout: 'admin' }, },] as const;
const router = createRouter(routes);
router.on('navigate', ({ match }) => { if (match.meta?.requiresAuth && !isLoggedIn()) { router.replace('/login'); return; } // ... render});Caveats
- Order matters. The first matching route wins. Put specific routes before generic ones. See match order.
as constfor type safety. Without it,routes[N].pathwidens tostringand you lose param inference. See TypeScript usage.- Single router per app. Creating multiple
createRouter()calls is supported but rarely useful — they’ll all attach delegated<a>interceptors and may double-handle clicks. If you need conditional routing, use routemetaand branch in your'navigate'handler.