Skip to content

Therapy Pack MVP — front-page flow + Editor (7.0.0)

1. Summary

Replace the current front page — a six-tool "info dump" (WelcomeView.tsx) that presents the technology and requires an SLP to already know which tool maps to their task — with an outcome-first flow that guides a clinician from a target sound to a therapy-ready, editable, printable pack. This is the app inversion: the pack (a persistent, editable object) becomes the primary surface; the six tools are demoted to an "Advanced" section and become populators that push selections into the pack.

7.0.0 is the first end-to-end slice of the Therapy Packs wedge (PHON-158): type/pick a target → seeded pack → curate in an Editor → export a printable you keep. Billing is designed-but-deferred; the flow delivers value before requiring an account (there are no accounts in 7.0.0).

This is a major release (new primary surface, navigation re-orientation) → version 7.0.0.

2. Why (grounding)

  • Competitive landing research (docs/commercial/2026-07-19-landing-flow-competitive-research.md): SLP-audience pages that convert lead with a prep-time / progress outcome, not features. No SLP competitor offers a guided "what are you targeting?" flow — it is a category differentiator. Winning first-run patterns terminate in seeded, editable work, never a blank tool. A single input box that doubles as a router (Canva pattern) is the lowest-friction first action.
  • Demand data (~/Repos/speech-community-analysis, 92,842-unit Reddit SLP corpus): materials/resources is the centerpiece cluster; phoneme demand is broad-but-bounded — /r/ dominates (3,489 mentions), /s/ (1,479), minimal pairs (510), stopping (486), vocalic /r/ (460); the Word Lists curation already mapped cluster reduction / cycles / apraxia / complexity. Pre-built packs are seeded from this, so breadth ≠ presumption. (Dysphagia is the #1 cluster overall but is out of PhonoLex's phonology scope.)
  • Pricing / positioning (docs/commercial/market-differentiation.md, PHON-178): the psychology to beat is TPT's buy-once-own-forever; the counter is an editable export the clinician owns — which is why the export renderer is a first-class deliverable, not a nice-to-have.

3. Goals / Non-goals

Goals (7.0.0): 1. New outcome-first front page with a target box + pre-built pack gallery + trust line; tools demoted to Advanced. 2. A target resolver (curated, shipped JSON — no runtime embeddings/LLM) with deterministic parsing and a seeded "did you mean". 3. A short guided refine step that seeds a pack from existing APIs. 4. The Editor: a sectioned workspace where curation happens, backed by an IndexedDB "My Packs" library (many saved packs, revisitable) with start-over/new-pack. 5. Light tools→Editor integration: one "Add to Editor" per tool near its export; tools keep their own UX + export. 6. Export: picture cards + worksheet/list + CSV, images where available, word-only fallback. 7. A starter set of pre-built packs from real demand.

Non-goals (explicitly deferred): - Accounts, server-side pack persistence, sharing links. - Billing / paywall enforcement (design the free/Pro line only; §10). - The tight in-tool loop (per-item add + multi-select + pack-chip-everywhere) — data model stays forward-compatible with it. - Target inference from pack contents → suggested additions (data model stays forward-compatible with it). - Audio / Speech Analysis stays entirely outside the pack MVP.

4. Architecture

Front page (new WelcomeView replacement)
  ├─ Target box ──resolver(curated JSON)──▶ resolved target ──▶ Guided refine (position/level)
  │                                                                      │
  ├─ Popular-packs gallery ──(pre-built target spec)────────────────────┤
  │                                                                      ▼
  └─ "Build your own with the tools" ─▶ Advanced tools          Seed via existing APIs
                                             │                   (words/search, contrastive, sentences)
                                             │ "Add to Editor"           │
                                             ▼                           ▼
                                        ┌─────────────────────────────────────┐
                                        │  EDITOR (primary surface)           │
                                        │  Words · Contrasts · Sentences ·    │
                                        │  Notes — curate (remove/replace/…)  │
                                        │  local-draft autosave               │
                                        └───────────────┬─────────────────────┘
                                                        ▼
                                            Export: cards | worksheet | CSV

All orchestration is client-side over existing endpoints (plan §4.6). No new backend service, no new D1 tables required for 7.0.0 (packs live in localStorage).

5. Component designs

5.1 Front page (replaces WelcomeView.tsx)

  • Hero: outcome headline (candidate: "Therapy-ready materials for any speech sound — in minutes.") + subline stating the deliverable.
  • Target box (primary action): placeholder Enter a target — /r/, s-blends, k vs t, final /s/…; empty/focused state renders the popular-packs gallery (collapses "search bar" and "gallery" into one element).
  • Escape hatch: "Or build your own custom pack using the tools →" → Advanced tools.
  • Trust line: evidence-based methodology · privacy · "decision support, not a diagnosis."
  • Tools → Advanced: the sidebar's Build/Analyze/Explore tools move under an "Advanced" grouping; the Editor becomes the primary destination. App_new.tsx null-state renders the front page; a persistent pack indicator (header chip on desktop, bottom drawer on mobile) appears once a pack exists.
  • Returning users → My Packs: the front page surfaces the saved My Packs library (also reachable from the pack indicator) as the fast path back into prior work — this serves the "returner" half of balance-both, alongside the newcomer-facing hero.

5.2 Target resolver

  • Controlled vocabulary shipped as JSON (client-side; no embeddings, no LLM, no round-trip):
  • phonemes + aliases (reuse normalizePhoneme / to_ipa / to_ascii; digraphs th→θ/ð, sh→ʃ, ch→tʃ);
  • positions (initial/medial/final + everyday synonyms);
  • contrast syntax (vs / / / - between two sounds → contrast mode);
  • clusters/blends; phonological-process presets (fronting/stopping/gliding/…) → curated target sets;
  • the named pre-built packs.
  • Deterministic parse → resolved target chip; Build only enabled on a resolved chip.
  • "Did you mean": a hand-seeded near-miss map (e.g. start→initial), always badged as a suggestion, never silently rewriting input. Clinical process names are excluded from fuzzy guessing (everyday-meaning collision) and stay curated.

5.3 Guided refine + seeding

  • After a bare-phoneme resolve, a 1-step refine (position, approximate level/difficulty) — the richer target modes (sound+position, contrast, process preset) from plan §4.2.
  • Seed via existing endpoints:
  • target words → /api/words/search (compileWordFilter), difficulty-ordered by norms (AoA / frequency percentiles), 15–25 candidates (plan §4.3);
  • contrast pairs → /api/contrastive (minimal/maximal/multiple);
  • sentences → /api/sentences.
  • Result assembled into a pack draft and opened in the Editor.

5.4 Pre-built packs (sourcing)

  • Recommended model: a pack is a saved target spec (params) + optional curated overrides (hand-picked words/sentences). Opening it runs the same seeding path as the guided flow, so content stays consistent and fresh; overrides let us guarantee quality starters. (Alternative: fully static JSON — rejected as it duplicates content and drifts from the live lexicon.)
  • Starter set (from demand data): Initial /r/, Vocalic /r/, S-blends, k vs t (fronting), Final /s/ (stopping), Cycles, Apraxia, Minimal pairs. Final list = advisor picks 3–6 (market-diff §7 open item).

5.5 Editor (primary surface)

  • Sectioned workspace (single scroll): header (editable title, target chips, level, counts, autosave state, My Packs, New / Start over, Duplicate, Preview, Export) → Target words (image cards, × remove / replace) → Contrast pairsSentences (target-highlighted) → Clinician notes (prints on the pack).
  • ⟳ replace surfaces Qwensim word-suggestions (word→word similarity via /api/associations/*) — reuses existing infra; its most natural home.
  • Each section has "+ Add from [tool]" which opens the matching Advanced tool.
  • Curate-here principle: adding is generous; pruning/replacing/reordering happens in the Editor.

5.6 Data model + persistence

  • Local-first, IndexedDB-backed pack library. No accounts, no server persistence in 7.0.0. IndexedDB (via a light wrapper — idb-keyval or Dexie, picked at planning) rather than localStorage, because the clinician builds and revisits a growing library of many packs — localStorage's ~5 MB string cap doesn't fit a pack library.
  • "My Packs" library: many saved packs, each autosaved on edit; list view to open / rename / duplicate / delete. A pack is the unit of work you return to across sessions.
  • Start over / New pack: an explicit action to clear the current pack (with confirm) or begin a fresh one without losing saved packs.
  • Schema per plan §4.5 (TherapyPackRequest / TherapyPack), extended with: schemaVersion (migration guard); per-item provenance (sourceTool, why-included) — required so the tight loop and target-inference are possible later without rework; the resolved target(s) stored structurally (not just a title); createdAt / updatedAt.
  • Keep all content non-patient-specific (privacy posture) — copy reminds users packs live in their browser and must not carry patient identifiers.

5.7 Tools ↔ Editor (Light integration)

  • Each of the six tools keeps its UX and its own export (the Editor is an additional destination, not a replacement).
  • Each gains one "Add to Editor" control near its export that pushes the tool's current results into the active pack; a uniform contract across tools (works for word grids, contrast pairs, sentences, a single Lookup word, a Text-Analysis extraction — "add these results" maps everywhere, unlike per-card buttons).
  • Confirmation toast with Undo. Pack indicator updates.

5.8 Export

Grounded in docs/commercial/2026-07-19-slp-worksheet-conventions-research.md, with one deliberate deviation recorded here: that research found adult materials favor real photos, but PhonoLex uses AAC symbols (Mulberry + OpenMoji) for all ages and treats them as preferable to real photos. AAC symbol sets are designed for iconicity — including abstract concepts that photographs represent poorly — which is exactly the vocabulary range therapy targets span. So imagery is unified across age bands; the pediatric/adult difference lives in format options, not image style. (A real-photo mode stays a possible future toggle if adult confrontation-naming demand appears — not in 7.0.0.)

Shared imagery — Mulberry/OpenMoji from R2 where available (~22K words post-PHON-185); word-only fallback (existing imageless policy). These are CC BY-SA — the per-image attribution key MUST flow into the exported PDF footer (ship policy in packages/data/src/phonolex_data/runtime/images.py). Never emulate Boardmaker/proprietary symbol art.

Formats (each a client-side–rendered PDF, plus CSV): - Picture cards — cut-out grid; label above image (toggle above / below / none — the none option covers adult confrontation-naming); grid-ladder presets 2×2 (4), 2×3 (6), 3×4 (12), 4×5 (20), default 12 / 20; bordered cells = cut lines + "print on cardstock / laminate" note; contrast mode = adjacent-cell pairs supporting the 6 initial + 6 final = 24-card convention. - Worksheet / listheader fields (Name · Date · Goal/Target · Clinician · Cue level — the difference between "printable" and "chartable"); default 10-item data block (n/10 = %) with per-item trial boxes + __/__ = __% + cue-level column (I/min/mod/max), or a whole-page "/N" score box; three stacked sections words → sentences (bold/underlined target) → optional passage; two-column contrast-pair block; caregiver home-practice footer. - CSV — machine-readable superset: word, IPA/phonemes, position, syllable_count, CV-shape, contrast-partner, carrier sentence, has_image.

Two convenience presets (they only preset the options above — imagery is identical AAC symbols): - "Kids" — labeled cards, position-organized (initial/medial/final), carrier-phrase sentences, trial-tally data, playful copy. - "Adult / medical" — optional unlabeled cards, word lists ordered by syllable complexity (mono → bi → multi) then word → phrase → sentence, functional sentences + optional script/stress + optional CVCV / nonword drill row (phonology layer generates these), accuracy-gated (80%) + cue-level data, functional copy.

PDF generationdecided: client-side PDF renderer (@react-pdf/renderer or pdfmake; final pick at planning) for deterministic, image-embedding output.

6. Analytics (PHON-168 taxonomy, via lib/analytics.ts track())

landing_view, target_resolved (target, method: box|gallery|tool), pack_seeded, add_to_editor (tool), pack_edited, export (format), plus the existing funnel events. No patient-identifying content.

7. IA / routing / version

  • New front page replaces the activeTool === null null-state; Editor becomes a primary, linkable surface (introduce a route so a pack is bookmarkable/reloadable). Tools grouped under "Advanced" in AppSidebar.tsx.
  • Version bump to 7.0.0package.json (single source of truth via config/product.ts), AppHeader chip, About drawer, index.html/structured data, docs (per version-bump checklist).

8. Monetization boundary (design only; deferred)

  • Free tier with real value (plan §5.1; "one or two complete packs" framing). Because there are no accounts in 7.0.0, nothing is enforced — 7.0.0 is effectively all-free; we only design where the line will be:
  • Likely-free: build/edit/export, unlimited local drafts, export carries a subtle "Made with PhonoLex" footer (doubles as distribution).
  • Likely-Pro (later): remove footer, premium/age-band formats, cloud save + share, higher volume.
  • Price test already set: $149/yr, $99 founding (market-diff §5). Do not build billing until willingness-to-pay is tested after observed use (plan §4.6, Week 5).

9. Affected files (indicative)

  • Replace packages/web/frontend/src/components/WelcomeView.tsx; edit App_new.tsx (routing/null-state/pack indicator), AppSidebar.tsx (Advanced grouping).
  • New: front page, target-resolver module + vocab JSON, guided refine, Editor + pack store (localStorage), pack indicator/drawer, export renderer, pre-built pack specs, "Add to Editor" in each tool.
  • Reuse: lib/wordFilter.ts, /api/words/search, /api/contrastive, /api/sentences, /api/associations/*, lib/normalize.ts, config/product.ts, lib/analytics.ts.

10. Decisions (resolved 2026-07-19)

  1. PDF approach — ✓ client-side PDF renderer (@react-pdf/renderer / pdfmake; final pick at planning). (§5.8)
  2. Pre-built pack sourcing — ✓ target-spec + curated overrides, materialized via live APIs. (§5.4)
  3. Free/Pro line — ✓ designed boundary in §8 confirmed (free = build/edit/export + "Made with PhonoLex" footer; Pro-later = remove footer, premium formats, cloud save/share). Not built in 7.0.0.
  4. Imagery — ✓ AAC symbols (Mulberry/OpenMoji) for all ages, preferable to real photos (iconicity for abstract concepts); real-photo mode dropped from 7.0.0 scope. (§5.8)
  5. Persistence — ✓ IndexedDB-backed multi-pack "My Packs" library + start-over. (§5.6)

Minor, at planning: IndexedDB wrapper (idb-keyval vs Dexie); final PDF lib pick.

11. Decomposition → implementation phases (feeds writing-plans)

Ordered by dependency (the Editor + data model is the spine): 1. Pack data model + IndexedDB "My Packs" store + Editor shell (sectioned workspace, add/remove/replace/reorder, autosave, library open/rename/duplicate/delete, start-over). 2. Export renderer — two age-band presets (kids picture cards + adult word/reading) × formats (cards/worksheet/CSV) + PDF. The owned artifact. 3. Front page + resolver + guided refine + seeding (the new entry). 4. Pre-built packs (starter set). 5. Tools → "Add to Editor" (light integration across six tools) + pack indicator/drawer. 6. IA/nav (Advanced grouping) + 7.0.0 version bump + analytics wiring.

12. Research inputs (complete)

Both spikes are done and their findings are folded into this spec: - Landing-flow competitive research → docs/commercial/2026-07-19-landing-flow-competitive-research.md (§2, §5.1). - SLP worksheet-conventions research → docs/commercial/2026-07-19-slp-worksheet-conventions-research.md (§5.8 — decided the two age-band presets).

13. Testing

  • Resolver unit tests (aliases, contrast syntax, did-you-mean gating, process-name exclusion).
  • Pack store tests (schema versioning/migration, autosave, provenance).
  • Seeding integration (guided target → correct API bodies via compileWordFilter).
  • Export snapshot tests (card + worksheet + CSV; image vs word-only fallback).
  • "Add to Editor" contract test per tool.
  • Frontend type-check + lint + build; workers unchanged (no API changes expected).

14. Risks

  • Scope: this is the full MVP flow; phases §11 must ship incrementally behind the new front page.
  • Export quality is load-bearing (monetization wedge) — the PDF-approach decision matters.
  • Image coverage gaps make some cards word-only; acceptable per imageless policy but set expectations in copy.
  • Seeding quality: guided defaults must produce a genuinely good starter pack or the "value before account" promise fails; lean on norm-ordered difficulty + curated overrides for pre-built packs.

15. Amendment 2026-07-20 — Editor cards + word-linking + quick-add (post-Phase-3 live-review)

After Phases 1/1b/2/3 shipped on the branch, a live walkthrough surfaced editor gaps against §5.5 and refinements to §5.7. Decisions (approved 2026-07-20):

  • §5.5 was under-built: Target words must render as picture cards, not text rows. Phase 1b's PackItemCard is text-only; the spec always said "image cards." The editor renders each target word as an AAC picture card (image where available via wordImageUrl/WordImageThumb, word-only fallback) with × remove / replace.
  • Words link to the lexicon (the "not linking words to word cards" gap). Added/seeded/typed words resolve to their lexicon entry at add-time and store ipa + image on the pack item, so the pack is self-contained (instant cards, export needs no re-fetch). PackWord gains imageFile? / imageProvider? (additive, optional — no schema-version bump). Phase 3b's mapWordToPackWord is updated to persist image_file/image_provider from the search response (it currently drops them, keeping only hasImage). A resolveWordForPack(word) helper (over the existing /api/words/batch or /api/words/:word) backs manual-add resolution; a word not in the lexicon stays word-only.
  • Quick-add on every section (interim + permanent), alongside Phase 5's "+ Add from [tool]". The Phase-1b manual add existed only on Words; make it consistent:
  • Words — type a word → resolve → picture card.
  • Contrasts — two small word fields (Word A / Word B) → a pair; each word resolved to a card; label defaults to the pack target or blank.
  • Sentences — one free-text field → the sentence; target words auto-highlighted (surface words containing the pack's target sound; none when no target). The per-section "+ Add from [tool]" (§5.5) remains the richer Phase-5 path; quick-add is the "just say what you want" path and does not replace it.
  • §5.7 refinement — "Add to Editor" is a pack-picker. Instead of always pushing to the active pack, the tool control presents a dropdown of the user's saved packs (default: active pack, plus "New pack…") so a selection can be added to any of several packs. Same word→lexicon linking applies to tool-added words.

Re-sequencing of remaining phases (§11): the editor card/linking/quick-add work is foundational (a PackWord data-model change + core editor display that pre-built packs and tool-add both ride on), so it lands before pre-built packs: 1. Editor cards + word-linking + quick-add (this amendment) — picture cards, PackWord image fields, resolveWordForPack, quick-add on all three sections, seeding stores image refs. 2. Pre-built packs (former Phase 4) — now display cards for free. 3. Tools → "Add to Editor" (former Phase 5) — with the pack-picker dropdown + linking. 4. IA/nav "Advanced" grouping + 7.0.0 bump + analytics taxonomy (former Phase 6).