# SPEC: RTSport Login Page > Agent Collaboration Protocol v1.4.0 > Build Date: 2026-05-08 > Test build — end-to-end protocol verification ## Overview A standalone login page for RTSport at `/rtsport/login`. Simple email+password form. Submits via fetch() to the existing auth endpoint, redirects to the appropriate dashboard on success (AT, Coach, Parent, AD Admin). Graceful error handling for wrong credentials. ## Contract | Field | Value | |-------|-------| | API Base Path | `/api/v1` (relative — same origin) | | Auth Scheme | Bearer JWT from `POST /api/v1/auth/login/json` | | Content Type | `application/json` | | Error Format | `{ "detail": "..." }` (401) | | Existing Routes | `/api/v1/auth/login/json` — `POST { email, password }` → `{ access_token, role, school_id }` | ## Data Models ### LoginRequest | Field | Type | Required | Notes | |-------|------|----------|-------| | email | string | yes | User's email address | | password | string | yes | Plaintext, sent over HTTPS | ### LoginResponse | Field | Type | Notes | |-------|------|-------| | access_token | string | JWT for Authorization header | | token_type | string | "bearer" | | role | string | "at" / "coach" / "parent" / "admin" | | school_id | string | Associated school | ## Endpoints (consume only — backend exists) ### `POST /api/v1/auth/login/json` **Request:** `{ "email": "test@example.com", "password": "..." }` **Success (200):** `{ "access_token": "...", "token_type": "bearer", "role": "at", "school_id": "schl_001" }` **Error (401):** `{ "detail": "Invalid email or password" }` ## UI Components ### LoginPage - Purpose: Capture email + password, authenticate, redirect on success - Data source: `POST /api/v1/auth/login/json` - States: idle, loading (button spinner), error (red banner), success (redirect) - Route: `/rtsport/login` ## Shared Constants | Constant | Values | |----------|--------| | Role routing | `at` → `/rtsport/at`, `coach` → `/rtsport/coach`, `parent` → `/rtsport/parent`, `admin` → `/rtsport/ad` | | Test credentials | `parent@example.com` / `testpass123` → parent dashboard | ## File Structure ``` backend/ login_router.py ← Mounts at /rtsport/login, serves login page __init__.py ← Empty frontend/ templates/ login.html ← Login page template static/ css/ login.css ← Login page styles js/ login.js ← Login form logic (fetch auth, store token, redirect) ``` ## Success Criteria - User visits `/rtsport/login`, sees email + password form - Submitting `parent@example.com` / `testpass123` stores JWT in localStorage and redirects to `/rtsport/parent` - Submitting wrong credentials shows a red "Invalid email or password" banner - Loading state shows on the submit button while the request is in flight - Mobile-friendly — works on iPhone SE viewport (375px) ## Out of Scope - Password reset flow - "Remember me" / persistent sessions - OAuth / social login - Registration