Files
initiative/specs/021-bestiary-statblock/quickstart.md

75 lines
3.1 KiB
Markdown

# 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.