SidelineWorks Build — Integration Status
Date: 2026-05-09
TRACK A: SidelineWorks Marketing Site (Port 8003)
Status: ✅ DONE
| Page | Status | Notes |
|---|---|---|
/ |
✅ 200 | Hero + role cards + CTA |
/product |
✅ 200 | Feature breakdown |
/pricing |
✅ 200 | 3-tier pricing |
/demo |
✅ 200 | Form with POST handler |
/contact |
✅ 200 | Contact form |
/blog |
✅ 200 | Blog index |
/blog/{slug} |
✅ 200 | Individual articles |
/health |
✅ 200 | Health check |
| SVGs | ✅ 200 | Favicon, wordmark, icon, RTSport badge |
Brand Assets Created
static/img/sidelineworks-icon.svg— Shield + medical cross icon for faviconstatic/img/sidelineworks-wordmark.svg— Full wordmark with taglinestatic/img/rtsport-wordmark.svg— RTSport sub-brand badge ("A product by SidelineWorks")
Fix Applied
Starlette 1.0.0 TemplateResponse signature change
Old: templates.TemplateResponse("home.html", {"request": request})
New: templates.TemplateResponse(request, "home.html", {"request": request})
Created tmpl() helper for all routes.
Running at: http://localhost:8003
TODO: Wadsworth to wire Cloudflare Tunnel for sidelineworks.com → port 8003
TRACK B: Dashboard API Unification (Port 8002)
Status: ✅ DONE
Dashboard Server (FastAPI proxy on port 8002)
- Serves all 4 dashboard templates + login page
- Proxies real API (port 8001) with response transformations
- Handles auth via
/api/loginPOST → real API login
Response Transformations
| Dashboard | Field Mismatch | Proxy Fix |
|---|---|---|
| Coach | teams is object, frontend expects array |
transform_teams() converts {Varsity: [...]} → [{team_name, athletes}] |
| Coach | Athlete has current_status, frontend expects status |
Added a["status"] = a["current_status"] |
| Coach | Athlete has case_title, frontend expects injury.body_part |
Added a["injury"] = {"body_part": case_title} |
| AT | stats has full_count/out_count/modified_count, frontend expects cleared/out/modified |
Renamed fields |
| AT | active_cases has athlete_id/athlete_name/injury_short, frontend expects id/name/injury |
Renamed fields |
| AD | Flat total_athletes/active_cases/out_today not nested under school_stats |
Added data["school_stats"] = {...} |
| AD | Sport has athletes/out/modified, frontend expects total_athletes/out_count/modified_count |
Renamed fields |
| AD | Activity has time_ago, frontend expects time |
Renamed field |
| Parent | API expects athlete_id param, frontend sends child_id |
Fixed in parent-tabs.js |
Auth Changes
- New
/loginpage with email/password form dashboard-tabs.js:autoLogin()now parses{access_token, role, school_id}from real API- Auth guard:
checkAuth()redirects to/loginif no token - All dashboard templates include
checkAuth()on DOMContentLoaded
Dashboards Served
| Dashboard | Route | Auth | Real Data |
|---|---|---|---|
| Coach | /coach |
✅ | ✅ (with proxy) |
| AT | /at |
✅ | ✅ (with proxy) |
| Parent | /parent |
✅ | ✅ (with proxy, no parent-child seed data) |
| AD | /ad |
✅ | ⚠️ No ad role user in seed data |
| Login | /login |
— | ✅ |
Running at: http://localhost:8002
TRACK C: Offline Architecture
Status: 🔮 Not started (scoped at 2-3 weeks)
ServiceWorker + IndexedDB + sync queue for sideline entry without internet.
Deferred — focus is Track A + Track B.
Demo Form Webhook
Status: 🔧 Pending (Wadsworth's job)
Demo form POST handler in main.py logs to stdout. Needs:
- Telegram notification via wacli or bot
- Or email notification
Cloudflare Tunnel
Status: 🔧 Pending (Wadsworth's job)
- sidelineworks.com → port 8003 (marketing site)
- Could also expose rtsport app → subdomain
Summary of Running Services
| Service | Port | PID | Status |
|---|---|---|---|
| RTSport API | 8001 | 145233 | ✅ Live (v0.3.0) |
| RTSport Dashboard | 8002 | 154072 | ✅ Live |
| SidelineWorks Marketing | 8003 | 153132 | ✅ Live |
| HoffDesk | 8000 | — | ✅ Live |