@xmachines/play-sveltekit-router
API / @xmachines/play-sveltekit-router
SvelteKit router adapter for the XMachines Universal Player Architecture. Provides bidirectional synchronisation between a RoutableActor’s state machine routes and the browser URL via SvelteKit’s $app/navigation.
Part of the xmachines-js monorepo.
Installation
npm install @xmachines/play-sveltekit-routerPeer dependencies (must be installed separately):
npm install @sveltejs/kit svelte xstate| Peer dependency | Required version |
|---|---|
@sveltejs/kit | ^2.0.0 |
svelte | ^5.0.0 |
xstate | ^5.31.0 |
Quick Start
import { connectRouter, createRouteMap } from "@xmachines/play-sveltekit-router";import { definePlayer } from "@xmachines/play-xstate";import { myMachine } from "./machine.js";
// 1. Create the actorconst createPlayer = definePlayer({ machine: myMachine });const actor = createPlayer();actor.start();
// 2. Build a bidirectional route map from the machine definitionconst routeMap = createRouteMap(myMachine);
// 3. Connect the router — returns a cleanup functionconst disconnect = connectRouter({ actor, routeMap });
// 4. Clean up when the component is destroyedonDestroy(() => disconnect());The bridge synchronises in both directions:
- URL → actor: SvelteKit
afterNavigateevents are translated toplay.routeevents and sent to the actor. - Actor → URL: Actor
currentRoutesignal changes are reflected to the browser URL viagoto().
Usage
connectRouter(options) — high-level API
The primary integration point. Instantiates a SvelteKitRouterBridge, calls connect(), and returns a cleanup function.
import { connectRouter, createRouteMap } from "@xmachines/play-sveltekit-router";
const routeMap = createRouteMap(machine);
// In a Svelte component or SvelteKit layoutconst disconnect = connectRouter({ actor, routeMap });
// Pass an explicit location for SSR or test environmentsconst disconnect = connectRouter({ actor, routeMap, location: { pathname: "/dashboard", search: "?tab=stats" },});
// CleanuponDestroy(() => disconnect());ConnectRouterOptions:
| Property | Type | Required | Description |
|---|---|---|---|
actor | RoutableActor | Yes | The XMachines actor to synchronise with the router |
routeMap | RouteMap | Yes | Bidirectional state ID ↔ URL path mapping |
location | LocationLike | null | No | Location stub for initial URL reads. Defaults to globalThis.location. Pass a mock in tests or a stub in SSR environments. |
SvelteKitRouterBridge — low-level class
Extends RouterBridgeBase from @xmachines/play-router. Use directly when you need fine-grained control over the connection lifecycle.
import { SvelteKitRouterBridge, createRouteMap } from "@xmachines/play-sveltekit-router";
const routeMap = createRouteMap(machine);const bridge = new SvelteKitRouterBridge(actor, routeMap, location);bridge.connect();
// On teardownbridge.disconnect();SvelteKit integration details:
navigateRouter→goto(path, { noScroll: true, keepFocus: true })watchRouterChanges→ registers anafterNavigatecallback via an indirection cell, avoiding directthiscaptureunwatchRouterChanges→ nulls the indirection cell, releasing the bridge reference before component unmount (since SvelteKit provides no programmatic cancel API forafterNavigate)
createRouteMap(machine)
Factory that builds a RouteMap from an XState machine definition. State route patterns are read from state.meta.route.
import { createRouteMap } from "@xmachines/play-sveltekit-router";import { createMachine } from "xstate";
const machine = createMachine({ id: "app", initial: "home", states: { home: { meta: { route: "/home" } }, dashboard: { meta: { route: "/dashboard" } }, settings: { meta: { route: "/settings/:section?" } }, },});
const routeMap = createRouteMap(machine);RouteMap / RouteMapping
Bidirectional state ID ↔ URL path mapping. Re-exported from @xmachines/play-router.
import { RouteMap } from "@xmachines/play-sveltekit-router";
const routeMap = new RouteMap([ { stateId: "#app.home", path: "/home" }, { stateId: "#app.dashboard", path: "/dashboard" }, { stateId: "#app.settings", path: "/settings/:section?" },]);API Summary
Exported symbols
| Export | Kind | Description |
|---|---|---|
connectRouter | function | High-level factory — connects the SvelteKit router to an actor, returns a cleanup function |
ConnectRouterOptions | type | Options bag for connectRouter |
createRouteMap | function | Builds a RouteMap from an XState machine definition |
RouteMap | class | Bidirectional state ID ↔ URL path mapping (re-exported from @xmachines/play-router) |
RouteMapping | type | Single { stateId, path } entry for RouteMap construction |
RouteMapOptions | type | Options for RouteMap construction |
LocationLike | type | Minimal { pathname, search } interface for location stubs |
PlayRouteEvent | type | Event sent to the actor on URL change ({ type: "play.route", to, params?, query? }) |
RouterBridge | type | Interface implemented by SvelteKitRouterBridge |
RoutableActor | type | Minimal actor interface from @xmachines/play-router — currentRoute, initialRoute, send(PlayRouteEvent) |
Demo
A runnable Svelte 5 + SvelteKit router adapter demo is available in examples/demo/. To run it from the monorepo root:
npm installnpm run dev -w @xmachines/play-sveltekit-router-demoThen open http://localhost:5173.
Testing
Run tests for this package in isolation:
# From the monorepo rootnpm test -w packages/play-sveltekit-router
# Or from this package directorynpm testCoverage thresholds: 80% lines, functions, branches, and statements.
License
MIT — see LICENSE.