Living Word — First-Run Tutorial + Just-in-Time Teaching — Acceptance Spec
Status: MERGED + LIVE on prod 2026-06-05 — PR #765 squash-merged (ad032337). Verified
tsc + unit 18/18 + Playwright 10/10 (desktop+mobile) on the preview; screenshots captured for
the founder feel-check. CI-wiring of the unit test (test.yml) remains a one-line founder
follow-up (OAuth workflow scope).
Status (original): APPROVED (design) — founder ruled the 4 foundational decisions 2026-06-05. Wave: 4 (Reach & retention) — conversion/retention track (roadmap: "interactive first-run tutorial … the single biggest popularity unlock for a cold player"). Author: orchestrator, 2026-06-05. Rule #17 gate: satisfied by the rulings below.
1. Goal
A cold player — a child, or a 65-year-old Sunday-school teacher — opens Living Word for the first time and is gently shown how to play, then taught each new mechanic the first time it appears. Today there is an intro screen and scattered hints, but no real onboarding and no teaching for the novel verb gestures, Word Cards, or the toolbar (audit 2026-06-05). This converts more of the reach we build later into retained players.
2. Founder rulings (baked in)
- Diegetic / in-world teaching — no blocking modal coach-mark cards. Teach via the existing on-canvas prompt line + Scribe Eden (the existing scene-entry guide) + a glow/halo around the next thing to do. In-context DOM highlight on the toolbar is acceptable (it is not a blocking overlay).
- Essentials + just-in-time — first run teaches move / interact / toolbar; then the FIRST time each new mechanic appears, a one-time hint teaches it, remembered so it never repeats.
- Skippable + Help replay — auto-runs on first session with a clear Skip; a "How to play" entry lets anyone replay it / read a controls reference afterward.
- Accessibility folded in — the tutorial is screen-reader friendly and reduced-motion-aware, AND we fix the two pre-existing gaps the audit found (intro animations ignore reduced-motion; the on-canvas prompt line is not announced to screen readers).
3. Current state (audit, verified 2026-06-05)
- Intro (
LivingWordIntro.tsx) shows EVERY visit (founder direction);introDismissedis NOT persisted. NohasCompletedTutorialflag anywhere. - Hints today: initial on-canvas feedback line
"Drag the screen to walk. Tap a scribe to talk. (Desktop: WASD + E.)"(LivingWordAdventure.tsx~L5816, drawn at ~L4703); per-verbarmedHints(explorer/verbs/*, shown only when a beat arms); Scribe Eden welcome dialogue;QuickPlayHintBanner(the ONLY persisted hint —useGameplayModelocalStoragehintSeen). - Verb gestures (witness=long-press, gather=taps, trust/cross=walk-into, plant/name/build/forgive)
are "learn by doing" — no teaching before a beat arms. Toolbar has icon +
aria-labelonly. - Input detection:
useIsTouchDevice(). Reduced-motion:useReducedMotion()exists but intro animations don't use it. Noaria-liveanywhere; the canvas feedback line is invisible to AT. - Reusable:
DialogueModal,ToolPanel, particle pool +drawArmedBeatHalo/drawSabbathVignette(explorer/explorer-render.ts),useTypewriter,MobileTouchControls,FiveActsHudChip. - Save:
LWProgressSnapshot(hooks/useCloudSave.ts) — all-optional, localStorage + cloud.
4. Design
4.1 First-run walkthrough (diegetic, essentials)
Triggers once for a player with no tutorial flag, on first entry into Eden after the intro is dismissed. A small step machine drives the existing prompt line + a highlight on the current target. Each step ADVANCES on the real action (not a timer), so the player learns by doing:
- Move — prompt adapts to input: touch → "Drag anywhere to walk"; desktop → "Use WASD or the arrow keys to walk." Advance once the player has moved ~2 tiles.
- Interact / talk — glow Scribe Eden; prompt "Walk to the guide and press E" (desktop) / "tap the guide" (touch). Advance when the dialogue opens.
- Your tools — brief in-context highlight (pulse) on the toolbar: "Your tools live here — switch scenes, track progress, and study. Open them any time." Advance on open or dismiss.
Then set the persisted flag (§4.4). A Skip affordance is visible throughout; skipping also sets the flag. The whole flow respects reduced-motion (no pulsing/halo animation when set — fall back to a static outline + the text prompt).
4.2 Just-in-time micro-tutorials (each shown once)
The FIRST time each mechanic is reached, show a one-time teaching beat, then never again:
- Each verb gesture — when a verb beat first arms, show a fuller first-time teach of THAT
gesture (extend the existing
armedHint) + a brief "well done" confirmation on success. Per-verb seen flag (witness, gather, plant, name, trust, build, forgive, cross). - First Word Cards encounter — a one-time line explaining "play a card that answers the
falsehood" before the first
WordCardsEncounter. - First scene exit/portal — a one-time "walk to the gate to continue the story" hint.
All gated by seen-flags; dismissible; never repeat. Existing armedHints remain as the
always-on fallback for later encounters.
4.3 "How to play" reference + replay
- A "How to play" entry reachable from the toolbar (in the Study or Account panel, or a small help affordance) opens a concise, fully screen-reader-readable controls reference: movement (both input types), interact, the verb gestures with their gestures, the toolbar tools.
- It offers "Run the walkthrough again", which re-triggers §4.1 (and may reset the §4.2 seen-flags so a returning teacher can re-see the gesture teaches — founder default: replay only the §4.1 essentials; leave §4.2 flags set unless "reset all tips" is chosen).
4.4 Persistence (anonymous-safe)
- localStorage-backed set of seen keys + a
firstRunTutorialDoneflag (mirrors theQuickPlayHintBannerpattern) so it works for anonymous guests. Mirror to a new optionalLWProgressSnapshot.tutorialSeen?: string[](+firstRunTutorialDone?: boolean) so signed-in players keep their state across devices. All optional → backward-compatible.
4.5 Accessibility (folded in — §2 ruling)
- Add ONE visually-hidden
aria-live="polite"region that mirrors the current teaching prompt / feedback line, so screen readers announce each step and every dynamic feedback update (this also fixes the standing "canvas feedback line not announced" gap). - All tutorial animation (halo pulse, highlight) is gated by
useReducedMotion()→ static fallback. Also wrap the intro animations (shimmer / lamp glow / mote drift inLivingWordIntro.tsx) in the reduced-motion guard (the audit's flagged gap). - Input-adaptive copy via
useIsTouchDevice()everywhere (tap vs press E; drag vs WASD).
5. Acceptance criteria (expected outputs)
- A brand-new player (no flags) gets the diegetic first-run walkthrough (move → talk → tools), input-adapted, with a working Skip.
- Completing OR skipping sets the persisted flag; the walkthrough does NOT auto-run again on reload / next session.
- The first time a verb gesture arms (and the first Word Cards encounter, and the first scene exit), its one-time teach shows; it does NOT show the second time.
- "How to play" is reachable from the toolbar, shows the full controls reference, and re-runs the walkthrough.
- Screen reader: an
aria-liveregion contains the current step / feedback text; the controls reference is fully readable. - Reduced-motion: with the OS pref set, no nonessential animation plays in the tutorial OR the intro (text/static fallback instead).
- Works for an anonymous guest (persists per-device); mirrors to cloud when signed in.
- No regression to the intro,
QuickPlayHintBanner, per-verbarmedHints, or gameplay.
6. Verification (rules 10, 12, 20 — and the founder's "can you test this" question)
- Playwright on the deployed preview, desktop AND mobile projects (the config has both):
first-run steps advance on real input; Skip works; reload does not re-trigger (flag persisted);
a verb just-in-time teach fires once then not again; "How to play" opens + replays;
reduced-motion emulation (
reducedMotion: 'reduce') hides animation; thearia-liveregion holds the step text. Assert BEHAVIOR + change over time, not just DOM presence (feedback_verify_behavior_not_dom_presence). - Screenshots captured at each tutorial step (desktop + mobile) for the founder's final "does this actually feel intuitive" check before merge.
journey-runnerpersona pass — run a non-technical persona (e.g. "Pastor Ruth") against the preview to evaluate "would she know what to click?" — the closest automated proxy for intuitiveness. Honest limit: automated checks prove it WORKS and show how it LOOKS; the final feel judgment is the founder's (or a real first-time user's).- DECISION_LOG line; knowledge-sync per rule #16. No
product_knowledgechange expected. - Player-facing copy is mostly mechanical (low theology risk); any Scribe-Eden voice additions are flagged for founder review at the PR (founder owns the in-world voice).
7. Scope / deferred
- v1 (this spec): first-run walkthrough + just-in-time mechanic teaches + "How to play" reference/replay + persistence + the accessibility fixes above.
- Deferred: sprite-sheet art, a full interactive sandbox level, voiced narration, analytics on tutorial drop-off (could add a lead-gen event later).