Replace the lesson showcase with the Schedule Rush onboarding game + activation-funnel fixes - #3036
Merged
Merged
Conversation
… dead verify flow The web app has no /login route (auth is modal-only via ?auth=), so any SuperTokens-generated website link 404'd. /day resolves and preserves search params through its redirect. Email verification was only half wired (web recipe with no backend recipe, and no ?auth=verify modal view), so the web-side init and dead verify branches are removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
…Auth redirects Mobile users could complete the whole keyboard walkthrough (it paints over MobileGate) only to be told to open Compass on a desktop; the overlays now never mount on a mobile OS so the gate shows first. google_oauth_redirect_started marks 'left for Google' so abandoned OAuth round trips are distinguishable from silent failures on return. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
…game The 12-step lesson takeover taught shortcuts one lecture at a time and users bailed before finishing. Schedule Rush keeps the same sandbox, takeover shell, entry points, and storage contract, but turns practice into one 90-second run: a fixed queue of ten scheduling tasks (create, typed quick-times, nudge, edge resize, delete, undo) placed against a dashed ghost slot, with scoring, speed bonuses, and streak multipliers. Time-up is a soft landing onto the same end screen as a clear. The end screen fixes the inverted signup funnel: the old graduation step stripped every signup affordance, so finishing the demo could never produce a showcase-sourced signup. Anonymous players now get signup as the primary CTA (Enter), with the calendar, replay, and the reminders opt-in beside it. The pure game reducer takes every timestamp as an argument, so a full winning run scripts in unit tests without fake timers. Analytics gain per-task shown/completed events plus run started/finished payloads; shortcut_showcase_step_completed is retired. The mid-run resume-step key now stores an in-progress sentinel: any stored value (legacy lesson ids included) re-offers the game from its one-screen how-to card. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
The Playwright run also caught a real-browser bug the unit tests could not: seatFocus parked focus on the Skip button during a run, so the lock-in Enter activated Skip to sign up. Mid-run focus now sits on the takeover region itself, keeping Enter and Tab as game verbs. The end screen's N reminders shortcut no longer requires focus off a button. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
…e-redesign-bhkzva
The HUD timer refactor left remainingMs with no callers; knip fails CI on unused exports. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
…n Sep 1 The recurrence Ends on picker opened at today's month when no end date was chosen (react-datepicker falls back to today with a null selection), which put it months away from the event being extended and made the past-midnight regression test time out the moment the real-world month rolled past its August fixture. It now opens at the event's own month. The booking prefetch e2e assumed arriving on the next month always prefetches the month after it, but with the 60-day horizon that month is unreachable early in a calendar month (Sep 1 + 60d lands before Nov 1). The spec now lets any arrival prefetch settle and asserts the horizon rule instead of a fixed fetch count. Both failures reproduce identically on origin/main today; they are ported here to get this PR's CI green and will no-op once main carries an equivalent fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
Contributor
Author
|
CI status note: the
Both fixes are ported into this branch (commit 9626b38) to get CI green and will no-op once Generated by Claude Code |
…e-redesign-bhkzva # Conflicts: # e2e/booking/public-booking.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Onboarding wasn't landing: analytics showed zero onboarding completions even from newly activated users, and session recordings surfaced four distinct causes. This PR addresses all four:
1230, Shift+Arrow nudges, Tab edge resize, Delete, Mod+Z undo), played with the real KEYMAP verbs on the same sandbox grid. Tetris analogues: a piece queue with next-piece preview, a dashed ghost target slot, lock-in flashes, score/speed-bonus/streak multipliers, and a soft time-up landing (score stands, replay offered).signup_started {source:"shortcut_showcase"}now fires from the completion path, not just early bail-outs.websiteBasePathpointed at/login, a route that does not exist (auth is modal-only via?auth=), so SuperTokens-generated links 404'd into the pirate screen. It now points at/day, which resolves and preserves search params. The half-wired email-verification recipe (web-only init, dead?auth=verifybranch, no backend recipe) is removed so both ends agree.isMobileOS()before mounting onboarding, so phone users completed the whole walkthrough underneath which satMobileGatetelling them to come back on a desktop. The onboarding trio no longer mounts on mobile — the gate (waitlist + copy-link) shows first, and no seen-flags get burned on a phone.Plus
google_oauth_redirect_started {intent}fires right before the Google redirect, so abandoned OAuth round trips are distinguishable from silent failures on return.Analytics notes for dashboard owners:
shortcut_showcase_step_completedis retired; the game emits richershortcut_game_run_started,shortcut_game_task_shown,shortcut_game_task_completed, andshortcut_game_replayed, andshortcut_showcase_finished/skippedgained outcome/score/phase payloads.onboarding_game_started,checklist_shown,onboarding_task_completed) never existed in this codebase — dashboards referencing them are querying nothing.Simplicity
The showcase package keeps its public store API byte-compatible (all 8 external call sites — RootShell, WelcomeModal, CommandPalette, auth callbacks, FirstEventPrompt — compile untouched), its storage keys, entry points, app-lock/focus-trap takeover shell, and the FirstEventPrompt handoff. The 12-branch lesson ladder, step metadata, phase-swap copy helpers, practice palette, and practice legend are deleted; the game reducer (
game.state.ts) is pure with every timestamp passed as an argument (noDate.now()inside), and the 10-task queue is deterministic and authored in one file (game.tasks.ts). Mid-run resume was simplified away: any stored progress value (legacy lesson ids included) just re-offers a fresh run from the one-screen how-to card.Automated validation
U), Enter→signup from the end screen (?auth=signupURL asserted), reminders opt-in (N,compass.notifications.enabledpolled totrue), and reload-mid-game re-offer were all exercised end to end.Independent review
Adversarial re-read of the diff during development; findings fixed before push: the quick-time buffer helper rejected valid 4-digit times (caught by the scripted-run unit test), end-screen Enter hint contradicted the auto-focused button ("hints never lie"), and the two focus/keyboard bugs caught by Playwright above.
Test plan
bun run lint— clean (19 pre-existing warnings, 0 errors)bun run type-check— clean (app + web tests configs)bun run test:web— 2962/2963 pass; the one failure (PublicBookingPageslot-pane skeleton race) fails identically on an unmodified checkout ofmainand is unrelated (filed as a follow-up task)bun packages/scripts/src/testing/test-parallel.ts backend-fast -- packages/backend/src/common/middleware/supertokens.middleware.test.tsand...util.test.ts— pass; the fulltest:backend:fastsuite has environment-caused failures (SSE/config 60s timeouts) reproduced identically onorigin/mainin this containerbunx playwright test e2e/onboarding/ --project=chromium-desktop— 8/8 pass (7 rewritten Schedule Rush specs +first-run.spec.tsunmodified)game.state.test.ts(scripted winning run, time-up, streak math, per-validator cases incl. resize rejecting whole-block moves and undo restoring the scripted delete), extendedpractice.state.test.ts, rewritten store/storage/component suites🤖 Generated with Claude Code
https://claude.ai/code/session_018r9yps9Wc8MPByQs1qonrY
Generated by Claude Code