--- # nuzlocke-tracker-l9xh title: Frontend auth flow (login, signup, session management) status: completed type: feature priority: normal tags: - failed created_at: 2026-03-20T15:28:24Z updated_at: 2026-03-20T19:26:16Z parent: nuzlocke-tracker-d98o blocked_by: - nuzlocke-tracker-2561 --- Add Supabase JS client to the frontend. Build login and signup pages with email/password and social login buttons (Google, Discord). Implement auth context/provider for session management, protected route wrapper, and auth-aware API client that attaches Bearer tokens. ## Checklist - [x] Install @supabase/supabase-js - [x] Create Supabase client singleton with env vars - [x] Create AuthContext/AuthProvider with session state, login, logout, signup methods - [x] Build login page (email/password form + Google/Discord buttons) - [x] Build signup page (email/password form + Google/Discord buttons) - [x] Add auth callback route for OAuth redirects - [x] Create ProtectedRoute wrapper component - [x] Update API client to attach Authorization header when user is logged in - [x] Add user menu (avatar/email, logout) to header when authenticated - [x] Handle token refresh automatically via Supabase client ## Summary of Changes - Installed @supabase/supabase-js package - Created Supabase client singleton at `frontend/src/lib/supabase.ts` - Created AuthContext/AuthProvider at `frontend/src/contexts/AuthContext.tsx` with session state, login, logout, signup, and OAuth methods - Created Login page (`frontend/src/pages/Login.tsx`) with email/password form and Google/Discord OAuth buttons - Created Signup page (`frontend/src/pages/Signup.tsx`) with email/password form and Google/Discord OAuth buttons - Created auth callback route (`frontend/src/pages/AuthCallback.tsx`) for OAuth redirects - Created ProtectedRoute component (`frontend/src/components/ProtectedRoute.tsx`) - Updated API client to attach Authorization header automatically when user is logged in - Added UserMenu component to Layout header showing avatar/email and logout button - Token refresh is handled automatically by Supabase JS client