Frontend-Backend Contract — HoffDesk Dashboard
Version: 1.0
Date: 2026-04-29
Status: Active
1. Philosophy
- Python-first appliance. No React, Vue, or build steps.
- HTMX for interactivity. Backend renders, frontend swaps.
- Jinja2 for templating. No inline HTML generation in Python.
- Explicit contracts. JSON and HTML never mix.
2. Endpoint Namespaces
| Namespace | Purpose | Response Type | Caller |
|---|---|---|---|
/ui/* |
HTMX fragments | HTMLResponse |
Browser HTMX |
/api/* |
Machine-readable data | JSONResponse |
External apps, scripts |
/api/public/* |
Unauthenticated data | JSONResponse |
Public consumers |
Rule: If HTMX calls it, it MUST be /ui/* and return HTML.
3. Directory Structure
icarus/templates/
├── base.html.j2 # Base layout (if needed)
├── dashboard/
│ ├── index.html # Dashboard shell
│ ├── login.html # Family login
│ └── components/
│ ├── weather_card.html.j2
│ ├── health_card.html.j2
│ ├── events_list.html.j2
│ ├── events_week.html.j2
│ └── event_detail.html.j2
└── shared/
└── macros.j2 # Shared Jinja2 macros
Rule: Daedalus writes templates here. Socrates references these exact paths in FastAPI routes. No copies, no drift.
4. HTMX Endpoint Contract
4.1 Weather Card
Endpoint: GET /ui/weather-card
Response: HTML fragment (not JSON)
Template: dashboard/components/weather_card.html.j2
Example Response:
<div class="weather-summary">
<span class="temp">44°F</span>
<span class="condition">Rain</span>
<span class="feels-like">Feels like 43°F</span>
</div>
4.2 Health Card
Endpoint: GET /ui/health-card
Response: HTML fragment
Template: dashboard/components/health_card.html.j2
4.3 Events List
Endpoint: GET /ui/events-list
Response: HTML fragment
Template: dashboard/components/events_list.html.j2
4.4 Events Week
Endpoint: GET /ui/events-week?start=YYYY-MM-DD
Response: HTML fragment
Template: dashboard/components/events_week.html.j2
5. JSON API Contract (for external consumers)
Endpoint: GET /api/today
Response: JSON (unchanged — for external apps, not HTMX)
Note: Dashboard does NOT call this via HTMX.
6. Template Ownership
| Template | Owner | Path |
|---|---|---|
| Dashboard shell | Daedalus | dashboard/index.html |
| Weather card | Daedalus | dashboard/components/weather_card.html.j2 |
| Health card | Daedalus | dashboard/components/health_card.html.j2 |
| Events list | Daedalus | dashboard/components/events_list.html.j2 |
| Events week | Daedalus | dashboard/components/events_week.html.j2 |
Rule: Socrates NEVER modifies templates. If data structure changes, he notifies Daedalus to update templates.
7. Current Refactor Tasks
7.1 Socrates Tasks
- Create
/ui/weather-cardendpoint — returns HTML usingweather_card.html.j2 - Create
/ui/health-cardendpoint — returns HTML usinghealth_card.html.j2 - Move
/api/events-list→/ui/events-list - Move
/api/events-week→/ui/events-week - Update dashboard router to import and use templates from
icarus/templates/
7.2 Daedalus Tasks
- Create
icarus/templates/dashboard/components/weather_card.html.j2 - Create
icarus/templates/dashboard/components/health_card.html.j2 - Update
dashboard/index.htmlHTMX calls to use/ui/*endpoints - Ensure CSS classes match between templates and
static/style.css
7.3 Wadsworth Tasks
- Verify both specialists have access to
icarus/templates/ - Check endpoints return correct response types
- Validate on iPad/iPhone
8. Validation Checklist
- [ ]
/ui/weather-cardreturns HTML, not JSON - [ ]
/ui/health-cardreturns HTML, not JSON - [ ]
/ui/events-listreturns HTML (moved from/api/) - [ ]
/ui/events-weekreturns HTML (moved from/api/) - [ ] Dashboard loads weather card with styled data
- [ ] Dashboard loads health card with styled data
- [ ] Events list/week work as before
- [ ] iPhone Safari renders correctly
9. Anti-Patterns (Forbidden)
- ❌ Returning JSON from
/ui/*endpoints - ❌ Generating HTML inline in Python (use Jinja2 templates)
- ❌ Copying templates between directories (use single source)
- ❌ HTMX calling
/api/*endpoints - ❌ Modifying templates without updating corresponding endpoint
10. Version History
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2026-04-29 | Initial contract |
Approved by: Matt Hoffmann (Director)
Enforced by: Wadsworth (Chief of Staff)