# CLAUDE.md - Codebase Documentation for Claude Code This file helps Claude understand the Deathwatch Roller codebase and provide better assistance. **Prefer the live code and `package.json` over older docs when they disagree.** For a deep, feature-by-feature guide, see `AGENTS.md` — it is the most detailed and up-to-date reference in the repo. ## Project Overview **Deathwatch Roller** is a Create React App + Express application for running Deathwatch tabletop RPG sessions. **Main Features:** - Player login, character sheets, and player management (GM) - Dice roller (skill checks and combat) with fate-point support - Mission play (GM/player views) and simulation lab - Requisition shop (buy gear with RP), gated by renown - Bestiary, rules search, and weapon references - GM Kit reference tables and user-submitted error reports **Tech Stack:** - Frontend: React 18 (plain JavaScript/JSX, **not** TypeScript) via Create React App - Backend: Node.js + Express (`database/server.js`) - Database: MariaDB via `mysql2/promise` (some legacy SQLite artifacts remain) - Styling: Tailwind CSS + component CSS ## Architecture The repo is a **single-root JavaScript app** — there is no `backend/` or `frontend/` directory (older docs that mention them are stale). ``` dwroller/ ├── src/ # React frontend (App.js, components/, utils/, tests/) ├── database/ # Express backend (server.js, routes/, mariadb.js, ...) ├── scripts/ # Import, cleanup, validation, generation, CI helpers ├── public/ # Static data/assets + printable pages (cards.html, print.html) ├── data/ # Static data and assets └── docs/ # Documentation (some structure docs are stale) ``` ## Key Files and Locations ### Frontend (`src/`) - `src/App.js` - main app, login/session state, tab wiring (`tab` state), `logUserAction()` - `src/components/` - feature UI components - `src/components/DeathwatchRoller.jsx` - combat dice roller (weapon mapping, attack/damage, hit locations, history, presets, tracker) - `src/components/SkillRoller.jsx` - sheet-driven skill checks, manual d100, target overrides - `src/components/rollHelpers.js` - shared d100, DoS/DoF, ids, fate helpers (`applyFateToTest()`) - `src/components/FateControls.jsx`, `src/components/useFate.js` - fate UI and persistence (`POST /api/players/:name/spend-fate`) - `src/components/MissionTab.jsx` - active mission play (GM/player views) - `src/components/SimulationTab.jsx` - simulation report UI and controls - `src/components/MissionSimTab.jsx` - older/generated mission simulator; check routing before extending - `src/utils/diceRoller.js` - mission-safe dice helpers, `MISSION_ROLL_CONTEXT_KEY` - `src/tests/` - Jest unit tests ### Backend (`database/`) - `database/server.js` - Express entrypoint and route mounting - `database/routes/` - API routes (players, sessions, shop, rules, bestiary, weapons, missions, simulations, staging, errors) - `database/routes/missionRoutes.js` - mission CRUD, active mission, `playerScene()` safe projection, active-scene patching, shared roll feed - `database/routes/simulationRoutes.js` - backend simulation engine and report CRUD - `database/mariadb.js` - MariaDB pool, schema creation/patching - `database/sessionModel.js` - session storage helpers - `database/shop-helpers.js` - requisition/shop business logic ## Development Workflow Run commands from the repository root unless noted. ```bash npm install npm start # CRA dev server on http://localhost:3000 npm run server:notest # backend only (cd database && node server.js) on :5000 npm run test:unit # frontend Jest unit tests ``` ### Scripts (see `package.json` for the full list) - `npm start` - frontend dev server (CRA proxies /api to :5000) - `npm run server` - runs unit tests first, then `database/server.js` - `npm run server:notest` - backend without running tests first - `npm run build` - runs unit tests, then `react-scripts build` - `npm run build:fast` - build then `pm2:reload` (skips tests) - `npm run test:integration` - starts PM2, runs integration Jest, stops PM2 - `npm run pm2:start` / `pm2:reload` / `pm2:stop` - PM2 process control - `./scripts/local-ci.sh` - local CI helper Ports: frontend `3000`, backend API `5000` (CRA proxy points at `5000`). ## App Tabs Tabs are selected in `src/App.js` via the `tab` state (see `AGENTS.md` for the full per-tab breakdown of components, endpoints, and behavior): | Tab key | Component | Availability | |---------|-----------|--------------| | `mission` (default) | `MissionTab.jsx` | All; GM/player views differ | | `roller` | `DeathwatchRoller.jsx` | All | | `shop` | `RequisitionShop.jsx` | All; GM controls for `gm` | | (fallback) | `PlayerTab.jsx` (Character Sheet) | All; GM edit tools for `gm` | | `rules` | `RulesTab.jsx` | All | | `weapons` | `WeaponsTab.jsx` | All | | `errors` | `ErrorReports.jsx` | All; GM sees/resolves all | | `bestiary` | `BestiaryTab.jsx` | GM-only | | `players` | `PlayerManagement.jsx` | GM-only | | `gmkit` | `GMKit.jsx` | GM-only | | `simulation` | `SimulationTab.jsx` | GM-only | External utility pages `public/cards.html` (nav `Kort`) and `public/print.html` (nav `Print`) are static printable pages, not React tabs. ## API Surface Mounted prefixes in `database/server.js`: | Prefix | Description | |--------|-------------| | `/api/players` | Players, GM player ops, fate, avatars | | `/api/sessions` | Session management | | `/api/shop` | Requisition shop and purchases | | `/api/rules` | Rules categories/search/random (`/api/rules/staging` for staging) | | `/api/weapons` | Weapon references | | `/api/bestiary` | Bestiary full/reload/enemies | | `/api/missions` | Mission CRUD, active mission, safe scene, roll feed | | `/api/simulations` | Run and manage simulation reports | | `/api/errors` | User-submitted error reports | | `/api/gmkit/list`, `/api/gmkit/upload` | GM kit assets | | `/api/copy-bestiary` | Bestiary copy utility | | `/api/narrate` | Ollama narration (`OLLAMA_BASE`, `NARRATOR_MODEL`) | Static serving includes `/gmkit`, `/weapon-images`, and `/avatars`. ### Authentication - Sessions use an `x-session-id` header; backend uses `requireSession` - GM endpoints check `x-gm-secret` / `GM_SECRET` (falls back to `defaultsecret`) - Some GM upload auth falls back to defaults — see route files ## Environment And Runtime Notes - Backend loads env via `dotenv` from its working directory. `server:notest` runs from `database/`, so `database/.env` is the relevant file. - MariaDB defaults are hard-coded in `database/mariadb.js`: host `192.168.1.113`, user `deathwatch`, database `deathwatch`, port `3307`, password from `DB_PASSWORD` or `defaultpassword`. - Backend may load rules/weapons/bestiary from MariaDB first, then fall back to JSON files under `public/` and `database/`. - The backend can serve `build/` statically when a production build exists. ## Data Sources - Rules index: `database/rules/rules-database.json` - Skills: `database/deathwatch_skills_p94_107.csv` - Armoury/shop: `public/deathwatch-armoury.json` - Bestiary: `public/deathwatch-bestiary-extracted.json` (+ `database/` copy) ## Code Style & Conventions - Plain JavaScript/JSX — match surrounding style; do not introduce TypeScript unless a migration is explicitly requested. - Prefer existing React hook/component patterns in `src/components/`. - Frontend API calls use relative `/api/...` URLs through the CRA proxy. - Keep `localStorage` keys stable. Known keys include: `dw:shop:authedPlayer`, `dw:shop:sessionId`, `dw:shop:playerData`, `dw:shop:players:v1`, `dw:presets:v3`, `dw:history:v2`, `dw:weapons:v3`, `dw:tracker:v1`, `dw:mission:rollContext`, `dw:enemies:v1`, `dw:rules:recent`, `dw:warning-dismiss-until:v1`. - Keep DB writes parameterized through `mysql2` APIs. - Preserve backend response shapes and `tabInfo` shape used by components/tests. - Keep d100/DoS behavior aligned across mission, skill, and combat rolls. ## Testing - `npm run test:unit` for normal frontend changes; target a file with `npm test -- src/tests/login.test.js`. - `npm run test:integration` only when backend/API behavior changes and PM2/MariaDB are available. - If tests fail because MariaDB, PM2, Ollama, or local services are unavailable, report that explicitly rather than masking it. ## Files To Treat Carefully - Do not commit or churn runtime logs (`database/backend.log`, `database/server.log`). - Do not overwrite database files, backups, generated JSON, PDFs, OCR output, or imported rulebook data unless the user specifically asks for data work. - Inspect `git status --short` before editing; avoid reverting unrelated local work. - Do not paste long rulebook passages into UI/docs — summarize in original wording and link/search the local rules DB. ## Documentation Full docs are in `docs/` (note: some structure docs are stale and still refer to non-existent `backend/`/`frontend/` dirs). See also `README.md`, `DEVELOPMENT_GUIDE.md`, and especially `AGENTS.md` for the detailed guide.