# stakeengine/web-sdk architecture

> Architecture diagram of the GitHub repository stakeengine/web-sdk, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/stakeengine/web-sdk
- Repository: https://github.com/stakeengine/web-sdk

## Overview

1. **Repository shape**
This is a Turborepo monorepo for a web SDK aimed at building and launching Stake Engine games. The top-level split is:
- `apps/*`: complete playable game apps (`lines`, `cluster`, `scatter`, `price`, `ways`, `number-picker`)
- `packages/*`: reusable building blocks for rendering, state, game flow, UI, utilities, and tooling
- root config: pnpm workspace, TurboRepo, shared lint/format settings, plus `caddyfile` for static hosting

2. **Primary runtime model**
Each app is a SvelteKit application that renders a game shell and is designed to ship as a static frontend. The game surface is mostly PixiJS-driven visuals wrapped by Svelte components, while HTML/Svelte is used for orchestration, overlays, and UI panels. The repo is optimized for local dev, Storybook-driven testing, and static build output for Stake Engine deployment.

3. **App-level composition**
Every app has the same high-level entry pattern:
- `src/routes/+page.svelte` sets up app context
- `src/components/Game.svelte` is the main game composition root
- `src/game/*` contains the app-specific state, event mapping, config, and actor logic
- `src/stories/*` provides Storybook scenarios for books and single book events
- `static/assets/*` holds the game’s audio, fonts, Spine atlases/JSON, and spritesheets

The apps differ by game mechanic and component set. For example:
- `lines` is the base line game
- `cluster` and `scatter` use cluster/tumble style structures
- `price` adds expanding/sticky wild mechanics
- `number-picker` is much smaller and mostly shows the same state/flow patterns in a reduced form

4. **Shared domain model: books and bookEvents**
The central game-data abstraction is the **book** returned by the RGS/math side. A book contains an ordered list of **bookEvents**. Apps replay those bookEvents locally to reproduce the round. Storybook uses this same model with static fixture data under `src/stories/data/*`, which lets developers test full rounds, specific event types, or random books without a live backend.

5. **Event-driven execution flow**
The key runtime flow is:
- a bookEvent is read
- `bookEventHandlerMap` selects the handler for that event type
- the handler emits one or more **emitterEvents**
- Svelte components subscribe to those emitterEvents and animate/update themselves
- async emitterEvents can be awaited so later steps only happen after animations finish

This creates a clear separation between game rules and visual timing. The repo emphasizes “task breakdown”: a single complex bookEvent is often decomposed into many smaller emitterEvents distributed across components.

6. **State and control boundaries**
Each app builds four major contexts at the entry boundary:
- `eventEmitter`: pub/sub channel between game logic and components
- `stateXstate`: finite state machine for bet/render/play/resume states
- `stateLayout`: viewport, orientation, canvas sizing, and responsive layout info
- `stateApp`: app/asset loading state and Pixi application reference

This is a strong architectural boundary: game logic reads/writes shared state through these contexts instead of passing props through deep trees.

7. **XState as the game-control layer**
`packages/utils-xstate` and each app’s `src/game/stateXstate.ts` formalize the betting lifecycle with an XState machine. That machine handles states like rendering, idle, bet, auto-bet, and resume-bet, and prevents UI actions from conflicting with active gameplay. UI components typically consult derived state like `isPlaying()` or `isBetting()` to disable controls at the right time.

8. **Rendering stack**
The visual engine is PixiJS 8, integrated through the in-house `pixi-svelte` package. That package provides Svelte components for Pixi primitives such as App, Container, Sprite, Spine, Text, Graphics, Particle systems, and asset loading. Game apps then build domain-specific components on top of those primitives, often using Spine animations and sprite sheets stored under each app’s `static/assets`.

9. **UI package split**
The UI is split into two reusable layers:
- `components-ui-pixi`: Pixi-based in-game UI widgets such as bet buttons, labels, orientation-specific layouts, and UI chrome
- `components-ui-html`: HTML/Svelte overlays and modals such as settings, paytable, game rules, auto-spin, buy bonus, and error dialogs

This separation matters architecturally: Pixi handles the animated game canvas, while HTML handles traditional overlay UI and dialogs.

10. **Reusable infrastructure packages**
Several packages form the shared backend of the frontend architecture:
- `utils-book`: sequencing and execution helpers for books/bookEvents
- `utils-event-emitter`: typed event bus and Svelte context wiring
- `utils-layout`: responsive canvas/layout state
- `utils-sound`: audio playback helpers
- `utils-slots`: slot-specific board/reel/tumble helpers
- `constants-shared`, `utils-shared`, `state-shared`: cross-app constants, helpers, and Svelte state modules
- `config-*`: shared TS/Svelte/Vite/Storybook/Lingui config packages

These packages keep app code focused on game specifics rather than infrastructure repetition.

11. **Storybook as a first-class test harness**
Storybook is not just documentation here; it is the main interactive test environment. It can run:
- component-level stories
- single bookEvent stories
- full book playback stories for base, bonus, and special modes

That means the architecture is designed so any game mechanic can be validated in isolation before being wired into the full app flow.

12. **Assets and loading pipeline**
All app-specific runtime assets live in `static/assets`, including:
- audio files and sound manifests
- fonts for stylized number rendering
- Spine animations for reels, wins, transitions, loaders, multipliers, and feature sequences
- spritesheets for symbols, UI frames, coin effects, and text

The app loading layer uses `stateApp.loadedAssets` so Pixi components can consume already-loaded assets rather than managing fetch/load concerns themselves.

13. **Internationalisation**
i18n is implemented per app and per UI package using Lingui-derived message maps, with English and Chinese message sources visible in the repo. The architecture supports locale-aware text without entangling localization with game logic; this is important for Stake-style variants such as social-casino text changes.

14. **Deployment boundary**
The repository is meant to produce static frontend builds that are then uploaded into Stake Engine. The README shows the expected build artifact flow: prerendered `index.html` plus client assets copied into a deployable directory. `caddyfile` indicates a simple static-serving deployment path rather than a custom server runtime.

Main entry points: [`pnpm-workspace.yaml`](https://github.com/stakeengine/web-sdk/blob/main/pnpm-workspace.yaml) (Workspace), [`apps/lines`](https://github.com/stakeengine/web-sdk/tree/main/apps/lines) (Lines), [`apps/cluster`](https://github.com/stakeengine/web-sdk/tree/main/apps/cluster) (Cluster), [`caddyfile`](https://github.com/stakeengine/web-sdk/tree/main/caddyfile) (Static host)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_root["Root"]
  node_workspace["Workspace<br/>pnpm/turbo monorepo"]
  node_deploy["Static host<br/>caddy static serving"]
end

subgraph group_apps["Apps"]
  node_lines["Lines<br/>SvelteKit game app"]
  node_cluster["Cluster<br/>SvelteKit game app"]
  node_scatter["Scatter<br/>SvelteKit game app"]
  node_price["Price<br/>SvelteKit game app"]
  node_ways["Ways<br/>SvelteKit game app"]
  node_numberpicker["Number Picker<br/>SvelteKit game app"]
end

subgraph group_packages["Packages"]
  node_storybook["Storybook<br/>scenario harness"]
  node_pixi["Pixi Svelte<br/>rendering runtime"]
  node_ui_pixi["UI Pixi<br/>in-game UI kit"]
  node_ui_html["UI HTML<br/>overlay UI kit"]
  node_xstate["Game Control<br/>state machine layer"]
  node_events["Event Bus<br/>pub/sub bridge"]
  node_books["Book Runtime<br/>book playback"]
  node_layout["Layout<br/>responsive state"]
  node_sound["Sound<br/>audio helpers"]
  node_slots["Slots Utils<br/>board helpers"]
  node_shared["Shared Utils<br/>common helpers"]
  node_shared_state["Shared State<br/>Svelte state modules"]
  node_constants["Shared Consts<br/>constants package"]
  node_rgs["RGS Client<br/>fetch/request layer"]
  node_configs["Tooling Config<br/>shared config packages"]
end

node_workspace -->|"workspace builds"| node_lines
node_workspace -->|"workspace builds"| node_cluster
node_workspace -->|"workspace builds"| node_scatter
node_workspace -->|"workspace builds"| node_price
node_workspace -->|"workspace builds"| node_ways
node_workspace -->|"workspace builds"| node_numberpicker
node_workspace -->|"workspace packages"| node_pixi
node_workspace -->|"workspace packages"| node_ui_pixi
node_workspace -->|"workspace packages"| node_ui_html
node_workspace -->|"workspace packages"| node_xstate
node_workspace -->|"workspace packages"| node_events
node_workspace -->|"workspace packages"| node_books
node_workspace -->|"workspace packages"| node_layout
node_workspace -->|"workspace packages"| node_sound
node_workspace -->|"workspace packages"| node_slots
node_workspace -->|"workspace packages"| node_shared
node_workspace -->|"workspace packages"| node_shared_state
node_workspace -->|"workspace packages"| node_constants
node_workspace -->|"workspace packages"| node_rgs
node_workspace -->|"workspace packages"| node_configs
node_deploy -->|"serves build"| node_lines
node_deploy -->|"serves build"| node_cluster
node_deploy -->|"serves build"| node_scatter
node_deploy -->|"serves build"| node_price
node_deploy -->|"serves build"| node_ways
node_deploy -->|"serves build"| node_numberpicker
node_lines -->|"renders with"| node_pixi
node_lines -->|"uses"| node_ui_pixi
node_lines -->|"uses"| node_ui_html
node_lines -->|"controls with"| node_xstate
node_lines -->|"emits via"| node_events
node_lines -->|"replays"| node_books
node_lines -->|"sizes with"| node_layout
node_lines -->|"plays sound"| node_sound
node_lines -->|"shares state"| node_shared_state
node_lines -->|"uses constants"| node_constants
node_lines -->|"uses helpers"| node_shared
node_cluster -->|"renders with"| node_pixi
node_cluster -->|"uses"| node_ui_pixi
node_cluster -->|"uses"| node_ui_html
node_cluster -->|"controls with"| node_xstate
node_cluster -->|"emits via"| node_events
node_cluster -->|"replays"| node_books
node_cluster -->|"sizes with"| node_layout
node_cluster -->|"plays sound"| node_sound
node_cluster -->|"shares state"| node_shared_state
node_cluster -->|"uses constants"| node_constants
node_scatter -->|"renders with"| node_pixi

click node_workspace "https://github.com/stakeengine/web-sdk/blob/main/pnpm-workspace.yaml"
click node_deploy "https://github.com/stakeengine/web-sdk/tree/main/caddyfile"
click node_lines "https://github.com/stakeengine/web-sdk/tree/main/apps/lines"
click node_cluster "https://github.com/stakeengine/web-sdk/tree/main/apps/cluster"
click node_scatter "https://github.com/stakeengine/web-sdk/tree/main/apps/scatter"
click node_price "https://github.com/stakeengine/web-sdk/tree/main/apps/price"
click node_ways "https://github.com/stakeengine/web-sdk/tree/main/apps/ways"
click node_numberpicker "https://github.com/stakeengine/web-sdk/tree/main/apps/number-picker"
click node_storybook "https://github.com/stakeengine/web-sdk/tree/main/packages/components-storybook"
click node_pixi "https://github.com/stakeengine/web-sdk/tree/main/packages/pixi-svelte"
click node_ui_pixi "https://github.com/stakeengine/web-sdk/tree/main/packages/components-ui-pixi"
click node_ui_html "https://github.com/stakeengine/web-sdk/tree/main/packages/components-ui-html"
click node_xstate "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-xstate"
click node_events "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-event-emitter"
click node_books "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-book"
click node_layout "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-layout"
click node_sound "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-sound"
click node_slots "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-slots"
click node_shared "https://github.com/stakeengine/web-sdk/tree/main/packages/utils-shared"
click node_shared_state "https://github.com/stakeengine/web-sdk/tree/main/packages/state-shared"
click node_constants "https://github.com/stakeengine/web-sdk/tree/main/packages/constants-shared"
click node_rgs "https://github.com/stakeengine/web-sdk/tree/main/packages/rgs-fetcher"
click node_configs "https://github.com/stakeengine/web-sdk/tree/main/packages/config-ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_workspace,node_deploy toneBlue
class node_lines,node_cluster,node_scatter,node_price,node_ways,node_numberpicker toneAmber
class node_storybook,node_pixi,node_ui_pixi,node_ui_html,node_xstate,node_events,node_books,node_layout,node_sound,node_slots,node_shared,node_shared_state,node_constants,node_rgs,node_configs toneMint
```

## Components

### Root

Workspace-level tooling, shared config, and static deployment

- [Workspace](https://github.com/stakeengine/web-sdk/blob/main/pnpm-workspace.yaml): pnpm/turbo monorepo · Monorepo orchestration and shared scripts · `pnpm-workspace.yaml`
- [Static host](https://github.com/stakeengine/web-sdk/tree/main/caddyfile): caddy static serving · Simple static deployment boundary for built app assets · `caddyfile`

### Apps

Playable SvelteKit game applications

- [Lines](https://github.com/stakeengine/web-sdk/tree/main/apps/lines): SvelteKit game app · Base line-game implementation with Pixi-driven board and Storybook scenarios · `apps/lines`
- [Cluster](https://github.com/stakeengine/web-sdk/tree/main/apps/cluster): SvelteKit game app · Cluster/tumble game variant with bonus and win-flow composition · `apps/cluster`
- [Scatter](https://github.com/stakeengine/web-sdk/tree/main/apps/scatter): SvelteKit game app · Scatter/tumble variant with multiplier and board-specific mechanics · `apps/scatter`
- [Price](https://github.com/stakeengine/web-sdk/tree/main/apps/price): SvelteKit game app · Variant with sticky and expanding wild mechanics plus superspin flow · `apps/price`
- [Ways](https://github.com/stakeengine/web-sdk/tree/main/apps/ways): SvelteKit game app · Ways-style game application sharing the common runtime model · `apps/ways`
- [Number Picker](https://github.com/stakeengine/web-sdk/tree/main/apps/number-picker): SvelteKit game app · Reduced game app showing the same core state and event patterns · `apps/number-picker`

### Packages

Reusable runtime, UI, and infrastructure packages

- [Storybook](https://github.com/stakeengine/web-sdk/tree/main/packages/components-storybook): scenario harness · Interactive validation environment for components, events, and full books · `packages/components-storybook`
- [Pixi Svelte](https://github.com/stakeengine/web-sdk/tree/main/packages/pixi-svelte): rendering runtime · Svelte bindings and primitives for PixiJS 8 rendering · `packages/pixi-svelte`
- [UI Pixi](https://github.com/stakeengine/web-sdk/tree/main/packages/components-ui-pixi): in-game UI kit · Pixi-based HUD, buttons, labels, and responsive in-canvas UI · `packages/components-ui-pixi`
- [UI HTML](https://github.com/stakeengine/web-sdk/tree/main/packages/components-ui-html): overlay UI kit · HTML/Svelte modals, menus, settings, and dialog overlays · `packages/components-ui-html`
- [Game Control](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-xstate): state machine layer · Shared XState game lifecycle utilities and app state machines · `packages/utils-xstate`
- [Event Bus](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-event-emitter): pub/sub bridge · Typed emitter and Svelte context wiring between logic and components · `packages/utils-event-emitter`
- [Book Runtime](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-book): book playback · Sequencing and execution helpers for books and bookEvents · `packages/utils-book`
- [Layout](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-layout): responsive state · Canvas sizing, orientation, and viewport state helpers · `packages/utils-layout`
- [Sound](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-sound): audio helpers · Audio player helpers for loops, music, and one-shot playback · `packages/utils-sound`
- [Slots Utils](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-slots): board helpers · Reel, tumble, and board enhancement helpers for slot-style mechanics · `packages/utils-slots`
- [Shared Utils](https://github.com/stakeengine/web-sdk/tree/main/packages/utils-shared): common helpers · General helpers such as sequencing, random, wait, and win level utilities · `packages/utils-shared`
- [Shared State](https://github.com/stakeengine/web-sdk/tree/main/packages/state-shared): Svelte state modules · Cross-app Svelte state for bet, modal, sound, UI, and config state · `packages/state-shared`
- [Shared Consts](https://github.com/stakeengine/web-sdk/tree/main/packages/constants-shared): constants package · Cross-app constants such as colors, bet values, timing, and z-index · `packages/constants-shared`
- [RGS Client](https://github.com/stakeengine/web-sdk/tree/main/packages/rgs-fetcher): fetch/request layer · Client helpers for fetching and shaping RGS/math responses · `packages/rgs-fetcher`
- [Tooling Config](https://github.com/stakeengine/web-sdk/tree/main/packages/config-ts): shared config packages · Reusable ESLint, TS, Vite, Storybook, Svelte, and Lingui configs · `packages/config-ts`

## Connections

- Workspace → Lines: workspace builds · Monorepo includes the game apps
- Workspace → Cluster: workspace builds · Monorepo includes the game apps
- Workspace → Scatter: workspace builds · Monorepo includes the game apps
- Workspace → Price: workspace builds · Monorepo includes the game apps
- Workspace → Ways: workspace builds · Monorepo includes the game apps
- Workspace → Number Picker: workspace builds · Monorepo includes the game apps
- Workspace → Pixi Svelte: workspace packages · Shared frontend runtime packages
- Workspace → UI Pixi: workspace packages · Shared frontend runtime packages
- Workspace → UI HTML: workspace packages · Shared frontend runtime packages
- Workspace → Game Control: workspace packages · Shared frontend runtime packages
- Workspace → Event Bus: workspace packages · Shared frontend runtime packages
- Workspace → Book Runtime: workspace packages · Shared frontend runtime packages
- Workspace → Layout: workspace packages · Shared frontend runtime packages
- Workspace → Sound: workspace packages · Shared frontend runtime packages
- Workspace → Slots Utils: workspace packages · Shared frontend runtime packages
- Workspace → Shared Utils: workspace packages · Shared frontend runtime packages
- Workspace → Shared State: workspace packages · Shared frontend runtime packages
- Workspace → Shared Consts: workspace packages · Shared frontend runtime packages
- Workspace → RGS Client: workspace packages · Shared frontend runtime packages
- Workspace → Tooling Config: workspace packages · Shared frontend runtime packages
- Static host → Lines: serves build · Static hosting target for app output
- Static host → Cluster: serves build · Static hosting target for app output
- Static host → Scatter: serves build · Static hosting target for app output
- Static host → Price: serves build · Static hosting target for app output
- Static host → Ways: serves build · Static hosting target for app output
- Static host → Number Picker: serves build · Static hosting target for app output
- Lines → Pixi Svelte: renders with · Game canvas is built on PixiJS Svelte primitives
- Lines → UI Pixi: uses · In-canvas UI and controls
- Lines → UI HTML: uses · Modal and overlay UI
- Lines → Game Control: controls with · Game lifecycle and betting state machine
- Lines → Event Bus: emits via · Book events become emitter events for components
- Lines → Book Runtime: replays · Local book playback and event sequencing
- Lines → Layout: sizes with · Responsive canvas and orientation state
- Lines → Sound: plays sound · Audio playback helpers
- Lines → Shared State: shares state · Cross-component app state and modals
- Lines → Shared Consts: uses constants · Shared values and timing
- Lines → Shared Utils: uses helpers · Common utility functions
- Cluster → Pixi Svelte: renders with · Game canvas is built on PixiJS Svelte primitives
- Cluster → UI Pixi: uses · In-canvas UI and controls
- Cluster → UI HTML: uses · Modal and overlay UI
- Cluster → Game Control: controls with · Game lifecycle and betting state machine
- Cluster → Event Bus: emits via · Book events become emitter events for components
- Cluster → Book Runtime: replays · Local book playback and event sequencing
- Cluster → Layout: sizes with · Responsive canvas and orientation state
- Cluster → Sound: plays sound · Audio playback helpers
- Cluster → Shared State: shares state · Cross-component app state and modals
- Cluster → Shared Consts: uses constants · Shared values and timing
- Scatter → Pixi Svelte: renders with · Game canvas is built on PixiJS Svelte primitives
