Session 49: Complete onboarding flow + name micro-fixes (2185 tests)

Name micro-fixes (close the normalization arc):
- collapseInitials merges "J C Escarra" -> "JC Escarra" (display + key); both
  playerName.js copies. Added mickey:michael nickname.

Onboarding flow (end-to-end, complete):
- Storage: Supabase user_metadata.preferences (no migration).
- API: src/routes/preferences.js GET/POST (requireAuth, admin getUserById/
  updateUserById, partial merge + sanitize) + Next /api/preferences proxy.
- Page: web onboarding/page.tsx — 3 steps (sports >=1 / books skip / bankroll
  presets+custom+skip) -> SIGNAL ACTIVE -> POST onboarding_complete:true -> 2s
  -> /dashboard. Redirects to login when unauthenticated.
- Redirect: dashboard fetches /api/preferences fresh; new+incomplete users
  (created_at >= cutoff) -> /onboarding; never while auth loading; existing
  users exempt.
- Personalization: Slate default tab = prefs.sports[0]; preferred books glow in
  the card lines grid (lib/books isPreferredBook, threaded dash->Slate->GameCard).
- Settings: PREFERENCES section loads + edits + saves sports/books/limit.

Backend 2156 -> 2185 tests (+29), 184 suites. Web build clean (exit 0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kev
2026-06-19 10:20:55 -04:00
parent 91b03c4044
commit 3b47b783dc
17 changed files with 687 additions and 17 deletions
+33 -2
View File
@@ -4,8 +4,39 @@
2026-06-18
## Current Phase
SHIP BUILD v48.0 — Name normalization applied at EVERY layer (snapshot source,
game-card strips, scan grid) + profile usage/rest wired. The dup-player arc closed.
SHIP BUILD v49.0 — Complete onboarding flow (prefs API, 3-step page, redirect,
dashboard personalization, settings editor) + name micro-fixes.
## Session 49 (2026-06-19) — SHIPPED ✅ ONBOARDING FLOW
Backend 2156 → **2185 tests** (+29), 184 suites. Web build clean (exit 0).
New routes: `/onboarding`, `/api/preferences`.
### Phase 1 — name micro-fixes (closes the normalization arc)
`playerName.js` (both copies): collapse adjacent single-letter words
("J C Escarra" → "JC Escarra", display + key) + added `mickey: 'michael'`.
### Phases 25 — onboarding, end-to-end
- **Storage:** Supabase `user_metadata.preferences` — NO migration. Shape:
`{ sports[], books[], weekly_limit, onboarding_complete }`.
- **API:** `src/routes/preferences.js` GET/POST (requireAuth; service-client
admin getUserById/updateUserById; POST is a PARTIAL merge + sanitized) +
`/api/preferences` Next proxy (forwards the bearer).
- **Page:** `web/src/app/onboarding/page.tsx` — 3 self-contained steps (sports
[≥1 required] → books [skip] → weekly bankroll [presets + custom + skip]) →
"SIGNAL ACTIVE / You're locked in" → POST `onboarding_complete:true` → 2s →
`/dashboard`. Redirects to /login when unauthenticated.
- **Redirect:** the dashboard fetches `/api/preferences` (fresh — avoids stale
session metadata); if `onboarding_complete !== true` AND the user is NEW
(`created_at >= 2026-06-19 cutoff`), → `/onboarding`. Never fires while auth is
loading (would bounce unauthenticated users). Existing users are exempt.
- **Personalization:** the Slate defaults its tab to `prefs.sports[0]`; preferred
books are highlighted (green glow) in each game card's lines grid
(`isPreferredBook` in `lib/books.js`, threaded dashboard → Slate → GameCard).
- **Settings:** a PREFERENCES section loads (GET) + edits + saves (POST) sports,
books, and weekly limit.
## Session 48 (2026-06-19) — SHIPPED ✅ NORMALIZATION AT EVERY LAYER
## Session 48 (2026-06-19) — SHIPPED ✅ NORMALIZATION AT EVERY LAYER