# Quickstart: Bestiary Search & Stat Block Display **Branch**: `021-bestiary-statblock` | **Date**: 2026-03-06 ## What This Feature Does Adds a searchable creature library (D&D 2024 Monster Manual) to the initiative tracker. Users can search for creatures by name, view their full stat block in a side panel, and add them as combatants with stats pre-filled (name, HP, AC). Multiple instances of the same creature are auto-numbered. ## Key Files to Touch ### New Files (Domain) - `packages/domain/src/creature-types.ts` — Creature, CreatureId, TraitBlock, etc. - `packages/domain/src/auto-number.ts` — Auto-numbering logic for duplicate creature names ### New Files (Web) - `data/bestiary/xmm.json` — Raw 5etools bestiary data (bundled at build time) - `apps/web/src/adapters/bestiary-adapter.ts` — Normalizes raw JSON to Creature[] - `apps/web/src/adapters/strip-tags.ts` — Strips {@tag} markup to plain text - `apps/web/src/hooks/use-bestiary.ts` — Provides search + creature lookup - `apps/web/src/components/bestiary-search.tsx` — Search input with autocomplete dropdown - `apps/web/src/components/stat-block.tsx` — Full creature stat block display - `apps/web/src/components/stat-block-panel.tsx` — Side panel / drawer wrapper ### Modified Files - `packages/domain/src/types.ts` — Add optional `creatureId` to Combatant - `packages/domain/src/index.ts` — Export new creature types - `apps/web/src/App.tsx` — Two-column layout + stat block panel state - `apps/web/src/components/action-bar.tsx` — Add search icon + bestiary search integration - `apps/web/src/hooks/use-encounter.ts` — Handle creatureId on add, auto-numbering - `apps/web/src/persistence/encounter-storage.ts` — Persist/rehydrate creatureId ## Architecture Fit ``` data/bestiary/xmm.json (static asset) | v bestiary-adapter.ts (web adapter) --normalizes--> Creature[] (domain types) | v use-bestiary.ts (hook) --provides--> search + lookup | v bestiary-search.tsx --selects creature--> use-encounter.ts --calls--> addCombatant (domain) | | v v stat-block-panel.tsx <--reads creature data-- creatureId on Combatant ``` The domain layer gets the `Creature` type definitions and auto-numbering logic (pure functions). The web adapter handles the raw-to-domain transformation and tag stripping. The hook layer orchestrates search and state. ## Running & Testing ```bash # Dev server pnpm --filter web dev # Run all tests pnpm test # Typecheck pnpm typecheck # Full merge gate pnpm check ``` ## Key Design Decisions 1. **Bundled JSON** — No runtime fetching, no database. JSON imported at build time. 2. **Pre-rendered text** — Tags stripped during normalization, not at render time. 3. **Creature type in domain** — Type definitions live in domain, normalization adapter lives in web. 4. **creatureId on Combatant** — Lightweight reference, not embedded creature data. 5. **Auto-numbering in domain** — Pure function that takes existing names and base name, returns resolved name.