---
estimated_steps: 39
estimated_files: 7
skills_used: []
---

# T03: Build frontend AuthContext, API auth functions, login and register pages

Create the React auth infrastructure: AuthContext provider with JWT persistence, API client auth functions, login page, register page, and wire AuthContext into App.tsx.

## Steps

1. Create `frontend/src/context/` directory.
2. Create `frontend/src/context/AuthContext.tsx`: React context providing `user` (UserResponse | null), `token` (string | null), `isAuthenticated` (boolean), `login(email, password)` (calls API, stores token in localStorage, fetches /me to populate user), `register(data)` (calls API, returns success/error), `logout()` (clears token + user from state and localStorage). On mount, check localStorage for existing token and call /me to rehydrate session. Export `AuthProvider` component and `useAuth()` hook.
3. Add auth API functions to `frontend/src/api/public-client.ts`:
   - `authRegister(data: RegisterRequest): Promise<UserResponse>` — POST /api/v1/auth/register
   - `authLogin(email: string, password: string): Promise<TokenResponse>` — POST /api/v1/auth/login
   - `authGetMe(token: string): Promise<UserResponse>` — GET /api/v1/auth/me with Authorization header
   - `authUpdateProfile(token: string, data: UpdateProfileRequest): Promise<UserResponse>` — PUT /api/v1/auth/me
   - Add TypeScript interfaces: `RegisterRequest`, `LoginRequest`, `TokenResponse`, `UserResponse`, `UpdateProfileRequest`
   - Modify `request<T>` to automatically inject Authorization header from localStorage when token exists
4. Create `frontend/src/pages/Login.tsx` (CSS module: `Login.module.css`):
   - Email + password form with validation (required fields, email format)
   - Error display for invalid credentials
   - Submit calls `useAuth().login()`, redirects to /creator/dashboard on success
   - Link to register page
   - Uses `useDocumentTitle('Login')` for consistent page titles
5. Create `frontend/src/pages/Register.tsx` (CSS module: `Register.module.css`):
   - Invite code + email + password + confirm password + display name form
   - Client-side validation: required fields, email format, password match, min password length (8 chars)
   - Error display for API errors (invalid code, email taken)
   - Submit calls `useAuth().register()`, redirects to /login with success message on completion
   - Uses `useDocumentTitle('Register')`
6. Wrap `<App />` content with `<AuthProvider>` in App.tsx. Add Route entries for `/login` and `/register`.

## Must-Haves

- [ ] AuthContext with login, register, logout, session rehydration from localStorage
- [ ] API auth functions with TypeScript types in public-client.ts
- [ ] request<T> injects Authorization header when token exists
- [ ] Login page with email/password form, error handling, redirect on success
- [ ] Register page with invite code + full form, validation, error handling
- [ ] CSS modules for both pages (not App.css)
- [ ] Routes /login and /register added to App.tsx
- [ ] `npm run build` passes with zero errors

## Verification

- `cd frontend && npm run build` — zero TypeScript errors
- `grep -r 'AuthProvider' frontend/src/App.tsx` — context is wired
- `test -f frontend/src/context/AuthContext.tsx` — context file exists
- `test -f frontend/src/pages/Login.tsx && test -f frontend/src/pages/Register.tsx` — both pages exist
- `test -f frontend/src/pages/Login.module.css && test -f frontend/src/pages/Register.module.css` — CSS modules exist

## Inputs

- `frontend/src/api/public-client.ts`
- `frontend/src/App.tsx`
- `frontend/src/App.css`
- `backend/schemas.py`

## Expected Output

- `frontend/src/context/AuthContext.tsx`
- `frontend/src/api/public-client.ts`
- `frontend/src/pages/Login.tsx`
- `frontend/src/pages/Login.module.css`
- `frontend/src/pages/Register.tsx`
- `frontend/src/pages/Register.module.css`
- `frontend/src/App.tsx`

## Verification

cd frontend && npm run build && test -f src/context/AuthContext.tsx && test -f src/pages/Login.tsx && test -f src/pages/Register.tsx
