Context. surface customer · domain tara · route /domains/tara/courses/[id] · auth signed-in · source apps/oshun/web/src/app/domains/tara/courses/[id]/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; 2026-06-29 targeted Playwright course-detail coverage added for shipped route anatomy, enrollment transition, section accordion, lesson overlays, quiz pass/fail scoring, missing-course fallback, and scoped axe scan. Evidence: apps/oshun/web/e2e/tara-course-detail.spec.ts
Purpose#
Dynamic course-detail surface in the /domains/tara/* namespace. Renders one
Tara meditation course identified by the URL segment, with sections, lessons,
enrollment flow, learning objectives, quiz interface, completion certificate,
and per-lesson resources.
Entry points#
- Course list / collections / search — surfaces under
/domains/tara/*link here with the course id - Direct URL / bookmark — yes;
params.idflows directly intoTaraCourseDetailPage - Domain back-stack —
router.back()wired intoonBack
Layout regions#
page.tsx is a 'use client' thin wrapper that reads params.id via
useParams<{ id: string }>() and renders
<TaraCourseDetailPage courseId={courseId} onBack={() => router.back()} />.
Inside TaraCourseDetailPage (TaraCourseDetail.tsx):
- Header / back affordance — back button, course title
- Format badge —
FORMAT_COLORS[course.format](daily / weekly / self- paced / scheduled / live) with the appropriate icon - Course meta — duration, lesson count, enrollment count, completion rate, average rating, difficulty
- Hero CTA — Enrollment / Continue / Completed CTA reflects
EnrollmentStatus(not-enrolled → enrolled → in-progress → completed) - Learning objectives — list of stated objectives
- Section accordion — one accordion per
TaraCourseSectionwith progress bar; expands to showTaraCourseLessonrows - Lesson row — icon by
LESSON_TYPE_ICONS[lesson.type](meditation / video / article / exercise / quiz / reflection / discussion), status bySTATUS_COLORS[lesson.status](locked / available / in-progress / completed) - Lesson resources panel — supporting materials for the active lesson
- Reflection prompts — reflection cards
- Quiz interface — multiple-choice / true-false with submit and review; scores produce a quiz-results card
- Completion certificate — full-page certificate when the course is complete
(
Trophyicon)
States#
- Course found —
SIMULATED_COURSES.find(...)returns a record; hero + sections render - Course missing (unknown id) — friendly inline empty state renders with
Course not foundand the domain back affordance - Enrollment status: not-enrolled — enrollment CTA visible
- Enrollment status: enrolled — local click transition enters
enrolledbefore auto-advancing - Enrollment status: in-progress — "Continue where you left off" CTA with progress percent
- Enrollment status: completed — certificate screen + share/download affordance is not route-reachable with current course fixtures
- Lesson status branches — locked (no entry) / available (Play) /
in-progress (Continue) / completed (
CheckCircle2) - Quiz answered correctly / incorrectly — result card copy and score attributes verified for 0% fail and 100% pass
- Course rating display — shows
Starrating + average score - Reduced motion —
./fixturesemulates reduced motion and the scoped course-detail accessibility test runs against the settled route root
Interactions#
Header#
- Back (button) — calls
router.back()viaonBack; direct header click still needs a browser assertion
Course hero#
- Enroll (button,
not-enrolledstate) — flips state toenrolled, then localin-progress - Continue / Start lesson (button) — opens the next available lesson
- Download certificate / Share (
Download,Share2icon buttons) — visible only after completion; completion fixture absent today - Resume CTA — uses local fixture progress today; persisted progress contract still needs BFF coverage
Section accordion#
- Section header row (button) — toggles open/closed; chevron rotates
- Per-section progress bar — non-interactive progress attributes verified
Lesson row#
- Lesson click
- When
status === 'locked':aria-disabled="true"and does not open an overlay - When
status === 'available' | 'in-progress': opens the lesson resources panel - When
status === 'completed': opens the completed quiz for review/retry
- When
Quiz#
- Multiple-choice options — radio-style selection
- True/false options — two-option selection
- Submit (button) — scores and reveals results
- Retry — no explicit retry button; re-opening a completed quiz starts a fresh attempt and is browser-covered
Resources / reflection prompts#
- Resource link — current resource/download/share controls are display-only disabled buttons until real downloads/shares are wired
- Reflection prompt — no available reflection lesson exists in current fixtures; all reflection rows are locked
Data & contracts#
- Reads:
SIMULATED_COURSESfrom@/lib/tara/tara-simulation-data- Content types from
@/lib/tara/content-types:TaraCourse,TaraCourseSection,TaraCourseLesson,LessonType,LessonStatus,CourseFormat,EnrollmentStatus
- Writes: enrollment + progress state are local to this component today
- Realtime: None.
- Caching: client-only
- Auth/role check: shell middleware
- Route param:
params.id: string— no decode in the page wrapper
Current E2E evidence#
apps/oshun/web/e2e/tara-course-detail.spec.tsopens/domains/tara/courses/tara-course-001, verifies the in-progress course anatomy, stats, objectives, teacher card, section progress, lesson statuses, disabled resource actions, section toggling, failed quiz scoring, passed quiz scoring, and unknown-course fallback.- The same spec opens
/domains/tara/courses/tara-course-003, verifies the not-enrolled state, clicks enroll, observes the localenrolled→in-progresstransition, and opens the first available lesson. - The scoped accessibility test runs axe against
[data-tara-course-detail="tara-course-001"]under reduced motion. apps/oshun/web/e2e/tara-teacher-pages.spec.tscovers a real teacher-profile course link intotara-course-001and browser back to the profile.
Cross-references#
- Sibling Tara routes:
- Component sources:
apps/oshun/web/src/components/domains/tara/TaraCourseDetail.tsxapps/oshun/web/src/lib/tara/tara-simulation-data.tsapps/oshun/web/src/lib/tara/content-types.ts
- Feature spec:
V1/features.md#tara
Open questions / known gaps#
- Confirm the BFF endpoint that hydrates real course content; currently
SIMULATED_COURSESis local fixture data - Document the persistence target for enrollment status and lesson progress (client vs. BFF)
- Verify how the certificate share / download interacts with the user's Library — should completed courses surface there automatically? Current fixtures do not expose a completed course state.
- Confirm whether the friendly inline missing-course state is the intended product behavior or whether this route should use a Next not-found page.
- Add a fixture or harness for an available reflection lesson if the reflection journal hand-off should be route-tested before BFF content exists.