Living Word Daily Puzzle — Wordle-style Bible Word Game
Wave-1 growth lever from the Living Word deep-dive plan. The narrative game is the destination; this is the daily habit + share loop that feeds it. Generosity is the conversion strategy — the puzzle must be fully valuable even if no CTA is ever clicked. Every doorway honors the AI Bridge Principle and appears only at the earned-trust moment AFTER the puzzle is finished, never during play.
§1. What it is (one paragraph)
A once-per-day, no-login, ~30–60-second word puzzle. The player guesses a hidden Bible word in 6 tries; each guess returns per-letter feedback (green = right letter+spot, yellow = in word wrong spot, gray = not in word) — the Wordle mechanic players already know. The same puzzle is served to everyone each day. After the board is finished (solved or out of guesses), the player sees a short teaching reveal that ties the word to Scripture, a spoiler-free shareable result card (emoji grid), and a single tasteful doorway into the narrative game + ChurchWiseAI. One play per day; revisiting shows the finished board, not a replay.
§2. Founder decisions (D1–D5) — ALL SIGNED OFF 2026-05-30
Resolved: D1 = (a) 5-letter Wordle-style · D2 = answer bank + teaching copy APPROVED · D3 = churchwiseai.com/living-word/daily, doorway → from-living-word · D4 = (a) streak with grace days · D5 = (b) API source of truth. Launch date set to 2026-06-15 (DAILY_LAUNCH_ISO). The table below preserves the original options + recommendations for the record.
| # | Decision | Options | Recommendation |
|---|---|---|---|
| D1 | Puzzle mechanic | (a) 5-letter Wordle clone; (b) variable-length (4–8); (c) a more Bible-distinct variant (guess-the-figure / verse-completion / "Babel" anagram) | (a) 5-letter Wordle-style. Proven viral format, instantly familiar, cleanest share grid, "buildable in days." Bible distinctiveness comes from the answer bank + teaching reveal, not a novel mechanic. Variant ideas → backlog for a v2 "mode." |
| D2 | Answer-bank curation | Founder reviews the seed bank + per-word teaching reveals (content depth, needs theological eye) | Engineering seeds ~60 family-safe, meaningful 5-letter biblical words (names, places, concepts) with verse + 1-line reveal; founder reviews/edits before first real play. No caveated/contested figures (mirror project_sermon_voice_rotation exclusion policy). |
| D3 | Route + share domain | /living-word/daily on churchwiseai.com; share URL host = churchwiseai.com vs livingword.bible | Play at churchwiseai.com/living-word/daily; share link points to the same canonical play URL. Doorway CTAs route to churchwiseai.com/from-living-word (mirrors Phase-1B Decision B1). Revisit if livingword.bible becomes the marketed front door. |
| D4 | Streak mechanic | (a) on, with grace days; (b) on, no grace; (c) off for v1 | (a) on, with grace days, never guilt. Founder ethic is pull-not-guilt (plan §Retention). Streak is visible + celebratory; a missed day is forgiven by 1 grace day before reset; NO push/guilt notifications ever. |
| D5 | Answer delivery | (a) date-seeded selection in client bundle (offline-ready, answer inspectable); (b) /api/living-word/daily returns the day's word (rotatable without redeploy, enables server-side play impression) | (b) API source of truth, client-cached. Grounds it in the existing quizzes/lead-gen route pattern, lets the bank rotate + log a server-side daily_play like other lead-gen events. Note: per-letter coloring needs the answer client-side once fetched (low-stakes free game — acceptable, same as Wordle's own model). PWA wave later adds a bundled offline fallback. |
§3. Scope (LOCKED)
In scope for v1:
- New self-contained route
/living-word/daily(does NOT mount the narrative engine — separate, lightweight, fast). - New API
GET /api/living-word/daily[?date=YYYY-MM-DD]returning the day's puzzle metadata + answer (see §6). - The puzzle board, on-screen + physical keyboard input, per-letter feedback, 6-guess limit.
- Teaching reveal after finish; spoiler-free share card; one earned-trust doorway block.
- localStorage persistence: today's board, one-play-per-day lock, streak (D4), guess distribution.
- Telemetry: new
daily_play/daily_complete/daily_share_click/daily_cta_clickevents tolw_lead_gen_events. - Page metadata +
LearningResource/GameJSON-LD for SEO/GEO. - Accessibility: colorblind/high-contrast mode, reduced-motion, keyboard, screen-reader guess announcements.
Out of scope (do NOT build in v1): accounts/leaderboards; multiplayer; the variant modes from D1(c); email capture inside the puzzle; A/B copy testing; the scene-level SEO landing pages (separate Wave-1 item); PWA/offline (Wave-4); cross-promo from PewSearch/SermonWise (later phase); founder analytics dashboard (Phase 1C of lead-gen).
§4. Core gameplay (LOCKED — assumes D1 = 5-letter Wordle-style)
- Answer: one hidden 5-letter Bible word per day, same for all players (§6 determinism).
- Guesses: up to 6. Each guess MUST be 5 letters. Guess validation: accept any 5-letter A–Z string (do NOT hard-reject non-dictionary words in v1 — a dictionary gate adds maintenance + frustration; revisit if abuse appears). Empty/short guesses are rejected inline ("Not enough letters") without consuming a turn.
- Per-letter feedback (Wordle rules, including duplicate-letter handling):
- Green: letter is correct and in the correct position.
- Yellow: letter is in the word but in a different position — but only as many yellows/greens as there are occurrences of that letter in the answer (standard Wordle duplicate logic: greens consume first, then yellows left-to-right up to the count).
- Gray: letter not in the answer (or all occurrences already accounted for).
- On-screen keyboard reflects best-known state per letter (green > yellow > gray, never downgrades).
- Win: all 5 green → board freezes on a solved state, teaching reveal + share + doorway appear.
- Loss: 6 guesses without solving → board freezes, the answer is revealed in the teaching reveal, share + doorway appear.
- One play per day: after finish, the board is read-only for the rest of that calendar day; reload shows the finished board + reveal + share (NOT a fresh game).
§5. Daily determinism & puzzle numbering (LOCKED)
- Launch epoch: a fixed
DAILY_LAUNCH_DATEconstant (UTC midnight) is "Puzzle #1". - Puzzle number =
floor((todayUTC - launchUTC) / 1 day) + 1. - Answer index into the ordered bank =
(puzzleNumber - 1) % bank.length. Ordered, deterministic, no randomness (Math.random/Date.noware unavailable in some build contexts anyway — selection is pure arithmetic on the date). - "Today" is UTC for the canonical puzzle so every player worldwide shares the same #N and shares compare cleanly. The UI MAY show a local-time "next puzzle in HH:MM:SS" countdown but the puzzle identity is UTC-keyed.
- Bank size ≥ 60 at launch so a repeat is ≥2 months out; bank can grow before any wrap.
§6. API — GET /api/living-word/daily (LOCKED; assumes D5 = (b))
- Query: optional
?date=YYYY-MM-DD(defaults to today UTC). Out-of-range/future dates clamp to today. - Response (200, JSON):
{"puzzleNumber": 42,"dateUtc": "2026-05-30","length": 5,"answer": "EXILE","reference": "Psalm 137:1","teaching": "By the rivers of Babylon, Israel wept in exile — and God's promise to bring them home never broke.","sceneId": "babel","season": null}
answeris returned uppercase.sceneId(nullable) links the word to a narrative scene for the doorway "play the full story" deep-link.season(nullable:advent|lent|eastertide|…) reserved for the future liturgical loop; v1 ignores it.The route fires a server-sideAMENDED 2026-06-10 (QW-2 funnel repair): the route no longer logsdaily_playlead-gen event on each fetchdaily_play— the s-maxage edge cache meant the handler only ran on cache misses, massively undercounting plays.daily_playnow fires CLIENT-side fromDailyPuzzle.tsxon the first puzzle interaction of the day (localStorage day-keylw-daily-play-fired= once/day/device), viatrackLeadGenEvent(). Do NOT re-add server-side lead-gen logging to this cached GET.- Caching:
Cache-Control: public, s-maxage=…until next UTC midnight so Vercel edge serves it cheaply; the client also caches the day's payload in memory + localStorage. - The answer bank lives in
src/app/living-word/data/daily-answer-bank.ts(typed array; D2 founder-reviewed). The route imports it; no DB table needed for v1 (a DB-backed bank is a later optimization).
§7. Teaching reveal (LOCKED shape; D2 content)
Shown only AFTER the board is finished. Contents:
- The word (revealed; on a loss this is how the player learns the answer — no shame framing).
- The
reference+ the 1-lineteachingfrom the API. - A quiet "Puzzle #N · come back tomorrow" line + local-time countdown to the next puzzle.
Tone: warm, teacherly, never preachy, never an NPC voice. This is authored-by-the-builders content, consistent with the AI Bridge Principle (it is not a character speaking).
§8. Share card — spoiler-free (LOCKED)
- Trigger: a "Share" button in the finished state.
- Payload (text, copied to clipboard / passed to
navigator.share):Living Word Daily #42 4/6⬜🟨⬜⬜⬜🟨⬜⬜🟩⬜🟩🟩⬜🟩⬜🟩🟩🟩🟩🟩https://churchwiseai.com/living-word/daily- Line 1:
Living Word Daily #<N> <guesses>/6(loss =X/6). - Emoji grid: one row per guess actually made; greens/yellows/grays mirror the board. High-contrast mode swaps 🟧/🟦 for 🟨/🟩 (colorblind share, like Wordle).
- NO letters, NO answer, NO teaching text in the share — spoiler-free is non-negotiable.
- Final line: the canonical play URL (D3).
- Line 1:
- Behavior: mobile uses
navigator.sharewhen available; desktop copies to clipboard + shows a "Copied!" toast. Either path firesdaily_share_click(metadata:{ puzzleNumber, result: 'win'|'loss', guesses }). - Optional (nice-to-have, not blocking): an
/api/ogimage variant for richer link unfurls — still spoiler-free (shows the emoji grid + brand, never the word).
§9. Brand doorway (LOCKED — honors AI Bridge + the 3 rules)
A single doorway block appears in the finished state, BELOW the share button. Never above; never mid-puzzle; never an NPC voice.
- The 3 brand-doorway rules (from the plan): (1) the puzzle is valuable even if no CTA is clicked; (2) cross-sell only at earned-trust moments to the right person; (3) lead-gen never contaminates the puzzle's voice.
- Content (placeholder — founder may refine copy):
Loved today's word? Walk the whole story — the same word lives in a scene of Living Word, the free narrative Bible game. [Play the full story →]
Built by ChurchWiseAI — the studio behind the AI characters, voice agents, and chatbots that help churches answer their people 24/7. [See what it does for ministry →]
- CTA 1 (in-product, primary): links to the narrative game at
/living-word. (The game does NOT support a?scene=deep-link — it only honorslwAllowTeleport/lwExplorerPreviewtest params — so we link to the journey start, not a mid-game jump.sceneIdis carried in telemetry only, not the URL.) Firesdaily_cta_click(metadata{ target: 'narrative', sceneId }). - CTA 2 (brand doorway):
https://churchwiseai.com/from-living-word?utm_source=living-word&utm_medium=daily&utm_campaign=daily-v1&puzzle=<N>. Firesdaily_cta_click(metadata{ target: 'cwa', puzzleNumber }).target="_blank" rel="noopener noreferrer". - Styling consistent with Phase-1B doorways: stone/navy, sacred-gold accent, Inter body, NOT animated, never jarring.
§10. Persistence & streak (LOCKED shape; D4 governs streak on/off)
localStorage keys (namespaced lw-daily-*):
lw-daily-state—{ puzzleNumber, dateUtc, guesses: string[], status: 'in_progress'|'won'|'lost' }. Gate: on load, if storedpuzzleNumber≠ today's, start fresh (and run the streak transition below); else restore the board.lw-daily-stats—{ played, wins, currentStreak, maxStreak, lastCompletedPuzzle, distribution: {1..6}, graceUsed: boolean }.- Streak transition (D4 = on, grace days): on completing puzzle N, if
lastCompletedPuzzle === N-1→currentStreak++; if=== N-2and!graceUsed→ keep streak, setgraceUsed=true(one grace forgiveness per gap); else →currentStreak = 1.graceUsedresets after a clean consecutive day. UpdatemaxStreak. Never surface guilt language; a broken streak shows a gentle "Welcome back" not "You lost your streak." - No server-side persistence of stats in v1 (privacy + simplicity); only the anonymized
daily_*funnel events go tolw_lead_gen_events.
§11. Telemetry (LOCKED — extends both LeadGenEventType unions)
Four NEW event types added to BOTH src/lib/living-word/lead-gen-client.ts and src/lib/living-word/lead-gen.ts (the unions must stay in sync — they are duplicated by design):
| Event | When | Fired from | Metadata |
|---|---|---|---|
daily_play | first puzzle interaction of the day (AMENDED 2026-06-10, QW-2 — was "puzzle fetched"/server, which undercounted behind the edge cache) | client (DailyPuzzle.tsx, once/day/device via lw-daily-play-fired) | { puzzleNumber, source } |
daily_complete | board reaches won/lost | client | { puzzleNumber, result, guesses } |
daily_share_click | share button used (either path) | client | { puzzleNumber, result, guesses } |
daily_cta_click | a doorway CTA clicked | client | { puzzleNumber, target, sceneId? } |
Client events use trackLeadGenEvent() (no direct fetch). All best-effort; telemetry NEVER breaks play.
§12. Accessibility (LOCKED)
- High-contrast / colorblind mode toggle (orange/blue instead of yellow/green), persisted in
lw-daily-prefs; share grid honors it. prefers-reduced-motion: no tile-flip / shake animations; state changes are instant.- Full keyboard play (physical keys + Enter/Backspace); on-screen keyboard buttons are real
<button>s witharia-labels including current letter state. - Each evaluated guess is announced to screen readers via an
aria-live="polite"region (e.g., "Row 3: E correct, X absent, I present, L correct, E absent — 3 of 5 correct"). - Board cells have accessible names; the finished state moves focus to the teaching reveal heading.
- Contrast meets WCAG AA in both color modes.
§13. Anti-goals (LOCKED — load-bearing)
- NO login / account / email capture to play or to see results. Frictionless is the whole point.
- NO CTA, ad, or brand interruption DURING the puzzle. Doorway is finished-state only.
- NO spoilers in the share card — no letters, no answer, no teaching text. Ever.
- NO "limited time" / "act now" / streak-guilt / fake-urgency copy anywhere.
- NO push notifications, no guilt-nudges. Streak is celebratory pull, never punitive.
- NO NPC-voiced cross-sell; the doorway is plainly builder-authored.
- NO third-party tracking pixels; first-party
lw_lead_gen_eventsonly (anonymized IP hash). - NO contested/caveated biblical figures or doctrinally divisive words in the bank without founder sign-off.
- NO mounting the heavy narrative engine on this route —
/living-word/dailymust be fast + self-contained. - NO randomness in answer selection — pure date arithmetic so every player shares the same #N.
§14. Acceptance criteria
Functional MUSTs
- Same calendar day (UTC) → identical puzzle #N and answer for every player/device.
- 6-guess limit enforced; per-letter feedback matches Wordle rules including duplicate-letter logic.
- Win and loss both freeze the board and reveal teaching + share + doorway; loss reveals the answer.
- One play per day: reload after finish restores the finished board, never a replay; an in-progress board restores its guesses.
- Share card is spoiler-free, shows the correct emoji grid +
#N x/6+ canonical URL; honors high-contrast mode. - All four
daily_*events log tolw_lead_gen_eventswith the specified metadata. - Doorway CTAs route as specified (narrative deep-link + churchwiseai.com/from-living-word with
utm_campaign=daily-v1). - Streak increments on consecutive days, forgives one gap via grace day, resets otherwise; no guilt copy.
- Page renders + is playable at 320–768px (mobile) and 768–1280px (desktop); reduced-motion + colorblind modes work.
LearningResource/GameJSON-LD present and valid in page head.
Anti-tests (engineering MUST verify explicitly)
- No CTA or brand element is in the DOM while
status === 'in_progress'. - Share clipboard/
navigator.sharepayload contains NO answer letters and NO teaching text. - Answer selection is identical across two machines with clocks set to the same UTC day, and differs by exactly one index across consecutive UTC days.
- No CTA routes to a non-churchwiseai.com host.
- No urgency/guilt strings ("limited time", "act now", "don't lose your streak", "X left") anywhere in the route.
- Telemetry failure (network blocked) does NOT break play or finish.
§15. Test plan
Unit / integration
- Duplicate-letter feedback matrix: answer
LEVELvs guessEAGLE,LLAMA,BELLE→ assert exact green/yellow/gray vectors. - Determinism:
puzzleNumber(date)+ index for launch day, +1 day, +bank-length day (wrap) → expected indices. - Streak FSM: consecutive, 1-gap (grace), 2-gap (reset), grace-reset-after-clean-day.
- Persistence: in-progress restore; finished restore (read-only); new-day reset.
- Share string builder: win 3/6, loss X/6, high-contrast variant — exact strings, no letters present.
Playwright E2E (on the deployed preview, per CLAUDE.md rule 20)
- Happy-path solve: type guesses to a win → board solved, teaching reveal + share + doorway visible,
daily_complete(result win) logged. - Loss path: 6 wrong guesses → answer revealed, share shows
X/6. - One-play-per-day: finish, reload → finished board restored, not replayable.
- Spoiler-free share: click Share → intercept clipboard/share payload → assert no answer letters, correct emoji grid, canonical URL.
- Doorway routing: click each CTA → narrative deep-link
/living-word?scene=…; brand CTA → churchwiseai.com/from-living-word withutm_campaign=daily-v1. - No mid-game CTA: during play, assert doorway not in DOM.
- A11y: keyboard-only solve; reduced-motion no-animation; colorblind toggle changes board + share emoji.
§16. Founder go/no-go gate (after v1 ships)
v1 is DONE and a v2 (variant modes / DB-backed bank / liturgical seasons) is cleared when:
- Puzzle live at the D3 route, answer bank D2-signed-off.
- 7 days of
daily_*data captured. - Measurable repeat play (returning-device rate) and at least some
daily_share_clickvolume (the plan's 90-day bar starts here). - Zero spoiler leaks and zero brand-misalignment complaints in founder review.
§17. Deferred (NOT v1)
- Variant modes (guess-the-figure, verse-completion, anagram) — D1(c) backlog.
- DB-backed answer bank with an admin authoring UI.
- Liturgical/seasonal bank tagging surfaced (Advent/Lent themed weeks) — schema field
seasonexists, UI deferred. - PWA/offline bundled-bank fallback (Wave-4).
- Scene-level SEO landing pages (separate Wave-1 item, own spec).
- Founder analytics dashboard for the
daily_*funnel (lead-gen Phase 1C).
End of spec. Engineering may begin §3–§11 immediately against a placeholder bank. The shipped answer bank + teaching copy (§6/§7) and the streak/route/delivery choices gate on founder sign-off of D1–D5 (§2) before the first real play goes to production.