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.

loading 0

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: GameHost mounts 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.