docs: synthesize research findings
This commit is contained in:
@@ -0,0 +1,281 @@
|
|||||||
|
# Project Research Summary
|
||||||
|
|
||||||
|
**Project:** The Last Garden
|
||||||
|
**Domain:** Browser-based narrative idle game (cozy + narrative + idle Venn) — 7-Season prestige arc with AI-assisted asset pipeline, solo/small-team production
|
||||||
|
**Researched:** 2026-05-08
|
||||||
|
**Confidence:** HIGH (stack, features, architecture, save/persistence pitfalls); MEDIUM (AI-pipeline practice, monetization timing, modding posture)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stack at a Glance
|
||||||
|
|
||||||
|
Decisive, opinionated answer. Do not re-litigate in later phases.
|
||||||
|
|
||||||
|
| Concern | Choice | Rationale (one line) |
|
||||||
|
|---|---|---|
|
||||||
|
| **Engine** | **Phaser 4 (v4.1.0+ "Salusa")** | Active stable line in 2026; rebuilt WebGL renderer; ships an official `npm create @phaserjs/game@latest` React + Vite + TypeScript template that removes ~6 months of "build the engine before the game" work. |
|
||||||
|
| **Language** | **TypeScript 5.6+** | A 7-Season game with save migrations across years is TypeScript-mandatory. |
|
||||||
|
| **Bundler / Dev Server** | **Vite 6.x** (Vite 8 + Rolldown when it lands) | ~1.2s cold start vs Webpack ~7s; ships in Phaser 4's official template. |
|
||||||
|
| **UI Framework** | **React 19** (DOM overlay, owns the chrome) | Narrative-cozy audience uses screen readers, copy-paste, browser zoom — canvas-native text fights all of it. Phaser owns the canvas; React owns the UI shell. |
|
||||||
|
| **State Bridge** | **Zustand 5.x** | Single canonical state tree; framework-agnostic; ~1KB; no Redux ceremony. Bridges Phaser scenes ↔ React UI. |
|
||||||
|
| **Numbers** | **break_eternity.js 2.1.3** | TypeScript-native, drop-in successor to break_infinity, supports very small values. Choose day one — retrofitting BigNumber after Season 2 is misery. |
|
||||||
|
| **Narrative Tooling** | **Ink + inkjs** | Writer authors `.ink` in the free Inky editor; runtime streams compiled JSON. Battle-tested for browser narrative (80 Days, Heaven's Vault). Highest-leverage decision in the content pipeline. |
|
||||||
|
| **Save Format** | **IndexedDB (via `idb`) primary + localStorage fallback, lz-string compressed, versioned `{schemaVersion, payload, checksum}`** | Idle saves grow with fragments; multi-layer write survives Safari periodic eviction and Chrome storage-pressure eviction. Always-on `navigator.storage.persist()`. |
|
||||||
|
| **Audio** | **Howler.js 2.2.4** for music + ambience crossfade; Phaser's native audio for SFX | Splits the persistent cello/ambience bed (Howler) from per-scene SFX (Phaser). Howler abstracts the iOS-Safari "must touch first" gotcha. |
|
||||||
|
| **Content Pipeline** | **YAML + Markdown+frontmatter (gray-matter) + `.ink` files in `/content/`, Zod-validated, compiled per-Season at build time** | Writers work in plain text; build fails on schema violations; per-Season chunks lazy-loaded at runtime. Scales to thousands of fragments without a CMS. |
|
||||||
|
| **AI Asset Pipeline** | Pinned model + locked checkpoint + persisted provenance per asset (`{model_id, checkpoint_hash, prompt, seed, sampler, params}`) + locked 10–20 painting "north star" reference set + mandatory human curation gate | Style drift across a 7-Season multi-year project is near-certain without this discipline. |
|
||||||
|
| **Animation** | Frame-sequence PNG atlases (TexturePacker) for ~all plants; Spine + spine-phaser 4.2 only for the 3 named characters *if* skeletal becomes necessary | Watercolor washes don't rig well; image sequences are honest with the medium. Don't add Spine in v1 unless a specific scene demands it. |
|
||||||
|
| **Persistence Backup** | Save export/import (Base64 text) shipped at v1 | Cheapest insurance against browser eviction; standard idle-genre expectation. |
|
||||||
|
| **Monetization Backend** | Cloudflare Worker + KV (or Supabase) + Stripe Checkout, server-authoritative entitlements | Defer until v1.x — ship the game first, monetization second. |
|
||||||
|
| **Cloud Save** | Defer to v1.x (PocketBase if/when needed) | Lineage games shipped without cloud saves; local-first is fine for launch. |
|
||||||
|
| **Tests** | Vitest for sim/economy/migrations; Playwright for e2e smoke | The non-rendering parts of an idle game *must* be unit-tested. |
|
||||||
|
|
||||||
|
### Reconciled Conflict: Rendering Layer
|
||||||
|
|
||||||
|
STACK.md and ARCHITECTURE.md examples disagreed on the canvas tech (Phaser vs PixiJS). **Resolution: Phaser 4 wins, decisively.** STACK.md was more deeply versioned and made the stronger case (active stable line, official React+Vite+TS template, framework-not-just-renderer, Spine-Phaser 4 runtime, mature audio/asset/scene/tween systems out of the box). ARCHITECTURE.md's three-layer firewall pattern (simulation → application → presentation) is renderer-agnostic and survives the swap intact. Read its PixiJS examples as illustrative; substitute Phaser 4 throughout.
|
||||||
|
|
||||||
|
**Operative rule for all future phases:**
|
||||||
|
- **Phaser owns the canvas** — garden, plants, weather, particles, watercolor post-process, Memory Storms.
|
||||||
|
- **React 19 owns the UI shell** — HUD, journal, dialogue overlays, fragment viewer, settings, shop, Keeper's Journal.
|
||||||
|
- **Zustand bridges them.**
|
||||||
|
- **The simulation core is rendering-agnostic** — `src/sim/` does not import from `src/render/` or `src/ui/`. Enforce with ESLint boundaries.
|
||||||
|
|
||||||
|
If a specific watercolor shader needs more than Phaser 4's filter system supports, an auxiliary PixiJS render layer is allowed (Phaser 4's renderer is PixiJS-compatible at the WebGL level), but this is an escape hatch, not the plan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
The Last Garden is three games stacked in a trenchcoat — an idle simulation with offline catch-up, a content-heavy narrative with hundreds of authored fragments and three character arcs, and a watercolor-and-cello aesthetic surface. The job of the architecture and stack is to keep these concerns from colonizing each other. All four researchers converged independently on the same broad shape: a **pure, headless, deterministic simulation core** that knows nothing about the renderer or DOM, a **reactive store (Zustand) bridging simulation and presentation**, **authored content as a build artifact (not code)** validated by Zod schemas and compiled per-Season, and **multi-layer versioned saves** with mandatory `navigator.storage.persist()` and migration framework day one. The recommended stack — Phaser 4 + React 19 + Vite + TypeScript + Zustand + Ink + Howler + break_eternity.js + IndexedDB — is the only combination that satisfies all four pulls (rendering fidelity, narrative density, idle-loop discipline, AI-friendly content pipeline) without inventing infrastructure.
|
||||||
|
|
||||||
|
The single biggest risk is **scope**: a solo / small-team commitment to seven authored Seasons over multiple calendar years. PITFALLS.md flags this as the project-killer ahead of every technical concern. Closely behind: the **structural risk that the story ends but the idle loop doesn't** — *A Dark Room* and *Universal Paperclips* succeeded specifically because they ended; the temptation to graft "endless prestige" onto a finite story will undermine the thematic argument the game exists to make. Other critical risks cluster into a small, well-understood set: save persistence fragility in browsers (Safari eviction, Chrome storage-pressure, private-browsing failures), system-clock cheating that fast-forwards through authored content, AI-asset style drift across model generations, FOMO mechanics that violate cozy tone, the Web Audio user-gesture requirement breaking the cello at first impression, and the canonical content/code divergence trap for narrative games.
|
||||||
|
|
||||||
|
The roadmap implication is unanimous across all four researchers: **Phase 1 must be foundation infrastructure — engine bootstrap + versioned save persistence + content pipeline + AI asset pipeline discipline + tonal doctrine — *before* any Season-content authoring scales.** Save versioning, fragment IDs, asset provenance, and the anti-FOMO doctrine are all retrofit-hostile decisions; they cost ~10 lines on day one and weeks of recovery work after Season 2 ships. The recommended escape hatch on the 7-Season scope commitment is to ship Season 1 publicly as a free, complete-feeling standalone experience that earns the budget and audience for Seasons 2–7 — PROJECT.md commits to v1 having all 7 Seasons but does not preclude shipping Season 1 first as a free prologue. Use that loophole.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Findings
|
||||||
|
|
||||||
|
### Recommended Stack
|
||||||
|
|
||||||
|
See **Stack at a Glance** above for the full opinionated table. Confidence is HIGH on engine + numeric + audio + bundler + state + narrative tooling; MEDIUM on the specific animation runtime (Spine vs PNG sequences — defaulting to PNG for v1) and exact content-pipeline tools (gray-matter is interchangeable; the *shape* is the recommendation); LOW on cloud-save backend choice (defer to v1.x).
|
||||||
|
|
||||||
|
**Core technologies (one line each):**
|
||||||
|
|
||||||
|
- **Phaser 4** — Canvas/WebGL framework: scenes, asset loader, tweens, particles, audio, input. Removes ~6 months of "build the engine before the game" work.
|
||||||
|
- **React 19** — UI shell for narrative chrome (HUD, journal, dialogue, settings). Required for accessibility, screen readers, and copy-paste of fragments.
|
||||||
|
- **Vite 6 + TypeScript 5.6** — Dev server with ~1.2s cold start; type-safety mandatory for save migrations and content schemas.
|
||||||
|
- **Zustand 5** — Single store bridging Phaser scenes and React UI. Tiny, framework-agnostic, no boilerplate.
|
||||||
|
- **break_eternity.js** — Big-number library for prestige economies. Pick day one; retrofitting after Season 2 is rewriting every formula.
|
||||||
|
- **Ink + inkjs** — Branching narrative scripting language with mature web runtime. Writer-friendly authoring tool (Inky), engineering-friendly compiled-JSON runtime.
|
||||||
|
- **Howler.js** — Layered, crossfading music + ambience. Handles iOS Safari autoplay-policy gotchas the cello cannot afford to trip.
|
||||||
|
- **IndexedDB (via `idb`) + lz-string + Zod** — Multi-layer compressed versioned saves with runtime schema validation. The single most defensive system in the project.
|
||||||
|
|
||||||
|
### Expected Features
|
||||||
|
|
||||||
|
**Must have (table stakes — players bounce or one-star without these):**
|
||||||
|
- Core idle loop (plant / wait / harvest memory fragments)
|
||||||
|
- Offline progression simulation with sensible cap (24h recommended)
|
||||||
|
- "While you were away" return screen — *delivered as a letter from the garden, not a stat dump* (tonal differentiator on a baseline feature)
|
||||||
|
- Save persistence (IndexedDB primary, localStorage fallback, multi-layer, versioned, `navigator.storage.persist()` called)
|
||||||
|
- Save export / import (Base64 text) — non-negotiable for browser idle games
|
||||||
|
- Settings menu with separate music / SFX / ambient sliders, master mute keybind, reduced-motion respect
|
||||||
|
- Tab visibility-aware tick logic (elapsed-time-based progression, not `setInterval` ticking)
|
||||||
|
- Multi-buy (x1 / x10 / x100 / Max) for any scaling purchase
|
||||||
|
- Numeric formatting (K / M / B / scientific notation)
|
||||||
|
- FTUE that respects the player (A Dark Room rule: one button at start, expand only when ready)
|
||||||
|
- Accessibility baseline: keyboard nav, text scaling, color-blindness icon redundancy, reduced motion
|
||||||
|
- Tab title / favicon as background indicator
|
||||||
|
- All 7 authored Seasons of content (PROJECT.md commitment)
|
||||||
|
- Three character arcs (Lura, Nameless Man, Archivist) and the final binary choice
|
||||||
|
- Roothold prestige currency (story-bible-locked)
|
||||||
|
- Watercolor + cello aesthetic, palette-shifted by Season
|
||||||
|
|
||||||
|
**Should have (differentiators — the moat):**
|
||||||
|
- Mechanic-as-metaphor design discipline (composting = letting go, prestige = grief, Roothold = what survives)
|
||||||
|
- Discovery-driven progression with no roadmap (A Dark Room / Paperclips lineage)
|
||||||
|
- Authored memory fragment system (every harvest = a piece of writing)
|
||||||
|
- Place-memory vignettes (Season 3+) — short interactive scenes
|
||||||
|
- Memory Storms (Season 4+) — event mechanic with narrative weight
|
||||||
|
- Cross-pollination + ecosystem planting (Season 5+) — true late-Season depth curve
|
||||||
|
- Letter-style "while you were away" return narration
|
||||||
|
- Episodic free additive content patches post-launch (Hollow Knight model)
|
||||||
|
|
||||||
|
**Defer to v1.x (genuine value, not launch-gating):**
|
||||||
|
- Cosmetic monetization catalog (planters, walls, gates, tool skins) — requires asset pipeline maturity; ship game first
|
||||||
|
- Premium Keeper's Journal (annotations layer)
|
||||||
|
- Season acceleration purchase
|
||||||
|
- PWA / installability + opt-in push notifications for Memory Storms only
|
||||||
|
- Cloud save sync
|
||||||
|
|
||||||
|
**Defer to v2+:**
|
||||||
|
- Steam port
|
||||||
|
- Mobile native ports
|
||||||
|
- Localization (defer the *translation*; do NOT defer string *externalization*)
|
||||||
|
- Garden visiting / limited social
|
||||||
|
- Voiced moments (only if cello-and-silence soundscape benefits)
|
||||||
|
- Modding (architecture leaves the door open; don't promise it)
|
||||||
|
|
||||||
|
**Anti-features (do NOT build, hard thematic constraints):**
|
||||||
|
Gacha, lootboxes, narrative gating behind purchase, Season *skipping* (vs accelerating), daily login bonuses, streaks, energy/stamina, rewarded ads, push-notification spam, lore codex / encyclopedia, generic fantasy flora, combat / boss fights, multiplayer/social/leaderboards (v1), voiced dialogue (v1), always-online, named/personality-rich Keeper, hint system / objective tracker, time-skip purchases that bypass real-time-as-metaphor.
|
||||||
|
|
||||||
|
### Architecture Approach
|
||||||
|
|
||||||
|
Three-layer firewall: **Simulation Core (pure, headless, renderer-agnostic) → Application Layer (Zustand store + command bus + event bus) → Presentation Layer (Phaser canvas for the diegetic world + React DOM for the UI chrome)**, with a fourth crosscutting **Data/Persistence Layer** (Content Repository, Save Repository, Asset Manifest, Telemetry, Entitlements) and a build-time **Content Pipeline** (YAML/Ink/Markdown → Zod validation → compiled per-Season JSON).
|
||||||
|
|
||||||
|
**Major components:**
|
||||||
|
|
||||||
|
1. **Tick Scheduler + Offline Catch-up Engine** — Fixed-timestep accumulator at 4–10 Hz. The same `simulate(state, dtMs, commands) → {state, events}` function runs live ticks and offline catch-up (capped at 24h, with `silent: true` flag to suppress per-tick audio/particles during catch-up).
|
||||||
|
2. **Garden Sim / Economy / Season-Prestige State Machine / Memory Fragment Selector / Story Trigger Engine** — Pure modules of typed state and pure functions. No DOM, no Pixi, no fetch. This is the architectural firewall.
|
||||||
|
3. **Game Store (Zustand)** — Reactive snapshot of simulation state. UI binds via selectors. Receives state, never owns logic.
|
||||||
|
4. **Command Bus + Event Bus (mitt)** — Commands flow down (user action → next-tick simulation); events flow laterally (simulation emits → audio + particles + story triggers + telemetry subscribe).
|
||||||
|
5. **Render layer (Phaser scenes)** — Garden, plants, particles, watercolor post-process, ambient effects.
|
||||||
|
6. **UI layer (React DOM overlay)** — HUD, fragment journal, dialogue cutscene player, shop, settings, accessibility menu.
|
||||||
|
7. **Story Cutscene Player + inkjs runtime** — Drives modal dialogue from compiled Ink JSON; sets `simulationPaused` flag during cutscenes; tied to Zustand variables so narrative branches react to game state.
|
||||||
|
8. **Audio Manager (Howler.js)** — Music bus (cello), ambient bus (garden / Pale silence), SFX bus. Crossfades across Season transitions.
|
||||||
|
9. **Save Repository** — Debounced multi-layer writes (IndexedDB primary, localStorage fallback). Format: `{schemaVersion, payload, checksum}`. Forward-migration chain `migrate_v1_to_v2 → ...`. Snapshot-before-migrate backups (last 3 retained).
|
||||||
|
10. **Content Repository + Build Pipeline** — Authored sources in `/content/`, schema-validated with Zod, compiled to per-Season JSON, lazy-loaded at runtime.
|
||||||
|
11. **Entitlements (server-authoritative, deferred)** — Cloudflare Worker + Stripe webhooks. v1.x.
|
||||||
|
|
||||||
|
The persistence model is **event-sourced *internally* (events drive subscribers), snapshot-stored *externally* (saves are world snapshots, not event logs)** — pure event sourcing replays years of history; pure snapshot loses the rich event stream that decouples audio/UI/story.
|
||||||
|
|
||||||
|
### Critical Pitfalls
|
||||||
|
|
||||||
|
The full ranked list lives in PITFALLS.md (14 critical pitfalls). The five most dangerous structural risks, surfaced for ongoing carry-forward:
|
||||||
|
|
||||||
|
1. **The story ends but the idle loop doesn't** — *The most dangerous structural pitfall in the entire project.* Decide before writing economy code: this game **rests** like a finished album you can replay; it does not extend with infinite prestige tiers. Author the Season 7 end state *first*. Cap Roothold to a finite ceiling tied to the narrative argument ("you cannot understand infinitely many things"). Build a credits/coda experience for players who reach the end. Banner concern for every phase.
|
||||||
|
2. **7-Season scope eats the solo developer alive** — Documented failure mode. PROJECT.md commits to "Full 7 Seasons at v1" but does not preclude shipping Season 1 first as a free standalone prologue that earns the budget and audience for the rest. Use that loophole. Cap Season-introduced mechanics (≤1 new system per Season). Quarterly mandatory kill list. Pre-write all authored content in plain text before serious engineering. Plan personal/financial runway around 5–7 calendar years.
|
||||||
|
3. **Save format becomes untenable mid-project** — Versioned saves day one. Migration registry. Multi-layer write (IndexedDB + localStorage). `navigator.storage.persist()` on first save. Snapshot-before-migrate backups. Save export/import as core feature, not power-user feature.
|
||||||
|
4. **AI-generated asset style drift across Seasons** — Pin the model + checkpoint + sampler + library version. Persist provenance per asset. Lock a 10–20 painting "north star" reference set hand-selected by the art lead. Mandatory human curation gate on every shipped asset. Visual regression testing across the full library before any model migration.
|
||||||
|
5. **Players grind past story beats** — Story-gate progression, not just currency-gate it. Pace fragments by reading time, not by harvest count. Defend "acceleration ≠ skipping" ruthlessly when economic pressure arises. Show the garden, not the optimization metrics — if the UI surfaces "fragments per hour," players will optimize; if it surfaces "what Lura said yesterday," they'll inhabit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Watch Out For (Top Pitfalls Banner)
|
||||||
|
|
||||||
|
Surfaced for the roadmapper and every downstream phase. Carry these forward:
|
||||||
|
|
||||||
|
- **Save persistence fragility in browsers** — Safari periodic eviction (WebKit bug 266559), Chrome storage-pressure eviction, private-browsing silent failures, browser-update wipes. Multi-layer + persist() + export feature is the minimum honest answer.
|
||||||
|
- **System-clock cheating trivializes idle progression** — Cap offline progression at 24h. Monotonic timestamp checks; refuse negative deltas. Story beats gate on tick count, not wall time. In a *narrative* idle, fast-forwarding ruins the story experience itself, not just monetization.
|
||||||
|
- **AI asset style drift across model generations** — A 7-Season project will span model rotations. Pinned models + provenance metadata + locked reference set + curation gate, or the watercolor consistency that the project's premise depends on will fracture irrecoverably.
|
||||||
|
- **FOMO mechanics violate cozy tone** — Anti-pattern doctrine in writing: no daily login bonuses, no streaks, no limited-time content, no nag notifications, no loss-aversion copy. Most pressure to add FOMO comes from monetization anxiety; PROJECT.md already locks the monetization scope — defend it.
|
||||||
|
- **Web Audio gesture requirement** — Cello will not play without a user gesture. First screen *must* be a hand-painted "Tend the garden" / "Begin" gate that satisfies the gesture and explicitly calls `AudioContext.resume()`. iOS Safari (including low-power mode) tested before launch. Audio bootstrap is a 1-day fix when planned and a 1-week fire when discovered at launch.
|
||||||
|
- **Tab throttling breaks `setInterval`-driven progression** — Don't simulate progression with timers. Use elapsed-time clock (`f(elapsed_real_time)`, not `f(number_of_ticks_received)`). Save on `visibilitychange` to hidden, `beforeunload`, and Season transitions. Identical behavior between "tab backgrounded" and "tab closed".
|
||||||
|
- **Tonal failure — "cozy with weight" becomes "depressing slog"** — Each Season requires explicit warm/quiet/heavy/lift pacing beats. External readers (2+) sign off on every Season's tonal balance before integration. Lura is the warmth anchor — write her as the contrast, not a co-griever. Endings matter more than middles; Season 7 must land *redemptive*, not pyrrhic.
|
||||||
|
- **Authored content diverges from code** — Single source of truth in `/content/` in YAML/Ink/Markdown. Stable string IDs (`season3.canopy.lura_07.vignette`, never `fragment_274`). All player-visible strings externalized day one — the *translation* can be deferred to v2; *externalization* cannot.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implications for Roadmap
|
||||||
|
|
||||||
|
All four researchers converged on the same phase ordering. The cross-file consensus: **Phase 1 must be foundation (engine bootstrap + save persistence + content pipeline + AI asset pipeline discipline + tonal doctrine) BEFORE any Season-content authoring scales.** Versioning, fragment IDs, asset provenance, and anti-FOMO doctrine are all retrofit-hostile.
|
||||||
|
|
||||||
|
### Phase 1: Foundations & Doctrine
|
||||||
|
|
||||||
|
**Rationale:** Every later phase is blocked without these. Save versioning, content pipeline, AI provenance, and anti-FOMO doctrine are retrofit-hostile decisions that cost ~10 lines on day one and weeks of recovery work later. Architecture firewall (`src/sim/` ↔ `src/render/`) must be enforced before any code grows around it.
|
||||||
|
**Delivers:** Phaser 4 + React + Vite + TypeScript scaffold; ESLint boundaries enforcing the simulation/presentation firewall; versioned save framework with migration registry, multi-layer write, `navigator.storage.persist()`, and Base64 export/import; content pipeline (YAML/Ink/Markdown → Zod → per-Season compiled JSON); AI asset pipeline (pinned model, provenance metadata, locked north-star reference set, curation gate); written anti-FOMO doctrine; written Season 7 end-state design.
|
||||||
|
**Addresses:** Save persistence (table stakes), accessibility baseline scaffolding, content-as-data, AI-assisted production constraint from PROJECT.md.
|
||||||
|
**Avoids:** Pitfall 1 (story-ends-but-loop-doesn't, by deciding the end state up front), Pitfall 3 (save format untenable), Pitfall 5 (AI style drift), Pitfall 8 (storage eviction), Pitfall 9 (FOMO doctrine), Pitfall 10 (content/code divergence), Pitfall 13 (engine choice validated against Season-5 plant-count prototype).
|
||||||
|
|
||||||
|
### Phase 2: Vertical Slice — Season 1 Core Loop
|
||||||
|
|
||||||
|
**Rationale:** The first Season's economy *is* the contract for all subsequent Seasons. If Phase 2 ships pure currency-gating, Phases 3–9 inherit the flaw and retrofit is expensive. Validate the content pipeline end-to-end with real fragments. The simulation-core firewall is stress-tested here.
|
||||||
|
**Delivers:** Pure deterministic simulation core with fixed-timestep accumulator (4–10 Hz); offline catch-up engine capped at 24h with `silent: true` flag; `break_eternity.js` wrapped in a typed `BigQty` abstraction; monotonic clock check (refuse negative deltas, system-clock cheat defense); first Season's authored fragments + memory fragment selector; story-gating *and* currency-gating on progression; first dialogue arc (Lura's introduction) via inkjs; minimal Phaser garden render + React HUD + Zustand store binding; "tend the garden" begin-gesture screen with explicit `AudioContext.resume()`; Howler.js music + ambient + SFX three-bus mixer; save-on-`visibilitychange` and on Season transitions; "while you were away" letter-style return screen.
|
||||||
|
**Uses:** Phaser 4, React 19, Vite, TypeScript, Zustand, break_eternity.js, inkjs, Howler.js, idb + lz-string, Zod, mitt.
|
||||||
|
**Implements:** Tick Scheduler, Offline Catch-up, Garden Sim, Economy, Memory Fragment Selector, Story Trigger Engine, Game Store, Command/Event Bus, basic Phaser render scene, basic React UI shell, Audio Manager.
|
||||||
|
**Avoids:** Pitfall 2 (grind past story — story-gating built in from day one), Pitfall 4 (clock cheating — cap + monotonic check shipped together), Pitfall 7 (BigNumber overflow — wrapped abstraction from first economy commit), Pitfall 11 (audio context blocked — begin gate + `resume()`), Pitfall 12 (tab throttling — elapsed-time clock, no `setInterval` progression).
|
||||||
|
|
||||||
|
### Phase 3: Season-Prestige State Machine + Roothold
|
||||||
|
|
||||||
|
**Rationale:** First major test of save migration and content lazy-loading colliding with simulation state machine. PITFALLS.md and ARCHITECTURE.md both flag this as where most things break in practice. Plan for it to take longer than expected. Validates that v1 → v2 save migrations work on real player data shape.
|
||||||
|
**Delivers:** Explicit 7-Season state machine; Roothold preservation across resets; first save schema migration (Season 1 saves migrate cleanly into Season 2-aware shape); per-Season content lazy-loading; Season transition tonal/audio crossfade; finite Roothold ceiling implementation matching the design-doc end state.
|
||||||
|
**Implements:** Season/Prestige State Machine, save migration framework activation, per-Season content chunking.
|
||||||
|
**Avoids:** Pitfall 1 (finite ceiling enforced in code, not just design doc), Pitfall 3 (real first migration shipped and tested).
|
||||||
|
|
||||||
|
### Phase 4: Watercolor + Cello Polish (Aesthetic Layer)
|
||||||
|
|
||||||
|
**Rationale:** Visual + audio polish layer once the core loop is visible and stable. Don't block earlier phases on shaders. The aesthetic *is* the moat per FEATURES.md.
|
||||||
|
**Delivers:** Watercolor post-process shader (Phaser 4 filter system); particle systems for memory motes, growth animations, ambient drift; per-Season palette + audio bed crossfading; Pale rendered as overexposed white silence with high-tone audio; texture-atlas-packed plant sprites; reduced-motion option respecting `prefers-reduced-motion`.
|
||||||
|
**Avoids:** Pitfall 13 (DOM-heavy garden — confirmed Phaser canvas is in use everywhere it should be), Pitfall 14 (tonal calibration — palette and audio shifts shipped per Season's pacing schedule).
|
||||||
|
|
||||||
|
### Phase 5: Seasons 2–7 Content Authoring + Mid-Season Mechanics
|
||||||
|
|
||||||
|
**Rationale:** Content production is its own track once the pipeline is proven through Season 1. Each Season adds at most ONE new mechanic per the scope-defense doctrine. Parallelizable with later engineering tracks.
|
||||||
|
**Delivers:** Authored fragments and dialogue for Seasons 2–7; place-memory vignettes (Season 3+); Memory Storms (Season 4+); cross-pollination + ecosystem planting (Season 5+); Lura/Nameless Man/Archivist arc completion; final binary narrative choice (Season 7); credits/coda rest-state experience.
|
||||||
|
**Avoids:** Pitfall 6 (scope death — quarterly kill list active, mechanics capped), Pitfall 14 (tonal failure — external reader gate before each Season's integration).
|
||||||
|
|
||||||
|
### Phase 6: Monetization + Backend (v1.x)
|
||||||
|
|
||||||
|
**Rationale:** Independent system; cosmetics don't affect core loop. Ship the game first per FEATURES.md guidance — monetization at launch breeds distrust in the cozy-narrative audience. Server-authoritative entitlements are mandatory (localStorage entitlements = DevTools makes everything free).
|
||||||
|
**Delivers:** Cloudflare Worker + Stripe Checkout + webhooks → entitlements DB; cosmetic catalog (planters, walls, gates, tool skins — garden-coherent only); Premium Keeper's Journal with annotation layer; Season acceleration purchase (accelerates *waiting*, never *skips* content).
|
||||||
|
**Avoids:** Pitfall 9 (FOMO — cosmetic catalog with fixed prices, never gacha; Season acceleration cannot bypass real-time-as-metaphor).
|
||||||
|
|
||||||
|
### Phase 7: PWA + Cloud Save + Polish (v1.x)
|
||||||
|
|
||||||
|
**Rationale:** "Live with it" affordances after launch validates demand. Cloud save resolves the cross-device gap once a real audience exists.
|
||||||
|
**Delivers:** PWA manifest + service worker; opt-in push notifications limited to Memory Storm events only; PocketBase (or equivalent) cloud save sync; additional place-memory vignettes as free additive content patches (Hollow Knight model).
|
||||||
|
|
||||||
|
### Phase 8: Accessibility Audit + Performance + Optional Web Worker Offload
|
||||||
|
|
||||||
|
**Rationale:** Polish, validate, ship beyond v1. The simulation core was designed pure/headless precisely so this offload is a one-day refactor when needed.
|
||||||
|
**Delivers:** Accessibility audit (keyboard nav, screen reader, contrast, motion); performance profiling (Season-5 plant count at 60fps on oldest target hardware); Web Worker offload for the simulation if profiler demands it; mobile testing on actual iOS Safari + Android Chrome devices.
|
||||||
|
|
||||||
|
### Phase Ordering Rationale
|
||||||
|
|
||||||
|
- **Save/load (Phase 1) before render (Phase 2's render slice):** Counterintuitive, but you don't want to discover save bugs after building three Seasons of art. The simulation can be validated headlessly.
|
||||||
|
- **Content pipeline (Phase 1) before Season 1 fragments (Phase 2):** Same reason. If the schema is wrong, every Season's content needs rework.
|
||||||
|
- **AI asset pipeline discipline (Phase 1) before any production-volume asset generation:** Style drift is irreversible at scale; the discipline must precede the volume.
|
||||||
|
- **Tonal doctrine + Season 7 end-state (Phase 1) before any economy code:** PITFALLS.md ranks the "story ends but loop doesn't" pitfall as the most dangerous structural risk. Must be designed first.
|
||||||
|
- **Vertical slice (Phase 2) before Season machine (Phase 3):** Validate the loop and the contract before generalizing to 7 Seasons.
|
||||||
|
- **Aesthetic polish (Phase 4) after the core loop works:** The watercolor shader is the moat, but it's not what makes the loop function — sprite-flat-color is fine for Phases 1–3 if it lets the simulation get right.
|
||||||
|
- **Content authoring (Phase 5) parallelizable with later engineering tracks:** Once the pipeline is proven, the writer can run independently.
|
||||||
|
- **Monetization (Phase 6) deferred:** Ship the game first; monetization second. PROJECT.md and FEATURES.md both endorse this.
|
||||||
|
- **PWA + cloud save (Phase 7) deferred:** Demand validation first; infrastructure second.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Confidence Assessment
|
||||||
|
|
||||||
|
| Area | Confidence | Notes |
|
||||||
|
|------|------------|-------|
|
||||||
|
| Stack | HIGH | Engine, language, state, numbers, audio, narrative tooling all decided with strong source coverage. MEDIUM only on animation runtime (Spine vs PNG sequences — defaulting to PNG for v1) and exact content-pipeline tool names (gray-matter is interchangeable; the *shape* is the recommendation). LOW on cloud-save backend (deferred to v1.x by design). |
|
||||||
|
| Features | HIGH | Genre conventions are well-codified; PROJECT.md is unusually opinionated about tone, which makes the differentiator-vs-anti-feature line unusually clear. The load-bearing judgment was tonal alignment, which the source material strongly supports. |
|
||||||
|
| Architecture | HIGH | Idle-game patterns (pure sim, fixed timestep, snapshot persistence, event bus) are well-documented; narrative-engine integration patterns (Ink runtime + cutscene player) are well-documented. The *combination* is opinionated extrapolation — MEDIUM on the specific bridge between Phaser scenes and React UI, but the broad shape is settled. |
|
||||||
|
| Pitfalls | HIGH | Save/persistence/browser pitfalls are HIGH (well-documented post-mortems and platform docs). Idle game balance pitfalls are HIGH (codified in incremental-game community). Narrative-idle pacing is MEDIUM-HIGH (small-N genre, but specific evidence). AI-pipeline pitfalls are MEDIUM (rapidly evolving practice, fewer post-mortems). Cozy-tone and solo-scope pitfalls are HIGH. |
|
||||||
|
|
||||||
|
**Overall confidence:** HIGH. The stack is decisive, the architecture is defensible, the feature scope is bounded by an unusually clear PROJECT.md, and the pitfalls are concrete enough to gate against in roadmap design.
|
||||||
|
|
||||||
|
### Gaps to Address During Planning
|
||||||
|
|
||||||
|
- **Specific AI asset model + licensing:** STACK.md and PITFALLS.md agree on the *shape* (pinned model, provenance, curation, locked reference set) but the *specific vendor* (Stable Diffusion fine-tune, Scenario, Layer, Midjourney with a licensed agreement, custom-trained LoRA) needs research and legal review during Phase 1.
|
||||||
|
- **Exact tick rate (4–10 Hz range):** ARCHITECTURE.md recommends 4–10 Hz; the right value depends on Season-5 plant-count prototype performance. Pin during Phase 1 prototype.
|
||||||
|
- **Cloud save backend choice:** PocketBase recommended if ≤10K MAU; Supabase if scaling further. Decide based on real player data — local-only is fine for v1 launch.
|
||||||
|
- **Spine vs PNG sequences for the 3 named characters:** Default is PNG sequences for v1 (watercolor doesn't rig well). Reconsider per-character if a specific scene demands skeletal motion.
|
||||||
|
- **Ethical Season acceleration UX:** The line between "accelerates waiting" and "skips content" needs concrete UI specification before Phase 6. Get a doctrine doc before code.
|
||||||
|
- **Anti-FOMO doctrine:** Drafted in PITFALLS.md as a list; needs to be written into a project doctrine document in Phase 1 and referenced at every monetization / engagement design review.
|
||||||
|
- **Telemetry: Plausible vs PostHog:** Either works. Plausible is the cozier-genre fit; PostHog if funnels are needed. Defer until launch nears.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
### Primary (HIGH confidence)
|
||||||
|
|
||||||
|
**Stack:** Phaser 4 release notes (v4.1.0 "Salusa", Apr 2026); Phaser CLI / `@phaserjs/create-game` template; break_eternity.js v2.1.3; Howler.js v2.2.4; inkjs; Spine-Phaser 4 runtime.
|
||||||
|
|
||||||
|
**Architecture:** Fix Your Timestep! (Gaffer On Games); The Idle Game Illusion: How Delta-Time Powers Progress; Anatomy of a video game (MDN); Use Web Workers off the main thread (web.dev); Inkle Ink; Zustand; Event Sourcing (Martin Fowler).
|
||||||
|
|
||||||
|
**Features:** A Dark Room design philosophy (Wikipedia, TV Tropes); Universal Paperclips (stages wiki); Cookie Clicker prestige system; Future of Idle Games (gamertagguru).
|
||||||
|
|
||||||
|
**Pitfalls:** The Math of Idle Games, Part III (Kongregate); WebKit Bug 266559 (Safari periodically erasing storage); Heavy throttling of chained JS timers in Chrome 88; Web Audio Autoplay Policy and Games (Chrome for Developers); Why Scope Is the Most Dangerous Enemy of Indie Games; Scope Creep: The Silent Killer of Solo Indie Game Development.
|
||||||
|
|
||||||
|
### Secondary (MEDIUM confidence)
|
||||||
|
Vite / Webpack 2026 benchmarks; State management 2026 comparisons; PocketBase / Supabase comparison; Cuphead frame-sequence pipeline reference (cited for pattern, not engine); Plausible vs PostHog comparison; Game-localization retrofit cost discussions; Scenario / Layer / Sloyd writeups on AI-asset style drift.
|
||||||
|
|
||||||
|
### Tertiary (LOW confidence)
|
||||||
|
Modding for browser idle games is rare in the wild; recommendations are "leave the door open without paying for it" rather than empirically validated. Specific cloud-save backend choice deferred to post-launch validation against real player numbers. Exact tick-rate within the 4–10 Hz recommended range will require Phase 1 prototype confirmation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Research completed: 2026-05-08*
|
||||||
|
*Ready for roadmap: yes*
|
||||||
Reference in New Issue
Block a user