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:
@@ -512,6 +512,27 @@ snapshot, locked to the line, and read from cache.
|
||||
merge carries ab_per_game/rest_days; `FEATURE_NAMES` is meta bookkeeping only,
|
||||
NOT a whitelist that filters the vector).
|
||||
|
||||
## Onboarding Flow (Session 49 — non-obvious)
|
||||
- **Preferences live in Supabase `user_metadata.preferences`** (NO table/migration).
|
||||
`src/routes/preferences.js` GET/POST behind `requireAuth`, read/written via the
|
||||
service client's `auth.admin.getUserById`/`updateUserById`. POST is a PARTIAL
|
||||
merge (only body keys change) + sanitized (valid sports only, ≤12 books, clamped
|
||||
limit). Shape: `{ sports[], books[], weekly_limit, onboarding_complete }`.
|
||||
- **Redirect reads FRESH from the API, not session metadata.** The dashboard
|
||||
fetches `/api/preferences` on mount and redirects new+incomplete users to
|
||||
`/onboarding`. Don't rely on `session.user.user_metadata` for this — it's stale
|
||||
after a backend write (admin API doesn't refresh the client session).
|
||||
- **Existing users are exempt** via a `created_at >= ONBOARDING_CUTOFF`
|
||||
(2026-06-19) check. The redirect effect also early-returns while `authLoading`
|
||||
(else it bounces unauthenticated users to onboarding instead of login).
|
||||
- **Dashboard personalization:** Slate `initialTab = prefs.sports[0]`; preferred
|
||||
books highlight in the card lines grid via `lib/books.js isPreferredBook`
|
||||
(matches DK/draftkings/DraftKings), threaded dashboard → Slate → vyndr/GameCard.
|
||||
- **Settings** has a PREFERENCES section (GET to load, POST to save) — the same
|
||||
sports/books/limit the onboarding collects.
|
||||
- **Name micro-fix:** `playerName.js` `collapseInitials` merges "J C" → "JC"
|
||||
(display + key) so space-separated initials dedupe.
|
||||
|
||||
## Active Skills
|
||||
- vyndr-voice (all user-facing output)
|
||||
- prop-analysis (grading methodology)
|
||||
|
||||
Reference in New Issue
Block a user