4.7 KiB
4.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
pnpm check # Merge gate — must pass before every commit (audit + knip + biome + typecheck + test/coverage + jscpd)
pnpm knip # Unused code detection (Knip)
pnpm test # Run all tests (Vitest)
pnpm test:watch # Tests in watch mode
pnpm typecheck # tsc --build (project references)
pnpm lint # Biome lint
pnpm format # Biome format (writes)
pnpm --filter web dev # Vite dev server (localhost:5173)
pnpm --filter web build # Production build
Run a single test file: pnpm vitest run packages/domain/src/__tests__/advance-turn.test.ts
Architecture
Strict layered architecture with ports/adapters and enforced dependency direction:
apps/web (React 19 + Vite) → packages/application (use cases) → packages/domain (pure logic)
- Domain — Pure functions, no I/O, no framework imports. All state transitions are deterministic. Errors returned as values (
DomainError), never thrown. Adapters may throw only for programmer errors. - Application — Orchestrates domain calls via port interfaces (
EncounterStore,BestiarySourceCache). No business logic here. - Web — React adapter. Implements ports using hooks/state. All UI components, routing, and user interaction live here.
Layer boundaries are enforced by scripts/check-layer-boundaries.mjs, which runs as a Vitest test. Domain and application must never import from React, Vite, or upper layers.
Data & Storage
- localStorage — encounter persistence (adapter layer, JSON serialization)
- IndexedDB — bestiary source cache (
apps/web/src/adapters/bestiary-cache.ts, viaidbwrapper) data/bestiary/index.json— pre-built search index for creature lookup, generated byscripts/generate-bestiary-index.mjs
Project Structure
apps/web/ React app — components, hooks, adapters
packages/domain/src/ Pure state transitions, types, validation
packages/application/src/ Use cases, port interfaces
data/bestiary/ Bestiary search index
scripts/ Build tooling (layer checks, index generation)
specs/<feature>/ Feature specs (spec.md, plan.md, tasks.md)
.specify/memory/ Project constitution
Tech Stack
- TypeScript 5.8 (strict mode,
verbatimModuleSyntax) - React 19, Vite 6, Tailwind CSS v4
- Lucide React (icons)
idb(IndexedDB wrapper for bestiary cache)- Biome 2.0 (formatting + linting), Knip (unused code), jscpd (copy-paste detection)
- Vitest (testing, v8 coverage), Lefthook (pre-commit hooks)
Conventions
- Biome 2.0 for formatting and linting (no Prettier, no ESLint). Tab indentation, 80-char lines. Imports are auto-organized alphabetically.
- TypeScript strict mode with
verbatimModuleSyntax. Use.jsextensions in relative imports when required by the repo's ESM settings (e.g.,./types.js). - Branded types for identity values (e.g.,
CombatantId). Prefer immutability/readonlywhere practical. - Domain events are plain data objects with a
typediscriminant — no classes. - Tests live in
packages/*/src/__tests__/*.test.ts. Test pure functions directly; map acceptance scenarios and invariants from specs to individualit()blocks. - Feature specs live in
specs/<feature>/with spec.md, plan.md, tasks.md. The project constitution is at.specify/memory/constitution.md. - Quality gates are enforced at pre-commit via Lefthook's
pnpm check— the project's single earliest enforcement point. No gate may exist only as a CI step or manual process.
Constitution (key principles)
The constitution (.specify/memory/constitution.md) governs all feature work:
- Deterministic Domain Core — Pure state transitions only; no I/O, randomness, or clocks in domain.
- Layered Architecture — Domain → Application → Adapters. Never skip layers or reverse dependencies.
- Clarification-First — Ask before making non-trivial assumptions.
- MVP Baseline — Say "MVP baseline does not include X", never permanent bans.
- Every feature begins with a spec — Spec → Plan → Tasks → Implementation.
Active Technologies
- TypeScript 5.8 (strict mode,
verbatimModuleSyntax) + React 19, Tailwind CSS v4, Lucide React, class-variance-authority (cva) (032-inline-confirm-buttons) - N/A (no persistence changes — confirm state is ephemeral) (032-inline-confirm-buttons)
Recent Changes
- 032-inline-confirm-buttons: Added TypeScript 5.8 (strict mode,
verbatimModuleSyntax) + React 19, Tailwind CSS v4, Lucide React, class-variance-authority (cva)