Implement the 021-bestiary-statblock feature that adds a searchable D&D 2024 Monster Manual creature library with inline autocomplete suggestions, full stat block display in a fixed side panel, auto-numbering of duplicate creature names, HP/AC pre-fill from bestiary data, and automatic stat block display on turn change for wide viewports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
74
specs/021-bestiary-statblock/quickstart.md
Normal file
74
specs/021-bestiary-statblock/quickstart.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user