Demos · Svelte bridge
Svelte 5 UI bridge
This demo shows Svelte observing readonly game snapshots and invoking typed commands without making the core runtime depend on Svelte.
Game codepublish(state)
GameAdapterreadonly view
Svelte UIrender snapshot
UI event → typed command → game code
Try one host
This example focuses on the common path. One host owns one adapter and game instance. The status becomes ready after game.ready, and disposal occurs when the host unmounts.
What the bridge owns
- Game → UI: game code is the only publisher; Svelte receives readonly snapshots.
- UI → game: commands are inferred from the command object and preserve sync or async returns.
- Lifecycle:
GameHostmounts one adapter per canvas and disposes it on unmount. - Isolation: each host keeps its state, commands, subscriptions, and game separate from other hosts.
Use the host component
type State = Readonly<{ score: number }>;
const commands = { increment: (amount: number) => score += amount };
<GameHost initial_state={{ score: 0 }} {commands} {create}>
{#snippet children(view)}
<output>{view.state.score}</output>
<button onclick={() => view.commands.increment(1)}>+1</button>
{/snippet}
{/GameHost> Use the adapter directly
const adapter = create_game_adapter({ initial_state: { score: 0 }, commands, create });
const unsubscribe = adapter.subscribe((view) => render(view));
await adapter.mount(canvas);
await adapter.dispose(); Public types
GameAdapterView<State, Commands>— readonly state, lifecycle status, error, and typed commands.GameAdapterOptions<State, Commands>— initial state, command map, scheduler, and game factory.GameBridge<State, Commands>— the game-owned publisher and readonly bridge surface.GameHost— Svelte 5 render-prop host that owns mount and disposal.
The demo uses a deterministic fake game so you can focus on state snapshots, commands, and disposal without unrelated rendering code.