# CLAUDE.md — Pole Dance Championships App ## Target Vision See `dancechamp-claude-code/` for full spec (3-app Supabase platform). Current implementation is a simplified MVP working toward that goal. ## Quick Start ```bash # Backend cd backend && .venv/Scripts/python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload # Web frontend cd web && npm run dev # runs on http://localhost:3000 # Seed test data cd backend && .venv/Scripts/python seed.py ``` ## Current Architecture - **Backend**: FastAPI + SQLAlchemy 2 (async) + aiosqlite (SQLite dev) + Alembic + bcrypt - **Web**: Next.js 15 (App Router) + Tailwind CSS + shadcn/ui + TanStack Query + Zustand - **Auth**: JWT access (15min) + refresh token rotation (7 days, SHA-256 hashed in DB) ## Project Layout ``` backend/app/ FastAPI app (models, schemas, routers, crud, services) backend/alembic/ Async migrations backend/.venv/ Virtual env (use .venv/Scripts/python) web/src/app/ Next.js App Router pages web/src/lib/api/ Axios client + API modules (auth, championships, users) web/src/store/ Zustand auth store web/src/components/ Shared UI components web/src/middleware.ts Route protection dancechamp-claude-code/ Target spec: SPEC.md, PLAN.md, DATABASE.md, DESIGN-SYSTEM.md, SCREENS.md ``` ## Gotchas - **passlib + bcrypt 5.x incompatible** — use `bcrypt` directly (NOT passlib) - **Circular import**: auth_service.py must NOT import crud_user - **SQLAlchemy UUID**: Use `sqlalchemy.Uuid(as_uuid=True)` not `postgresql.UUID` - **Stale uvicorn**: Kill with `powershell.exe -NoProfile -Command "Get-Process python | Stop-Process -Force"` - **Web API URL**: set `NEXT_PUBLIC_API_URL` in `web/.env.local` (default: http://localhost:8000/api/v1) ## Test Credentials (run seed.py) ``` admin@pole.dev / Admin1234 (admin, approved) organizer@pole.dev / Org1234 (organizer, approved) member@pole.dev / Member1234 (member, approved) ``` ## API Routes - Auth: POST /api/v1/auth/{register,login,refresh,logout,me} - Championships: GET/POST/PATCH/DELETE /api/v1/championships - Registrations: POST/GET/PATCH/DELETE /api/v1/registrations - Users (admin): GET /api/v1/users, PATCH /api/v1/users/{id}/{approve,reject} - Health: GET /internal/health | Swagger: GET /docs ## Code Conventions - Backend: Pydantic v2 schemas, async SQLAlchemy, `from_attributes = True` - Web: Functional components, TanStack Query for server state, Zustand for auth, shadcn/ui components - Registration: members auto-approved, organizers require admin approval ## Environment - Windows 10, Python 3.12, Node.js - Docker NOT installed, PostgreSQL NOT installed (use SQLite for dev) - venv always in backend/.venv ## Linear Workflow (MANDATORY) **Every action** (coding, migrations, docs, planning, bug fixes) MUST have a Linear issue. Before starting ANY task: 1. Check if a matching Linear issue exists in the "Pole dance app" workspace 2. If not — create one (title, description, priority) 3. Set status to **In Progress** before writing any code After completing: - Set status to **Done** - Make a git commit with message: `POL-N: ` - Report the issue number to the user (e.g. "Done — POL-42") **Unrelated fixes during a task:** If you discover and fix something unrelated to the current issue (e.g. a bug spotted while working on a feature), create a **separate Linear issue** describing what was fixed, commit it separately with that issue's `POL-N` prefix. Never mix unrelated changes into another issue's commit.