# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **Weirsøe Party Protocol** is a Danish party game web platform (Jackbox-style) where games display on a primary screen and players participate via mobile. The MVP game is "Fup og Fakta" (a Fibbage-style lie-and-guess game). - Backend: Django 6.0.2 + Django Channels (WebSockets) + Redis - Frontend: Angular 19 shell + shared TypeScript API client library - Database: MySQL (SQLite fallback for dev) - Deployment: Proxmox LXC containers (not Docker) ## Commands ### Backend (Django) ```bash python manage.py runserver # Dev server python manage.py migrate # Apply migrations python manage.py test # Run all backend tests python manage.py test lobby # Run tests for a single app python manage.py shell # Django shell ``` ### Frontend — API client (`/frontend`) ```bash cd frontend npm install npm test # Vitest unit tests npm run build # TypeScript compile check (--noEmit) ``` ### Frontend — Angular shell (`/frontend/angular`) ```bash cd frontend/angular npm install npm start # Dev server (ng serve) npm run build # Production build npm run test # Vitest unit tests ``` ### i18n validation ```bash python scripts/check_i18n_drift.py # Check for key drift between locales ``` ## Architecture ### Backend apps | App | Purpose | |-----|---------| | `partyhub/` | Main Django project — settings, root URLs, ASGI/WSGI, i18n bootstrap | | `lobby/` | Session & player management — create/join session, locale-aware error responses | | `fupogfakta/` | Game logic — all domain models, score calculation (server-authoritative) | | `realtime/` | WebSocket event layer (stub) | | `voice/` | Voice/TTS interface (stub, Phase 2) | | `core_admin/` | Health endpoint (`/healthz`), global admin | **Key domain models** (all in `fupogfakta/models.py`): `GameSession`, `Player`, `Category`, `Question`, `RoundConfig`, `RoundQuestion`, `LieAnswer`, `Guess`, `ScoreEvent`. Score calculation is server-side only. `ScoreEvent` provides an auditable trail of all point changes. ### Frontend layers 1. **Shared API client** (`frontend/src/`) — pure TypeScript, framework-agnostic. Defines all API types (`api/types.ts`) and HTTP client abstraction (`api/client.ts`). 2. **Angular shell** (`frontend/angular/`) — Angular 19 standalone components (no NgModules), hash-based routing. `host-shell.component` for the presenter screen; `player-shell.component` for mobile players. The Angular shell consumes the shared client via `frontend/src/api/angular-client.ts`. ### Real-time flow `LOBBY → LIE → GUESS → REVEAL → FINISHED` — phase transitions broadcast a `PhaseViewModel` to all connected clients via WebSocket. Clients are read-only; only the server is authoritative for state. ### i18n - **Single source of truth**: `shared/i18n/lobby.json` (keys in both `en` and `da`) - Loaded once at startup with LRU cache (`partyhub/i18n_bootstrap.py`) - Key naming: domain-first — `frontend.ui.host.*`, `frontend.ui.player.*`, `backend.errors.*`, `backend.error_codes.*` - Locale resolved from `Accept-Language` header; missing key returns key + logs warning; missing translation falls back to `en` ## Key Conventions ### Errors Backend error responses use stable machine-readable codes (`backend.error_codes.*`) with separately localized messages. Never couple error code strings to locale. ### Game constraints (MVP) - 3–12 players per session - Session codes: 6-char alphanumeric (no 0/O/1/I/L) - Anti-cheat: no duplicate lies, lies cannot match the correct answer, answer order randomized ### Git workflow - `main`: stable baseline - `feature/`: development branches - `release/vX.Y.Z`: release preparation - Release: merge → create release branch → update `VERSION` + `CHANGELOG.md` → tag → push ### TypeScript Strict mode required. Target ES2022. API response interfaces in `frontend/src/api/types.ts` must match backend responses exactly. ### Database Use `ForeignKey` with explicit `on_delete` (`PROTECT`/`CASCADE`/`SET_NULL`). Add `db_index=True` on frequently queried fields. Migrations are auto-generated by Django and versioned in `migrations/`. ## Environment Variables ``` DJANGO_SECRET_KEY, DJANGO_DEBUG, DJANGO_ALLOWED_HOSTS DB_ENGINE, DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT CHANNEL_REDIS_HOST, CHANNEL_REDIS_PORT USE_SPA_UI (fallback: WPP_SPA_ENABLED) WPP_SPA_ASSET_BASE, WPP_SPA_ASSET_VERSION ``` ## Test Files of Note - `lobby/tests.py` — comprehensive Django TestCase coverage for session/player/i18n/error flows - `frontend/angular/src/app/api-contract-smoke.spec.ts` — API contract smoke tests - `frontend/angular/src/app/lobby-i18n.spec.ts` — i18n parity checks - `frontend/tests/lobby-loader.parity.test.ts` — shared i18n loader parity