3.2 KiB
3.2 KiB
Quickstart: On-Demand Bestiary with Pre-Indexed Search
Feature: 029-on-demand-bestiary Date: 2026-03-10
What This Feature Does
Replaces the bundled full bestiary file (one source, ~1.3 MB of copyrighted content) with:
- A pre-shipped lightweight index (102 sources, 3,312 creatures, ~52 KB gzipped) for instant search and combatant creation
- On-demand fetching of full stat block data per source, cached in IndexedDB
Key Changes
Removed
data/bestiary/xmm.json— no longer shipped with the app
New Files
apps/web/src/adapters/bestiary-index-adapter.ts— loads and parses the shipped index, converts compact format to domain typesapps/web/src/adapters/bestiary-cache.ts— IndexedDB cache adapter for fetched source dataapps/web/src/components/source-fetch-prompt.tsx— dialog prompting user to fetch/upload source dataapps/web/src/components/source-manager.tsx— UI for viewing and clearing cached sources
Modified Files
apps/web/src/hooks/use-bestiary.ts— rewritten to search from index and look up creatures from cacheapps/web/src/hooks/use-encounter.ts—addFromBestiaryaccepts index entries (no fetch needed to add)apps/web/src/components/bestiary-search.tsx— shows source display name in resultsapps/web/src/components/stat-block-panel.tsx— triggers source fetch prompt when creature not cachedpackages/domain/src/creature-types.ts— newBestiaryIndexEntryandBestiaryIndextypes
Unchanged
apps/web/src/adapters/bestiary-adapter.ts— normalization pipeline processes fetched data exactly as beforeapps/web/src/adapters/strip-tags.ts— tag stripping unchangedapps/web/src/components/stat-block.tsx— stat block rendering unchangedapps/web/src/persistence/encounter-storage.ts— encounter persistence unchanged
Architecture Overview
index.json (shipped, static)
↓ Vite JSON import
bestiary-index-adapter.ts
↓ BestiaryIndexEntry[]
use-bestiary.ts (search, add)
↓
bestiary-search.tsx → use-encounter.ts (addFromBestiary)
↓
stat-block-panel.tsx
↓ creatureId → source not cached?
source-fetch-prompt.tsx
↓ fetch URL or upload file
bestiary-adapter.ts (normalizeBestiary — unchanged)
↓ Creature[]
bestiary-cache.ts (IndexedDB)
↓
stat-block.tsx (renders full stat block)
Development Commands
pnpm check # Must pass before every commit
pnpm test # Run all tests
pnpm typecheck # TypeScript type checking
pnpm --filter web dev # Dev server at localhost:5173
Testing Strategy
- Domain tests: Pure function tests for new
BestiaryIndexEntrytype and any utility functions - Adapter tests: Test index parsing (compact → readable format), test IndexedDB cache operations (mock IndexedDB via fake-indexeddb)
- Component tests: Not in scope (existing pattern — components tested via manual verification)
- Integration: Verify search returns multi-source results, verify add-from-index flow, verify fetch→cache→display flow
New Dependency
idb— Promise-based IndexedDB wrapper (~1.5 KB gzipped). Used only inbestiary-cache.ts.