Architecture · LikeC4
Ember Tide
A backend-free, single-screen cooperative deck-builder — React 19 + Zustand + Vite compiled to a static bundle, state in memory only, no accounts and no tracking
The whole picture
System landscape
The system in context, then opened up into its containers.
Ember Tide — system landscape
index
Ember Tide — containers (content → engine → store → UI, with art, gates & build)
embertideSystemA backend-free, single-screen cooperative deck-builder — React 19 + Zustand + Vite compiled to a static bundle, state in memory only, no accounts and no tracking
Moving parts — evolving, dev-time & planned surfaces
movingPartsInside each box
Containers & components
Each part decomposed into the components that implement it. Every box links to its source in the interactive explorer.
Rules engine — pure combat + economy resolver
engineContainersrc/core + src/rules — combat and economy as functions over explicit state with no Zustand imports, so the rules stay unit-testable in isolation. Deterministic via seeded RNG; returns new state, never mutates
State store — Zustand slices at the edges
storeContainersrc/store — the single source of truth, kept at the edges so the engine stays pure. Domain-partitioned slices mutate board state by composing engine output; the store imports the engine, never the reverse
React board — single-screen UI
uiContainersrc/ui — a single-screen co-op board. Pure view + dispatch: components read Zustand hooks and fire actions on tap/drag; no game logic lives here. 44px tap targets, icon-first cards, rules text sized never to clip
Art pipeline — SVG composer + fal.ai raster panels
artContainersrc/illustration + scripts — a hybrid pipeline: a deterministic SVG composer assembles the structural leaded-glass layers, and a fal.ai briefing system generates reproducible 2K raster panels. Card art falls back composer → committed raster
Quality gates — balance, accessibility & e2e
gatesContainerThe constraints that keep the game shippable and six-year-old-readable: balance simulations, contrast/touch-target accessibility checks, and Playwright e2e — all run on every change
How it runs
Walkthrough flows
Dynamic views — the narrative spine of the system, step by step.
Walkthrough — a tap becomes new state
playFlowThe clean spine in motion. A tap is a dispatch; the store composes the pure engine output into board state; Zustand notifies subscribers and the view re-renders. No game logic lives in the UI, and the engine never imports the store.
Walkthrough — rendering stained-glass art
artFlowA hybrid pipeline. The deterministic SVG composer always produces structural leaded-glass layers; where a reproducible 2K raster panel exists (generated offline from a committed fal.ai prompt and cached in git), the renderer prefers it. Nothing calls fal.ai at runtime.
Walkthrough — the quality gates
gateFlowBalance and readability are correctness properties, not polish. Every change runs balance simulations against the pure engine (win rate in a 40–70% band) and contrast/touch-target checks against the UI; a hosted-CI deploy guard keeps the build local-household only before it ships to the website.
Explore it live
The figures above are static exports. The interactive explorer lets you pan, zoom, follow relationships, and jump from any box to the source.