diff --git a/README.md b/README.md index 5c9aedd..8ce5179 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Encounter Console +# 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. @@ -34,17 +34,43 @@ Open `http://localhost:5173`. | `pnpm --filter web dev` | Start the dev server | | `pnpm --filter web build` | Production build | | `pnpm test` | Run all tests (Vitest) | -| `pnpm check` | Full merge gate (knip, biome, typecheck, test, jscpd) | +| `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/app/ Use cases — orchestrates domain via port interfaces -data/bestiary/ Bestiary index for creature search -scripts/ Build tooling (layer boundary checks, index generation) -specs/ Feature specifications (spec → plan → tasks) +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 @@ -55,5 +81,45 @@ Strict layered architecture with enforced dependency direction: apps/web (adapters) → packages/application (use cases) → packages/domain (pure logic) ``` -Domain is pure — no I/O, no randomness, no framework imports. Layer boundaries are enforced by automated import checks that run as part of the test suite. See [CLAUDE.md](./CLAUDE.md) for full conventions. +- **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.