Files
initiative/README.md
Lukas d13641152f Update README with setup guide, contributing workflow, and bestiary docs
Fixes packages/app → packages/application path, expands scripts table,
documents the parallel merge gate, adds contributing workflow with
spec-driven process and Claude Code skills, and documents bestiary
index regeneration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:48:11 +02:00

126 lines
5.9 KiB
Markdown

# Initiative
A local-first initiative tracker and encounter manager for tabletop RPGs (D&D 5e / 2024). Runs entirely in the browser — no server, no account, no data leaves your machine.
## What it does
- **Initiative tracking** — add combatants (batch-add from bestiary, custom creatures with optional stats), roll initiative (manual or d20), cycle turns and rounds
- **Encounter state** — HP, AC, conditions, concentration tracking with visual status indicators
- **Bestiary integration** — import bestiary JSON sources, search creatures, and view full stat blocks
- **Player characters** — create reusable player character templates with name, AC, HP, level, color, and icon; search and add them to encounters with pre-filled stats; manage (edit/delete) from a dedicated panel
- **Encounter difficulty** — live 3-bar indicator in the top bar showing encounter difficulty (Trivial/Low/Moderate/High) based on the 2024 5.5e XP budget system; automatically derived from PC levels and bestiary creature CRs
- **Undo/redo** — reverse any encounter action with Undo/Redo buttons or keyboard shortcuts (Ctrl+Z / Ctrl+Shift+Z, Cmd on Mac); history persists across page reloads
- **Import/export** — export the full encounter state (combatants, undo/redo history, player characters) as a JSON file or copy to clipboard; import from file upload or pasted JSON with validation and confirmation
- **Persistent** — encounters survive page reloads via localStorage; bestiary data cached in IndexedDB; player characters stored independently
## Prerequisites
- Node.js 22+
- pnpm 10.6+
## Getting Started
```sh
pnpm install
pnpm --filter web dev
```
Open `http://localhost:5173`.
## Scripts
| Command | Description |
|---------|-------------|
| `pnpm --filter web dev` | Start the dev server |
| `pnpm --filter web build` | Production build |
| `pnpm test` | Run all tests (Vitest) |
| `pnpm test:watch` | Tests in watch mode |
| `pnpm vitest run path/to/test.ts` | Run a single test file |
| `pnpm typecheck` | TypeScript type checking |
| `pnpm lint` | Biome lint |
| `pnpm format` | Biome format (writes changes) |
| `pnpm check` | Full merge gate (see below) |
### Merge gate (`pnpm check`)
All of these run at pre-commit via Lefthook (in parallel where possible):
- `pnpm audit` — security audit
- `knip` — unused code detection
- `biome check` — formatting + linting
- `oxlint` — type-aware linting (complements Biome)
- Custom scripts — lint-ignore caps, className enforcement, component prop limits
- `tsc --build` — TypeScript strict mode
- `vitest run` — tests with per-path coverage thresholds
- `jscpd` + `jsinspect` — copy-paste and structural duplication detection
## Tech Stack
- TypeScript 5.8 (strict mode), React 19, Vite 6
- Tailwind CSS v4 (dark/light theme)
- Biome 2.4 (formatting + linting), oxlint (type-aware linting)
- Vitest (testing, v8 coverage), Lefthook (pre-commit hooks)
- Knip (unused code), jscpd + jsinspect (duplication detection)
## Project Structure
```
apps/web/ React 19 + Vite — UI components, hooks, adapters
packages/domain/ Pure functions — state transitions, types, validation
packages/application/ Use cases — orchestrates domain via port interfaces
data/bestiary/ Pre-built bestiary search index (~10k creatures)
scripts/ Build tooling (layer checks, index generation)
specs/ Feature specifications (spec → plan → tasks)
```
## Architecture
Strict layered architecture with enforced dependency direction:
```
apps/web (adapters) → packages/application (use cases) → packages/domain (pure logic)
```
- **Domain** — pure functions, no I/O, no randomness, no framework imports. Errors returned as values (`DomainError`), never thrown.
- **Application** — orchestrates domain calls via port interfaces (`EncounterStore`, `PlayerCharacterStore`, etc.). No business logic.
- **Web** — React adapter. Implements ports using hooks/state. All UI components, persistence, and external data access live here.
Layer boundaries are enforced by automated import checks that run as part of the test suite.
## Contributing
### Workflow
Development is spec-driven. Feature specs live in `specs/NNN-feature-name/` and are managed through Claude Code skills (see [CLAUDE.md](./CLAUDE.md) for full details).
| Scope | What to do |
|-------|-----------|
| Bug fix / CSS tweak | Fix it, run `pnpm check`, commit. Optionally use `/browser-interactive-testing` for visual verification. |
| Change to existing feature | Update the feature spec, then implement |
| Larger change to existing feature | Update the spec → `/rpi-research``/rpi-plan``/rpi-implement` |
| New feature | `/speckit.specify``/speckit.clarify``/speckit.plan``/speckit.tasks``/speckit.implement` |
Use `/write-issue` to create well-structured Gitea issues, and `/integrate-issue` to pull an existing issue's requirements into the relevant feature spec.
### Before committing
Run `pnpm check` — Lefthook runs this automatically at pre-commit, but running it manually first saves time. All checks must pass.
### Conventions
- **Biome** for formatting and linting — tab indentation, 80-char lines
- **TypeScript strict mode** with `verbatimModuleSyntax` (type-only imports must use `import type`)
- **Max 8 props** per component interface — use React context for shared state
- **Tests** in `__tests__/` directories — test pure functions directly, use `renderHook` for hooks
See [CLAUDE.md](./CLAUDE.md) for the full conventions and project constitution.
## Bestiary Index
The bestiary search index (`data/bestiary/index.json`) is pre-built and checked into the repo. To regenerate it (e.g., after a new source book release):
1. Clone [5etools-mirror-3/5etools-src](https://github.com/5etools-mirror-3/5etools-src) locally
2. Run `node scripts/generate-bestiary-index.mjs /path/to/5etools-src`
The script extracts creature names, stats, and source info into a compact search index.