Persistent player character templates (name, AC, HP, color, icon) with full CRUD, bestiary-style search to add PCs to encounters with pre-filled stats, and color/icon visual distinction in combatant rows. Also stops the stat block panel from auto-opening when adding a creature. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.6 KiB
2.6 KiB
Quickstart: Player Character Management
Branch: 005-player-characters | Date: 2026-03-12
Overview
This feature adds persistent player character templates that can be reused across encounters. Player characters have a name, AC, max HP, a chosen color, and a preset icon.
Implementation Layers
Domain (packages/domain/src/)
New files:
player-character-types.ts—PlayerCharacterId,PlayerCharacter,PlayerColor,PlayerIcon, validation setscreate-player-character.ts— Pure create functionedit-player-character.ts— Pure edit functiondelete-player-character.ts— Pure delete function
Modified files:
types.ts— Addcolor?,icon?,playerCharacterId?toCombatantevents.ts— AddPlayerCharacterCreated,PlayerCharacterUpdated,PlayerCharacterDeletedto unionindex.ts— Re-export new types and functions
Application (packages/application/src/)
Modified files:
ports.ts— AddPlayerCharacterStoreport interface
New files:
create-player-character-use-case.tsedit-player-character-use-case.tsdelete-player-character-use-case.ts
Web (apps/web/)
New files:
src/persistence/player-character-storage.ts— localStorage adaptersrc/hooks/use-player-characters.ts— React state + persistence hooksrc/components/create-player-modal.tsx— Create/edit modalsrc/components/player-management.tsx— List/edit/delete viewsrc/components/color-palette.tsx— Color selection gridsrc/components/icon-grid.tsx— Icon selection grid
Modified files:
src/components/action-bar.tsx— Add "Players" section to search dropdownsrc/components/combatant-row.tsx— Render color/icon for PC combatantssrc/App.tsx— Wire upusePlayerCharactershook, pass to componentssrc/persistence/encounter-storage.ts— Handle new optional Combatant fields in rehydration
Testing Strategy
- Domain: Pure function unit tests for create/edit/delete (validation, error cases, events)
- Persistence: Rehydration tests (corrupt data, missing fields, invalid color/icon)
- Integration: Layer boundary check already runs in CI — verify new domain files have no outer-layer imports
Key Patterns to Follow
- Branded types: See
CombatantIdintypes.tsfor pattern - Domain operations: See
add-combatant.tsfor{result, events} | DomainErrorpattern - Persistence: See
encounter-storage.tsfor localStorage + rehydration pattern - Hook: See
use-encounter.tsforuseState+useEffectpersistence pattern - Ports: See
EncounterStoreinports.tsfor interface pattern