A lightweight, label-based router for Svelte 5. Define named routes that map to URL patterns, then use router.route reactively — not just to show components, but for any logic that depends on where you are.
npm install svelte-navigator-lite
Call createRouter once at your app's entry point (e.g. App.svelte):
import { createRouter, router } from 'svelte-navigator-lite';
import type { RouteList } from 'svelte-navigator-lite';
const routes: RouteList = {
'login': {
rootPath: 'login',
segments: [],
},
'dashboard': {
rootPath: 'dashboard',
segments: [],
},
};
createRouter(routes, 'dashboard'); // second argument is the default/fallback route
Then use router.route anywhere in your Svelte components — it's a reactive Svelte 5 $state value:
{#if router.is('login')}
<Login />
{:else if router.is('dashboard')}
<Dashboard />
{/if}
Every route has a rootPath — the first URL segment — and an array of segments for everything after it.
'login': {
rootPath: 'login', // matches /login
segments: [],
}
Use name to capture a URL segment into router.params:
'event': {
rootPath: 'event',
segments: [{ name: 'eventId' }], // matches /event/123
}
// router.params.eventId === '123'
Use enforceVal to require a literal string at that position:
'create-calendar': {
rootPath: 'calendar',
segments: [{ enforceVal: 'create' }], // matches /calendar/create only
}
enforceVal and name segments can be combined in any order:
'edit-event': {
rootPath: 'event',
segments: [
{ name: 'eventId' }, // matches /event/:eventId/edit
{ enforceVal: 'edit' },
],
}
Add optional: true to make a trailing segment optional. Optional segments must come after all required segments.
'event': {
rootPath: 'event',
segments: [
{ name: 'eventId' },
{ enforceVal: 'edit', optional: true }, // matches /event/123 AND /event/123/edit
],
}
Search params are automatically captured into router.searchParams when present in the URL. No configuration is needed — they never affect whether a route matches.
// /password-reset?token=abc → router.searchParams.token === 'abc'
// /password-reset → router.searchParams === {}
router.navigate(route, params?, searchParams?)Navigate to a named route. Path params fill dynamic segments; pass search params separately as the third argument.
router.navigate('event', { eventId: '123' });
// → /event/123
router.navigate('password-reset', undefined, { token: 'abc123' });
// → /password-reset?token=abc123
router.navigate('event', { eventId: '123' }, { tab: 'details' });
// → /event/123?tab=details
Throws if a required param is missing.
goto(path)Lower-level navigation to a raw path. Accepts an optional { replaceState: true } option to replace instead of push.
import { goto } from 'svelte-navigator-lite';
goto('/login');
goto('/login', { replaceState: true });
Guards run before navigation and redirect if their condition is met. fn returning true triggers the redirect.
import type { RouteGuard } from 'svelte-navigator-lite';
const guards = {
authenticated: {
fn: () => !auth.isValid(), // redirect if NOT authenticated
redirectTo: 'login',
} satisfies RouteGuard,
unauthenticated: {
fn: () => auth.isValid(), // redirect if already authenticated
redirectTo: 'dashboard',
} satisfies RouteGuard,
};
const routes: RouteList = {
'login': {
rootPath: 'login',
segments: [],
routeGuards: [guards.unauthenticated],
},
'dashboard': {
rootPath: 'dashboard',
segments: [],
routeGuards: [guards.authenticated],
},
};
Guards run in order and stop at the first redirect.
createRouter(routes, defaultRoute)Registers all routes and sets the fallback route. Parses the current URL immediately. Must be called once before using router.
router.routeThe label of the currently matched route. Falls back to defaultRoute if no route matches.
router.paramsAn object containing the captured path param values for the current route.
router.searchParamsAn object containing the search params present in the current URL. Empty object when none are present.
router.notFoundtrue when the current URL did not match any defined route and the router fell back to defaultRoute. Use this to render a 404 state without needing a dedicated catch-all route.
{#if router.notFound}
<NotFound />
{:else if router.is('dashboard')}
<Dashboard />
{/if}
router.navigate(route, params?, searchParams?)Navigate to a named route, applying guards and building the URL from the route definition.
router.is(route)Returns true if router.route === route. Useful for active link styling.
class:active={router.is('dashboard')}
router.matches(routes)Returns true if router.route is any of the provided route names.
class:active={router.matches(['dashboard', 'settings'])}
router.registerRoute(name, route)Register a new route.
registerRoute('settings', {
rootPath: 'settings',
segments: [],
routeGuards: [guards.authenticated],
})
### `page`
A readable Svelte store that emits `{ url: URL }` and updates on every navigation. Useful when you need the raw URL.
```ts
import { page } from 'svelte-navigator-lite';
$page.url.pathname;
rootPath is always required and must match the first URL segment exactly.required segments + 1 and total segments + 1 (the +1 accounts for rootPath).rootPath with nothing after it (e.g. /login not /login/extra).defaultRoute.