Context. surface customer · domain tara · route /domains/tara/programs · auth signed-in · source apps/oshun/web/src/app/domains/tara/programs/page.tsx
Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; content re-verified 2026-06-03 against current source; 2026-06-29 targeted Playwright coverage added for browser lists, selected-card detail, programId deep links, missing programId fallback, local enrollment, current/locked day rows, day detail, header back, milestone state, and scoped axe scans. Evidence: apps/oshun/web/e2e/tara-programs.spec.ts
Purpose#
Browser for multi-day / multi-week Tara meditation programs. Lists enrolled "My
programs" and all available programs; selecting one opens ProgramDetailView
with daily structure, meditation, quote, intention, activities, milestone
markers, and a progress bar.
Entry points#
- Tara hub — verify the cross-link from
/tara - Deep link with program selection —
?programId=<id>pre-selects a program viauseBrowserSearchParams().get('programId') - Direct URL / bookmark — yes
- Domain back-stack —
router.back()wired intoonBack
Layout regions#
page.tsx is a 'use client' thin wrapper that:
- Reads
programIdfromuseBrowserSearchParams() - Renders
<TaraProgramsBrowserPage onBack={() => router.back()} initialProgramId={initialProgramId} />
Inside TaraProgramsBrowserPage (TaraCollections.tsx):
- Sticky header — back button, "Programs" heading, "Multi-day structured journeys" subtitle, Calendar icon
- My programs section —
myPrograms = SIMULATED_PROGRAMS.filter(enrolled === true); only visible when at least one enrollment exists - All programs grid —
SIMULATED_PROGRAMScards - Program detail view — when
selectedProgram !== null, replaces the browser with<ProgramDetailView>showing day-by-day plan, milestones, and progress
States#
- Browser (no selection) —
selectedProgram === null; My programs + All programs visible - Detail view (selected via card) —
selectedProgram !== null; browser hidden - Detail view (deep link) —
initialProgramIdmatches a program; the effect on[initialProgramId]rehydrates selection on URL change - Initial program id missing —
SIMULATED_PROGRAMS.find(...) === null; falls through to the browser - No enrolled programs — My programs section hidden
- Milestones reached — static milestone reached/unreached state in
ProgramDetailView - Reduced motion — shared Playwright fixture emulates reduced motion; scoped browser/detail axe scans run against settled roots
Interactions#
Header#
- Back (button) —
router.back()viaonBack
My programs section#
- Program card — sets
selectedProgram; reveals detail view - Progress bar inside card — non-interactive
progress * 100fill
All programs grid#
- Program card — same selection behavior
Program detail view (ProgramDetailView)#
- Back inside detail — clears
selectedProgram - Day row — opens the day's meditation, quote, intention, activities
- Mark day complete — no shipped control exists to flip
ProgramDay.completed - Milestone celebration — crossing a milestone is not currently route-drivable because day completion cannot be changed in the UI
- Enroll — non-enrolled program starts locally and locks future days
- Un-enroll — no shipped un-enroll control exists
Data & contracts#
- Reads:
SIMULATED_PROGRAMS(in-file fixture fromTaraCollections.tsx)
- Writes: enrollment + day completion state are local to the component today
- Realtime: None.
- Caching: client-only
- Auth/role check: shell middleware
- Query param:
programId(string | null) — read once, applied viauseEffect([initialProgramId])
Current E2E evidence#
apps/oshun/web/e2e/tara-programs.spec.tsopens/domains/tara/programs, verifies the no-selection browser state, two enrolled cards in "My Programs", three cards in "All Programs", card enrollment/current-day/progress state, and selection intotara-prog-001.- The same spec verifies
tara-prog-001detail state, reached and unreached milestones, current/completed/locked day rows, the day-4 detail view's quote, intention, meditation, activities, locked day non-entry, and detail back. - It opens
/domains/tara/programs?programId=tara-prog-002to prove deep-link hydration, then/domains/tara/programs?programId=tara-prog-missingto prove missing IDs fall back to the browser. - It opens non-enrolled
tara-prog-003, clicks Start Program, verifies local enrollment/current-day update and future-day locking, and opens day 1. - It verifies header
router.back()by navigating from/domains/tarato/domains/tara/programs, then clicking the route header back button. - It runs scoped axe scans against
[data-tara-programs-browser]and[data-tara-program-detail="tara-prog-001"].
Cross-references#
- Sibling Tara routes:
- Component sources:
apps/oshun/web/src/components/domains/tara/TaraCollections.tsx(TaraProgramsBrowserPageline 2013)
- Feature spec:
V1/features.md#tara
Open questions / known gaps#
- Confirm whether deep-link
?programId=should update the URL when the user selects a program from a card (current page reads the param on mount but does not propagate selection back to the URL) - Document the persistence target for enrollment + day completion. Current enrollment is local component state; no day-complete write exists.
- Confirm the BFF endpoint for programs once it lands; today
SIMULATED_PROGRAMSis local fixture data - Verify milestone celebration accessibility if a real day-complete action ships; current UI only displays static reached/unreached milestone chips.