Files
dwroller/CLAUDE.md

8.9 KiB

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.

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.