Feature Spec: Player Character UI (Character Management)
| Field |
Value |
| Feature |
Player Character UI (Character Management) |
| Issue |
#TBD |
| Status |
Draft |
| Author |
The Doctor |
| Date |
2026-04-10 |
Overview
What it does
Adds a Blazor WASM interface for viewing and managing player character sheets. The DM can view all characters in a campaign and apply inline overrides (HP, AC, conditions). Players, once auth is wired, can view their own character sheets.
Why it's needed
Character state must be visible outside Discord to support DM oversight and player self-service. This UI provides a canonical view of character stats, equipment, spells, and proficiencies, aligned with the domain model in spec #9.
Out of scope
Architecture Notes (The Doctor)
Projects / layers touched
New interfaces in DungeonMaster.Core
IPlayerCharacterQueryService — read-only character sheets + campaign list
IPlayerCharacterOverrideService — DM override operations
Integration points with existing systems
Domain Model
Records
public sealed record PlayerCharacterSummary(Guid Id, string Name, string ClassName, string RaceName, int Level);
public sealed record PlayerCharacterDetail(
Guid Id,
string Name,
string ClassName,
string RaceName,
int Level,
int CurrentHitPoints,
int MaxHitPoints,
int ArmorClass,
AbilityScores AbilityScores,
IReadOnlyList<string> Proficiencies,
IReadOnlyList<string> Spells,
Guid? ImageId);
API Contract (Rory)
Endpoints
GET /api/campaigns/{id}/characters — DM-only list of characters
GET /api/characters/{id} — DM + owning player
PUT /api/characters/{id}/overrides — DM-only inline overrides (HP/AC/conditions)
UI Specification (Clara)
Page / component breakdown
- CampaignCharacterList (
/campaigns/{id}/characters) — DM view for all PCs
- CharacterDetail (
/characters/{id}) — detailed sheet view
Blazor component list
| Component |
File |
Purpose |
CampaignCharacterList |
Pages/Characters/CampaignCharacterList.razor / .razor.cs |
List all characters in a campaign |
CharacterDetail |
Pages/Characters/CharacterDetail.razor / .razor.cs |
Full character sheet view |
CharacterPortraitCard |
Components/Characters/CharacterPortraitCard.razor / .razor.cs |
Displays portrait image from spec #17 |
AbilityScoreGrid |
Components/Characters/AbilityScoreGrid.razor / .razor.cs |
STR/DEX/CON/INT/WIS/CHA grid |
EquipmentPanel |
Components/Characters/EquipmentPanel.razor / .razor.cs |
Shows equipped items and backpack (spec #27) |
SpellListPanel |
Components/Characters/SpellListPanel.razor / .razor.cs |
Known/prepared spells |
OverrideModal |
Components/Characters/OverrideModal.razor / .razor.cs |
DM-only inline overrides |
Theme / styling requirements
- Use
var(--color-surface) for card backgrounds
- Use
var(--spacing-md) for layout spacing
- Use
var(--font-size-lg) for character name heading
User interaction flow
- DM opens CampaignCharacterList → selects a character
- CharacterDetail loads full sheet with portrait
- DM clicks "Override" → modal edits HP/AC/conditions → saves
- Changes persist and update the UI
Test Scenarios (Danny) ⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
-
Given a campaign with two characters
When the DM opens the character list
Then both characters display with name, class, and level
-
Given a DM updates HP via OverrideModal
When the API returns success
Then the UI reflects the new HP value
Edge cases
-
Given a character has no portrait
When CharacterDetail loads
Then a placeholder image is displayed
-
Given the player is not the owner
When they request /api/characters/{id}
Then the API returns 403 Forbidden
Error / failure cases
-
Given invalid override data (negative HP)
When PUT /overrides is called
Then the API returns 400 Bad Request
-
Given the API is unavailable
When the character detail page loads
Then an error state is shown
Acceptance Criteria
Functional
Non-functional
Dependencies
Agent Work Breakdown
| Agent |
Task |
Depends On |
| The Doctor |
Approve spec |
— |
| Danny |
Write failing bUnit tests |
Spec approved |
| Clara |
Implement character UI components |
Danny's tests |
| Rory |
Implement API endpoints + query services |
Core entities |
| Danny |
Confirm all tests pass |
All implementation |
Definition of Done
Feature Spec: Player Character UI (Character Management)
Overview
What it does
Adds a Blazor WASM interface for viewing and managing player character sheets. The DM can view all characters in a campaign and apply inline overrides (HP, AC, conditions). Players, once auth is wired, can view their own character sheets.
Why it's needed
Character state must be visible outside Discord to support DM oversight and player self-service. This UI provides a canonical view of character stats, equipment, spells, and proficiencies, aligned with the domain model in spec #9.
Out of scope
Architecture Notes (The Doctor)
Projects / layers touched
DungeonMaster.Web— character pages + componentsDungeonMaster.Api— character query + override endpointsDungeonMaster.Core— query services and DTOsDungeonMaster.Shared— character sheet DTOsNew interfaces in
DungeonMaster.CoreIPlayerCharacterQueryService— read-only character sheets + campaign listIPlayerCharacterOverrideService— DM override operationsIntegration points with existing systems
Domain Model
Records
API Contract (Rory)
Endpoints
GET /api/campaigns/{id}/characters— DM-only list of charactersGET /api/characters/{id}— DM + owning playerPUT /api/characters/{id}/overrides— DM-only inline overrides (HP/AC/conditions)UI Specification (Clara)
Page / component breakdown
/campaigns/{id}/characters) — DM view for all PCs/characters/{id}) — detailed sheet viewBlazor component list
CampaignCharacterListPages/Characters/CampaignCharacterList.razor/.razor.csCharacterDetailPages/Characters/CharacterDetail.razor/.razor.csCharacterPortraitCardComponents/Characters/CharacterPortraitCard.razor/.razor.csAbilityScoreGridComponents/Characters/AbilityScoreGrid.razor/.razor.csEquipmentPanelComponents/Characters/EquipmentPanel.razor/.razor.csSpellListPanelComponents/Characters/SpellListPanel.razor/.razor.csOverrideModalComponents/Characters/OverrideModal.razor/.razor.csTheme / styling requirements
var(--color-surface)for card backgroundsvar(--spacing-md)for layout spacingvar(--font-size-lg)for character name headingUser interaction flow
Test Scenarios (Danny)⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
Given a campaign with two characters
When the DM opens the character list
Then both characters display with name, class, and level
Given a DM updates HP via OverrideModal
When the API returns success
Then the UI reflects the new HP value
Edge cases
Given a character has no portrait
When CharacterDetail loads
Then a placeholder image is displayed
Given the player is not the owner
When they request
/api/characters/{id}Then the API returns
403 ForbiddenError / failure cases
Given invalid override data (negative HP)
When PUT
/overridesis calledThen the API returns
400 Bad RequestGiven the API is unavailable
When the character detail page loads
Then an error state is shown
Acceptance Criteria
Functional
Non-functional
Dependencies
Agent Work Breakdown
Definition of Done