Skip to content

@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

Terminal window
npm install @xmachines/play-sveltekit-router

Peer dependencies (must be installed separately):

Terminal window
npm install @sveltejs/kit svelte xstate
Peer dependencyRequired 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 actor
const createPlayer = definePlayer({ machine: myMachine });
const actor = createPlayer();
actor.start();
// 2. Build a bidirectional route map from the machine definition
const routeMap = createRouteMap(myMachine);
// 3. Connect the router — returns a cleanup function
const disconnect = connectRouter({ actor, routeMap });
// 4. Clean up when the component is destroyed
onDestroy(() => disconnect());

The bridge synchronises in both directions:

  • URL → actor: SvelteKit afterNavigate events are translated to play.route events and sent to the actor.
  • Actor → URL: Actor currentRoute signal changes are reflected to the browser URL via goto().

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 layout
const disconnect = connectRouter({ actor, routeMap });
// Pass an explicit location for SSR or test environments
const disconnect = connectRouter({
actor,
routeMap,
location: { pathname: "/dashboard", search: "?tab=stats" },
});
// Cleanup
onDestroy(() => disconnect());

ConnectRouterOptions:

PropertyTypeRequiredDescription
actorRoutableActorYesThe XMachines actor to synchronise with the router
routeMapRouteMapYesBidirectional state ID ↔ URL path mapping
locationLocationLike | nullNoLocation 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 teardown
bridge.disconnect();

SvelteKit integration details:

  • navigateRoutergoto(path, { noScroll: true, keepFocus: true })
  • watchRouterChanges → registers an afterNavigate callback via an indirection cell, avoiding direct this capture
  • unwatchRouterChanges → nulls the indirection cell, releasing the bridge reference before component unmount (since SvelteKit provides no programmatic cancel API for afterNavigate)

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

ExportKindDescription
connectRouterfunctionHigh-level factory — connects the SvelteKit router to an actor, returns a cleanup function
ConnectRouterOptionstypeOptions bag for connectRouter
createRouteMapfunctionBuilds a RouteMap from an XState machine definition
RouteMapclassBidirectional state ID ↔ URL path mapping (re-exported from @xmachines/play-router)
RouteMappingtypeSingle { stateId, path } entry for RouteMap construction
RouteMapOptionstypeOptions for RouteMap construction
LocationLiketypeMinimal { pathname, search } interface for location stubs
PlayRouteEventtypeEvent sent to the actor on URL change ({ type: "play.route", to, params?, query? })
RouterBridgetypeInterface implemented by SvelteKitRouterBridge
RoutableActortypeMinimal actor interface from @xmachines/play-routercurrentRoute, initialRoute, send(PlayRouteEvent)

Demo

A runnable Svelte 5 + SvelteKit router adapter demo is available in examples/demo/. To run it from the monorepo root:

Terminal window
npm install
npm run dev -w @xmachines/play-sveltekit-router-demo

Then open http://localhost:5173.

Testing

Run tests for this package in isolation:

Terminal window
# From the monorepo root
npm test -w packages/play-sveltekit-router
# Or from this package directory
npm test

Coverage thresholds: 80% lines, functions, branches, and statements.

License

MIT — see LICENSE.

Classes

Interfaces

Type Aliases

Functions