Files
initiative/CLAUDE.md
Lukas b6e052f198 Overhaul bottom bar: batch add, custom fields, stat block viewer
Unify the action bar into a single search input with inline bestiary
dropdown. Clicking a dropdown entry queues it with +/- count controls
and a confirm button; Enter or confirm adds N copies to combat.

When no bestiary match exists, optional Init/AC/MaxHP fields appear
for custom creatures. The eye icon opens a separate search dropdown
to preview stat blocks without leaving the add flow.

Fix batch-add bug where only the last creature got a creatureId by
using store.save() instead of setEncounter() in addFromBestiary.
Prevent dropdown buttons from stealing input focus so Enter confirms
the queued batch.

Remove the now-redundant BestiarySearch component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:27:06 +01:00

96 lines
5.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
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`, via `idb` wrapper)
- **`data/bestiary/index.json`** — pre-built search index for creature lookup, generated by `scripts/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 `.js` extensions 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/`readonly` where practical.
- **Domain events** are plain data objects with a `type` discriminant — no classes.
- **Tests** live in `packages/*/src/__tests__/*.test.ts`. Test pure functions directly; map acceptance scenarios and invariants from specs to individual `it()` 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:
1. **Deterministic Domain Core** — Pure state transitions only; no I/O, randomness, or clocks in domain.
2. **Layered Architecture** — Domain → Application → Adapters. Never skip layers or reverse dependencies.
3. **Clarification-First** — Ask before making non-trivial assumptions.
4. **MVP Baseline** — Say "MVP baseline does not include X", never permanent bans.
5. **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)
- TypeScript 5.8, CSS (Tailwind CSS v4) + React 19, Tailwind CSS v4 (033-fix-concentration-glow-clip)
- N/A (no persistence changes) (033-fix-concentration-glow-clip)
- N/A (no persistence changes — display-only refactor) (034-topbar-redesign)
- TypeScript 5.8 (strict mode, `verbatimModuleSyntax`) + React 19, Tailwind CSS v4, Lucide React (icons), class-variance-authority (035-statblock-fold-pin)
- N/A (no persistence changes — all new state is ephemeral) (035-statblock-fold-pin)
- TypeScript 5.8 (strict mode, `verbatimModuleSyntax`) + React 19, Tailwind CSS v4, Lucide React (icons) (036-bottombar-overhaul)
- N/A (no persistence changes — queue state and custom fields are ephemeral) (036-bottombar-overhaul)
## Recent Changes
- 032-inline-confirm-buttons: Added TypeScript 5.8 (strict mode, `verbatimModuleSyntax`) + React 19, Tailwind CSS v4, Lucide React, class-variance-authority (cva)