How stakeengine/web-sdk works
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 Workspace · lines Lines · cluster Cluster · caddyfile Static host
Components 23
Root
Workspace-level tooling, shared config, and static deployment
- Workspace · Monorepo orchestration and shared scripts
pnpm-workspace.yaml - Static host · Simple static deployment boundary for built app assets
caddyfile
Apps
Playable SvelteKit game applications
- Lines · Base line-game implementation with Pixi-driven board and Storybook scenarios
apps/lines - Cluster · Cluster/tumble game variant with bonus and win-flow composition
apps/cluster - Scatter · Scatter/tumble variant with multiplier and board-specific mechanics
apps/scatter - Price · Variant with sticky and expanding wild mechanics plus superspin flow
apps/price - Ways · Ways-style game application sharing the common runtime model
apps/ways - Number Picker · Reduced game app showing the same core state and event patterns
apps/number-picker
Packages
Reusable runtime, UI, and infrastructure packages
- Storybook · Interactive validation environment for components, events, and full books
packages/components-storybook - Pixi Svelte · Svelte bindings and primitives for PixiJS 8 rendering
packages/pixi-svelte - UI Pixi · Pixi-based HUD, buttons, labels, and responsive in-canvas UI
packages/components-ui-pixi - UI HTML · HTML/Svelte modals, menus, settings, and dialog overlays
packages/components-ui-html - Game Control · Shared XState game lifecycle utilities and app state machines
packages/utils-xstate - Event Bus · Typed emitter and Svelte context wiring between logic and components
packages/utils-event-emitter - Book Runtime · Sequencing and execution helpers for books and bookEvents
packages/utils-book - Layout · Canvas sizing, orientation, and viewport state helpers
packages/utils-layout - Sound · Audio player helpers for loops, music, and one-shot playback
packages/utils-sound - Slots Utils · Reel, tumble, and board enhancement helpers for slot-style mechanics
packages/utils-slots - Shared Utils · General helpers such as sequencing, random, wait, and win level utilities
packages/utils-shared - Shared State · Cross-app Svelte state for bet, modal, sound, UI, and config state
packages/state-shared - Shared Consts · Cross-app constants such as colors, bet values, timing, and z-index
packages/constants-shared - RGS Client · Client helpers for fetching and shaping RGS/math responses
packages/rgs-fetcher - Tooling Config · Reusable ESLint, TS, Vite, Storybook, Svelte, and Lingui configs
packages/config-ts
Connections 48
- 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