- Remove NeoUserProvider + NeoInstituteProvider from App.tsx startup chain
- Strip user_db_name/school_db_name from CCUser; add school_id (Phase B wires it to Supabase)
- Remove DatabaseNameService from AuthContext and UserContext
- Remove provisionUser() call from login path; API endpoint preserved for Phase B decision
- Simplify UserContext.resolveProfile: fast-path JWT metadata then background Supabase fetch
- Replace user.user_db_name reads in singlePlayerPage + snapshotService with null-safe guards
- Add useDeviceContext hook (desktop/tablet/phone/iwb, persists to localStorage)
App now loads to dashboard without any Neo4j dependency at startup.
Canvas opens to blank TLDraw state; Phase B rebuilds navigation on Supabase.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Before: UserContext waited for a Supabase profiles table query (~200ms)
before setting isInitialized=true, causing FullContextRoutes to show
a spinner on every page refresh even with a valid stored session.
After: UserContext immediately builds a profile from auth metadata +
localStorage (synchronous, zero network calls) and sets isInitialized=true
before the Supabase query. The Supabase profiles table is still queried
in the background and the profile is updated when it returns with
authoritative user_db_name/school_db_name data.
On refresh with a stored session: auth metadata is available
synchronously via INITIAL_SESSION, so the page renders with no visible
spinner.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>