Files
dwroller/CLAUDE.md

201 lines
8.9 KiB
Markdown

# 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.