Skip to content

Architecture

Toaster Chef is server-authoritative — all game and simulation state lives on the Colyseus server. The Phaser 3 client renders state and sends player input; it never directly mutates state.

Stack

Layer Tech
Game client Phaser 3 (browser, TypeScript)
Simulation / multiplayer server Colyseus 0.17.x (Node.js 22, TypeScript)
Shared types shared/ package (@toasterchef/shared)
Map generation rot-js, simplex-noise, custom WFC — server-side only

(A React Native mobile client, toasterchef-mobile, is referenced in the project's architecture notes as a future client surface.)

Server-authoritative model

flowchart LR
    Client[Phaser 3 client] -- "player input" --> Server[Colyseus server]
    Server -- "authoritative state" --> Client
    Server -- "map gen (rot-js, simplex-noise, WFC)" --> MapGen[Map generation — server-side only]

Map generation runs exclusively server-side; clients never run map-generation code. This prevents cheating and ensures all players see the same map. Phaser 3 never runs server-side — it is strictly a browser client. NPC simulation (pathing, hunger decay, life-state transitions, crime events) all runs in Colyseus.

The room lifecycle: a client joinOrCreate('game_room') triggers GameRoom.onCreate(), which builds a GameState, runs MapGenerator.generate() into state.mapData, and starts a 100 ms simulation interval. Colyseus matchmaking spins up additional rooms as they fill (maxClients = 8 per room).

Map generation libraries (all server-side)

  • rot-js — street skeleton, block layout, BSP / cellular automata
  • simplex-noise v4 — heatmaps for poverty / hunger / crime / traffic (use the createNoise2D() API; this is a breaking change from v3)
  • poisson-disk-sampling — natural placement of Kitchen Garages and POIs
  • Custom WFC (Wave Function Collapse), written in-project in TypeScript — neighborhood tile filling

The generator returns a GeneratedMap (tiles, streets, points of interest, neighborhood zones, NPC spawns), serialized to JSON and synced to clients via Colyseus state. Clients render the tiles array as a Phaser tilemap and never re-run generation.

Shared types and the simulation model

Core domain types live in shared/src/types/ and are imported by both client and server:

  • npc.tsNPCState (housing, employment, role, emotional state, hunger, trust, position)
  • trike.tsTrikeState (battery, degradation, pastries, buffs, movement state)
  • resources.tsPlayerResources (money, food, communityTrust), FoodQuality, PastryBatch
  • map.tsMapConfig, PointOfInterest, NeighborhoodZone, GeneratedMap
  • scenario.tsScenarioConfig, SimulationOutcome, domain types (HelpCategory, HelpSeverity, HelpStatus, MPWRAction)
  • simulation.tsCircleSimState, HelpRequestSimState, MPWRLedgerEntry (Layer 2+), SimClock

State syncs from server to client via Colyseus delta encoding; the client listens with room.state.onChange(). Help-request expiry windows are authoritative in code (critical 6h / urgent 24h / routine 72h) and take precedence over documentation.

Three core resources

flowchart TD
    Money --> Food
    Food --> Trust[Community Trust]
    Trust --> Money
  • Money — earned from donations/sales, spent on ingredients, staff, and upgrades
  • Food — produced by Chefs, distributed to the community
  • Community Trust — built by consistent service, lost by waste or neglect; unlocks infrastructure and new areas

Proposed fourth resource: Carbon Footprint

[HYPOTHESIS] design direction — not committed. No code change today; a separate design pass is required before committing.

The three tracked resources could be extended to four with Carbon Footprint — modeled as a cost on production, transport, and energy use, offset by solar generation and reuse credits. This would make sustainability decisions visible in scenario outcomes, consistent with the Sustainability directive. Any carbon insight derived from a scenario run is [SIMULATION OUTPUT], not [PILOT VALIDATED], and does not become validated without real-world Trike or Kitchen Garage deployment data.