[Ratio unlocks 2/2] Frontend: anon lesson mode, horizon locks, claim celebration, funnel events #332

Closed
opened 2026-07-02 02:46:19 +00:00 by spikerj · 2 comments
Owner

Implements the frontend of the #329 design (spike doc on that issue; epic #323). Depends on #331.

  • Anonymous session bootstrap in language-runner: obtain/store anonId (localStorage, beside sandbox state); lesson mode no longer hard-redirects anonymous users to login — within-horizon lessons play through the anon attempt/submit endpoints
  • Route anon completions through the progress-sync outbox pattern pointed at the anon endpoints (offline-queue behavior preserved)
  • Sidebar lock semantics: ratio-locked (beyond horizon) gets a distinct icon + tooltip ("Complete N more to reveal — or sign in and see everything"), separate from the existing prerequisite lock; all titles remain listed
  • Horizon-advance celebration snackbar; quiet persistent sign-in line in the sidebar footer — no modals, no nags
  • Sign-in claim flow: call POST /api/Lessons/progress/claim after first authenticated load when an anonId exists; celebrate the response ("N lessons claimed, badge earned"); clear the anonId
  • Funnel events via activity-tracking: anon-session-created, anon-lesson-completed, unlock-milestone, signup-with-claim
  • E2E: extend the anonymous walk — anonymous visitor completes a free lesson, sees the horizon advance (ties into epic #307's P3/P4 fixtures)

Guardrails from the design: sandbox mode untouched; books/text/videos stay free; the server's horizon is authoritative — the client renders it, never computes it.

Implements the frontend of the #329 design (spike doc on that issue; epic #323). Depends on #331. - [ ] Anonymous session bootstrap in `language-runner`: obtain/store `anonId` (localStorage, beside sandbox state); lesson mode no longer hard-redirects anonymous users to login — within-horizon lessons play through the anon attempt/submit endpoints - [ ] Route anon completions through the `progress-sync` outbox pattern pointed at the anon endpoints (offline-queue behavior preserved) - [ ] Sidebar lock semantics: ratio-locked (beyond horizon) gets a distinct icon + tooltip ("Complete N more to reveal — or sign in and see everything"), separate from the existing prerequisite lock; all titles remain listed - [ ] Horizon-advance celebration snackbar; quiet persistent sign-in line in the sidebar footer — no modals, no nags - [ ] Sign-in claim flow: call `POST /api/Lessons/progress/claim` after first authenticated load when an anonId exists; celebrate the response ("N lessons claimed, badge earned"); clear the anonId - [ ] Funnel events via activity-tracking: `anon-session-created`, `anon-lesson-completed`, `unlock-milestone`, `signup-with-claim` - [ ] E2E: extend the anonymous walk — anonymous visitor completes a free lesson, sees the horizon advance (ties into epic #307's P3/P4 fixtures) Guardrails from the design: sandbox mode untouched; books/text/videos stay free; the server's horizon is authoritative — the client renders it, never computes it.
spikerj added the enhancement label 2026-07-02 02:46:19 +00:00
Author
Owner

Splitting this into two reviewable PRs since it spans critical shared lesson code.

Part 1 (up now): spikersoft-angular#99 — the self-contained, fully-tested foundation:

  • new @spikersoft/platform-anon-session lib (AnonSessionService owns the PII-free localStorage handle + lazy mint; AnonLessonService typed client for horizon/submit/claim via X-Anon-Session)
  • sign-in claim-on-auth in AppComponent (migrate ledger → celebrate snackbar → clear handle → signup-with-claim; retries on failure)
  • sidebar ratio-lock (distinct spark marker + "complete more or sign in" tooltip, horizonLessonNumber input; null = unchanged for authed users) + en/es i18n
  • funnel events anon-session-created, signup-with-claim
  • 11 new tests; nx build spikersoft green

Part 2 (next): the keystone — remove the lesson-mode hard-redirect in the shared LanguageRunner, route within-horizon anonymous play through attempt/anonymous + submit/anonymous across the five runtime adapters, add the anonymous progress outbox, light up the reserved My Journey horizon slot for anonymous viewers, and extend the Playwright anonymous walk. Kept separate because it touches the shared runner base + every adapter and deserves its own focused review.

Leaving this open until part 2 lands.

Splitting this into two reviewable PRs since it spans critical shared lesson code. **Part 1 (up now): spikersoft-angular#99** — the self-contained, fully-tested foundation: - new `@spikersoft/platform-anon-session` lib (`AnonSessionService` owns the PII-free `localStorage` handle + lazy mint; `AnonLessonService` typed client for horizon/submit/claim via `X-Anon-Session`) - sign-in **claim-on-auth** in `AppComponent` (migrate ledger → celebrate snackbar → clear handle → `signup-with-claim`; retries on failure) - sidebar **ratio-lock** (distinct spark marker + "complete more or sign in" tooltip, `horizonLessonNumber` input; null = unchanged for authed users) + en/es i18n - funnel events `anon-session-created`, `signup-with-claim` - 11 new tests; `nx build spikersoft` green **Part 2 (next):** the keystone — remove the lesson-mode hard-redirect in the shared `LanguageRunner`, route within-horizon anonymous play through `attempt/anonymous` + `submit/anonymous` across the five runtime adapters, add the anonymous progress outbox, light up the reserved My Journey horizon slot for anonymous viewers, and extend the Playwright anonymous walk. Kept separate because it touches the shared runner base + every adapter and deserves its own focused review. Leaving this open until part 2 lands.
Author
Owner

Done — merged to master in two parts: pt1 (anon-session foundation, sign-in claim, sidebar ratio-lock) in PR #99, and pt2 (anonymous ratio-unlock lesson play across all tracks: anon-lesson interceptor, progress-sync anon routing, runner anon mode + horizon gating, My Journey horizon overlay, funnel events, E2E) in PR #100. Closing.

Done — merged to `master` in two parts: pt1 (anon-session foundation, sign-in claim, sidebar ratio-lock) in PR #99, and pt2 (anonymous ratio-unlock lesson play across all tracks: anon-lesson interceptor, progress-sync anon routing, runner anon mode + horizon gating, My Journey horizon overlay, funnel events, E2E) in PR #100. Closing.
Sign in to join this conversation.