Files
weirsoe-party-protocol/CLAUDE.md
Asger Geel Weirsøe d2dbd8c802
Some checks failed
CI / test-and-quality (push) Has been cancelled
CI / test-and-quality (pull_request) Successful in 2m43s
docs: design doc for fup og fakta game engine + platform architecture
Captures all brainstormed decisions:
- Pluggable game cartridge platform (GameDriver interface)
- Celery + Redis timer-driven phase transitions
- Session owner play/pause/exit controls (no skip)
- Escalating scoring per round, incremental reveal scoring
- Emoji reactions during guess phase → post-game awards
- Relational per-user config presets with game-specific models
- Ephemeral game state (no persistence after exit/finish)
- Full WebSocket event reference and data lifecycle

Also: updated TODO.md (WebSocket done, persisted answers done),
created CLAUDE.md, and PROMPT.md for ralph-loop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 07:35:55 +01:00

4.8 KiB
Raw Permalink Blame History

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)

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)

cd frontend
npm install
npm test       # Vitest unit tests
npm run build  # TypeScript compile check (--noEmit)

Frontend — Angular shell (/frontend/angular)

cd frontend/angular
npm install
npm start      # Dev server (ng serve)
npm run build  # Production build
npm run test   # Vitest unit tests

i18n validation

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)

  • 312 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/<name>: 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