Files
2026-05-08 21:37:11 -04:00

6.8 KiB
Raw Permalink Blame History

The Last Garden — Claude Code Project Guide

A 7-Season browser narrative idle game in the lineage of A Dark Room and Universal Paperclips. Players tend a walled garden at the fraying edge of a world that is being forgotten; the idle loop is the act of remembering.

Source of Truth

Always read these before suggesting changes:

Stack (locked, do not re-litigate)

  • Engine: Phaser 4 (npm create @phaserjs/game@latest — official React + Vite + TypeScript template)
  • UI shell: React 19 (DOM overlay; HUD, journal, dialogue, settings)
  • State bridge: Zustand 5
  • Numbers: break_eternity.js (BigQty wrapper from day one)
  • Narrative: Ink + inkjs
  • Audio: Howler.js (music + ambience), Phaser native (SFX)
  • Save: IndexedDB (via idb) + localStorage fallback + lz-string + versioned schema + Base64 export
  • Content: Markdown+frontmatter / YAML / .ink in /content/, Zod-validated, compiled per-Season at build time
  • Tests: Vitest (sim + migrations) + Playwright (e2e smoke)

Architectural Firewall (load-bearing)

  • Phaser owns the canvas — garden, plants, weather, particles, watercolor post-process.
  • React 19 owns the UI shell — HUD, journal, dialogue overlays, fragment viewer, settings, shop.
  • Zustand bridges them.
  • Simulation core is rendering-agnosticsrc/sim/ does not import from src/render/ or src/ui/. Enforced by ESLint boundary rules in CI.

Banner Concerns (carry forward at every phase)

  1. The story ends but the loop doesn't — the most dangerous structural pitfall. Roothold has a finite ceiling tied to the narrative; design Season 7 end-state before economy code; build a credits/coda rest state.
  2. 7-Season scope eats solo devs — defended by structuring Phase 2 as a plausibly-shippable standalone Season 1 prologue and capping new mechanics at one per Season.
  3. Browser save fragility — multi-layer (IndexedDB + localStorage), versioned, navigator.storage.persist() always called, Base64 export shipped at v1.
  4. System-clock cheating — 24h offline cap, monotonic deltas, story gates on tick count.
  5. AI asset style drift — pinned model + provenance metadata + locked north-star reference set + mandatory human curation gate, enforced from Phase 1.
  6. FOMO mechanics violate cozy tone — anti-FOMO doctrine doc enforced at every UX review (no daily logins, streaks, limited-time, or nag).
  7. Web Audio user-gesture requirement — first screen is a "Tend the garden / Begin" gate that calls AudioContext.resume().
  8. Tab throttling — elapsed-time progression, never setInterval ticking; save on visibilitychange + beforeunload + Season transitions.
  9. Tonal failure — external readers gate every Season's tone before integration; Lura is the warmth anchor.
  10. Authored content / code divergence — single source of truth in /content/, stable string IDs (e.g., season3.canopy.lura_07.vignette), all player-visible strings externalized day one.

Hard Thematic Constraints (Out of Scope by Design)

These are not deferred features — they are excluded because they would undermine the game's argument:

  • No gacha, no lootboxes, no random-drop monetization
  • No narrative gating behind purchase
  • No Season skipping (acceleration only)
  • No daily login bonuses, streaks, or limited-time content
  • No energy / stamina systems
  • No rewarded ads
  • No push-notification spam (Memory Storm opt-in is the only allowed notification)
  • No lore codex or encyclopedia entries (fragments do all world-building)
  • No generic fantasy flora (real species, slightly wrong)
  • No combat, no boss fights (the Archivist is not an enemy)
  • No multiplayer / leaderboards in v1
  • No voiced dialogue in v1
  • No always-online (local-first save model)
  • No named/personality-rich Keeper (player projects onto the system)
  • No hint system / objective tracker

GSD Workflow

This project uses Get Shit Done (GSD) with the following config (see .planning/config.json):

  • Mode: YOLO — auto-approve at decision gates
  • Granularity: Standard (58 phases)
  • Parallelization: plans run in parallel within a phase
  • Models: Opus for research, synthesis, roadmap (Quality profile)
  • Workflow agents: research before planning, plan-check before execution, verifier after each phase

Commands

  • /gsd-discuss-phase N — gather context for phase N before planning
  • /gsd-plan-phase N — create the executable plan for phase N
  • /gsd-execute-phase N — execute all plans in phase N
  • /gsd-verify-work — UAT a completed phase
  • /gsd-progress — situational command: where am I, what's next?
  • /gsd-stats — project metrics

Next Action

Run /gsd-discuss-phase 1 to begin Phase 1 (Foundations & Doctrine).

Code Style

  • TypeScript strict; no any in production code.
  • Player-visible strings are externalized in /content/, never hardcoded.
  • Memory fragment IDs are stable strings (season3.canopy.lura_07.vignette), never numeric.
  • Simulation modules are pure — no Date.now(), no setInterval, no DOM, no fetch. Inject time as a parameter; the tick scheduler owns wall-clock access.
  • BigNumbers go through the typed BigQty wrapper around break_eternity.js. Never raw Decimal values in app code.
  • Save format always carries {schemaVersion, payload, checksum}. Never serialize raw state.
  • New AI-generated assets must carry full provenance metadata ({model_id, checkpoint_hash, prompt, seed, sampler, params}) and pass the curation gate before reaching the manifest.

Tone

This is a contemplative game about loss, memory, and what persists. Code comments and PR descriptions can be functional, but anything player-facing — UI text, error messages, tooltips, the "while you were away" letter — should match the bible's voice: warm, specific, intermittent, sometimes funny, sometimes devastating. Lura is the warmth anchor; write her as the contrast, not a co-griever.