System State View — Frontend Handoff
For: Socrates 🧠 (Backend)
From: Daedalus 🎨 (Frontend)
Date: 2026-04-26
Files Delivered
| File | Path |
|---|---|
| Template | shared/project-docs/dashboard/templates/system-state.html.j2 |
| Stylesheet | shared/project-docs/dashboard/static/system-state.css |
Integration Checklist
1. Route Registration
Add to your FastAPI/Starlette routing:
from fastapi import APIRouter
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
router = APIRouter(prefix="/system")
templates = Jinja2Templates(directory="path/to/dashboard/templates")
@router.get("/state", response_class=HTMLResponse)
async def system_state_page(request: Request):
# GET /system/state should return HTML (this page)
# The same endpoint serves JSON via Accept header or ?format=json
# This template expects the JSON data as context variables
return templates.TemplateResponse(
"system-state.html.j2",
{
"request": request,
# Pass the API response data here
"family": {...},
"members": [...],
"rules": [...],
"routing_decisions": [...],
"telemetry": {...}
}
)
2. Static File Serving
Copy system-state.css to your static directory:
cp shared/project-docs/dashboard/static/system-state.css /path/to/dashboard/static/
3. Template Filter Needed
Add this Jinja2 filter for time formatting:
from datetime import datetime
def format_time(value):
if isinstance(value, str):
dt = datetime.fromisoformat(value.replace('Z', '+00:00'))
else:
dt = value
now = datetime.now(dt.tzinfo)
diff = now - dt
if diff.days == 0:
if diff.seconds < 3600:
return f"{diff.seconds // 60}m ago"
return f"{diff.seconds // 3600}h ago"
if diff.days == 1:
return "Yesterday"
return dt.strftime("%b %d")
# Register in your Jinja2 environment
env.filters['format_time'] = format_time
4. HTMX Polling
The container has hx-trigger="load, every 30s" — the endpoint must:
- Return HTML when requested normally
- Re-render the template with fresh data on each poll
Template Variables Expected
{
"family": {
"family_id": "hoffmann",
"member_count": 4,
"rule_count": 7
},
"members": [
{
"id": "sully",
"name": "Sullivan",
"nickname": "Sully",
"current_grade": 1,
"school": "...",
"teacher": "Mrs. Smith",
"calendar_color": "blue", # blue, pink, purple, green, orange
"stats": {
"documents_routed": 12,
"avg_confidence": 0.94
}
}
],
"rules": [
{
"id": "rule_001",
"description": "Sully's grade level and teacher",
"pattern": "first grade|1st grade|grade 1|Mrs\\. Smith",
"assign_to": ["sully"],
"confidence": 0.95,
"status": "active", # active, inactive, disabled
"last_triggered": "2026-04-26T14:30:00Z",
"trigger_count": 15
}
],
"routing_decisions": [
{
"id": 123,
"timestamp": "2026-04-26T14:30:00Z",
"document_title": "Field Trip Permission Slip",
"source": "telegram",
"inferred_members": ["sully"],
"confidence": 0.95,
"rule_triggered": "rule_001",
"action": "auto_routed", # auto_routed or user_asked
"briefing_sent": true
}
],
"telemetry": {
"total_documents": 45,
"auto_routed": 38,
"user_asked": 5,
"errors": 2,
"avg_processing_time_ms": 3200,
"confidence_distribution": {
"high": 38,
"medium": 5,
"low": 2
}
}
}
Design Notes
- Extends
base.html.j2for consistent nav/header - CSS uses existing design tokens from
style.css - Member colors mapped: blue, pink, purple, green, orange (falls back to indigo)
- Mobile responsive: decisions stack vertically on narrow screens
- Bar charts are pure CSS flex (no external charting libs)
Success Criteria
- [ ] Page loads at
/system/state - [ ] Shows all 4 family members with confidence bars
- [ ] Shows all rules with regex patterns
- [ ] Shows confidence distribution as CSS bars
- [ ] Shows last 10 routing decisions with status icons
- [ ] Refreshes every 30s via HTMX
- [ ] Works on mobile without horizontal scroll
Questions?
Tag @Daedalus89Bot or drop a note in shared/project-docs/.