Feature Spec: Campaign Dashboard UI (DM Oversight)
| Field |
Value |
| Feature |
Campaign Dashboard UI (DM Oversight) |
| Issue |
#TBD |
| Status |
Draft |
| Author |
The Doctor |
| Date |
2026-04-10 |
Overview
What it does
Provides a Blazor WASM dashboard for the Human DM to monitor active campaigns. The dashboard surfaces active session status, player roster, encounter state, narrative log tail, and dice roll history, plus quick actions (trigger encounter, award loot, send DM message, toggle autopilot).
Why it's needed
The Human DM needs a single pane of glass to oversee gameplay without switching between Discord and multiple UI pages. This dashboard consolidates essential controls and telemetry to keep sessions smooth and auditable.
Out of scope
- Real-time voice or video features
- Full analytics/reporting suite
- Editing world lore or rulesets (separate specs)
Architecture Notes (The Doctor)
Projects / layers touched
New interfaces in DungeonMaster.Core
ICampaignDashboardQueryService — composes dashboard snapshot
Data flow
Dashboard loads /campaigns/{id}/dashboard
→ API calls ICampaignDashboardQueryService
→ Query composes session, encounter, narrative log tail, dice history
→ Web renders panels + quick actions
Integration points with existing systems
Domain Model
Records
public sealed record CampaignDashboardSnapshot(
Guid CampaignId,
Guid? ActiveSessionId,
bool AutopilotEnabled,
IReadOnlyList<PlayerSummary> Players,
EncounterSummary? ActiveEncounter,
IReadOnlyList<NarrativeLogEntry> NarrativeTail,
IReadOnlyList<DiceRollEntry> DiceHistory);
API Contract (Rory)
Endpoints
GET /api/campaigns/{id}/dashboard — returns CampaignDashboardSnapshot
POST /api/campaigns/{id}/dashboard/trigger-encounter — DM-only quick action
POST /api/campaigns/{id}/dashboard/award-loot — DM-only quick action
POST /api/campaigns/{id}/dashboard/dm-message — DM-only; posts to Discord channel
PUT /api/campaigns/{id}/dashboard/autopilot — toggle autopilot
UI Specification (Clara)
Page / component breakdown
- CampaignDashboard (
/campaigns/{id}/dashboard) — main DM oversight page
Blazor component list
| Component |
File |
Purpose |
CampaignDashboard |
Pages/Campaigns/CampaignDashboard.razor / .razor.cs |
Layout container and data loading |
EncounterPanel |
Components/Dashboard/EncounterPanel.razor / .razor.cs |
Active encounter status, HP bars, turn order |
NarrativeTailPanel |
Components/Dashboard/NarrativeTailPanel.razor / .razor.cs |
Last N narrative log entries |
DiceHistoryPanel |
Components/Dashboard/DiceHistoryPanel.razor / .razor.cs |
Recent dice rolls |
QuickActionsPanel |
Components/Dashboard/QuickActionsPanel.razor / .razor.cs |
Trigger encounter, award loot, DM message, autopilot toggle |
PlayerRosterPanel |
Components/Dashboard/PlayerRosterPanel.razor / .razor.cs |
Player cards with HP/AC summary |
Theme / styling requirements
- Use
var(--color-surface) for panel backgrounds
- Use
var(--spacing-md) for panel padding
- Use
var(--color-accent) for active encounter highlights
- No hardcoded colors or inline styles
User interaction flow
- DM navigates to dashboard page for campaign
- Page loads snapshot and displays panels
- DM uses quick actions (trigger encounter, award loot, send message)
- Autopilot toggle updates state and refreshes snapshot
Test Scenarios (Danny) ⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
-
Given a campaign with an active session
When the DM loads the dashboard
Then the snapshot shows session status, players, and narrative tail
-
Given the DM clicks "Toggle Autopilot"
When the API confirms
Then the UI updates the toggle and refreshes the snapshot
Edge cases
-
Given there is no active encounter
When the dashboard loads
Then EncounterPanel shows an empty-state message
-
Given the narrative log is empty
When NarrativeTailPanel renders
Then a placeholder message is shown without errors
Error / failure cases
-
Given the API returns 403
When the DM loads the dashboard
Then the page shows an authorization error state
-
Given quick action fails
When the DM triggers it
Then an error toast is shown and no state changes occur
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 dashboard components |
Danny's tests |
| Rory |
Implement dashboard API/query service |
Core entities |
| Danny |
Confirm all tests pass |
All implementation |
Definition of Done
Feature Spec: Campaign Dashboard UI (DM Oversight)
Overview
What it does
Provides a Blazor WASM dashboard for the Human DM to monitor active campaigns. The dashboard surfaces active session status, player roster, encounter state, narrative log tail, and dice roll history, plus quick actions (trigger encounter, award loot, send DM message, toggle autopilot).
Why it's needed
The Human DM needs a single pane of glass to oversee gameplay without switching between Discord and multiple UI pages. This dashboard consolidates essential controls and telemetry to keep sessions smooth and auditable.
Out of scope
Architecture Notes (The Doctor)
Projects / layers touched
DungeonMaster.Web— dashboard page + componentsDungeonMaster.Api— dashboard query + quick-action endpointsDungeonMaster.Core— dashboard query serviceDungeonMaster.Shared— dashboard DTOsNew interfaces in
DungeonMaster.CoreICampaignDashboardQueryService— composes dashboard snapshotData flow
Integration points with existing systems
Domain Model
Records
API Contract (Rory)
Endpoints
GET /api/campaigns/{id}/dashboard— returnsCampaignDashboardSnapshotPOST /api/campaigns/{id}/dashboard/trigger-encounter— DM-only quick actionPOST /api/campaigns/{id}/dashboard/award-loot— DM-only quick actionPOST /api/campaigns/{id}/dashboard/dm-message— DM-only; posts to Discord channelPUT /api/campaigns/{id}/dashboard/autopilot— toggle autopilotUI Specification (Clara)
Page / component breakdown
/campaigns/{id}/dashboard) — main DM oversight pageBlazor component list
CampaignDashboardPages/Campaigns/CampaignDashboard.razor/.razor.csEncounterPanelComponents/Dashboard/EncounterPanel.razor/.razor.csNarrativeTailPanelComponents/Dashboard/NarrativeTailPanel.razor/.razor.csDiceHistoryPanelComponents/Dashboard/DiceHistoryPanel.razor/.razor.csQuickActionsPanelComponents/Dashboard/QuickActionsPanel.razor/.razor.csPlayerRosterPanelComponents/Dashboard/PlayerRosterPanel.razor/.razor.csTheme / styling requirements
var(--color-surface)for panel backgroundsvar(--spacing-md)for panel paddingvar(--color-accent)for active encounter highlightsUser interaction flow
Test Scenarios (Danny)⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
Given a campaign with an active session
When the DM loads the dashboard
Then the snapshot shows session status, players, and narrative tail
Given the DM clicks "Toggle Autopilot"
When the API confirms
Then the UI updates the toggle and refreshes the snapshot
Edge cases
Given there is no active encounter
When the dashboard loads
Then EncounterPanel shows an empty-state message
Given the narrative log is empty
When NarrativeTailPanel renders
Then a placeholder message is shown without errors
Error / failure cases
Given the API returns 403
When the DM loads the dashboard
Then the page shows an authorization error state
Given quick action fails
When the DM triggers it
Then an error toast is shown and no state changes occur
Acceptance Criteria
Functional
Non-functional
Dependencies
Agent Work Breakdown
Definition of Done