Fitness Dashboard¶
- URL: https://fitness.justinsforge.com (CF Access, allowlist [email protected], same policy shape as finances)
- App:
forge/scripts/forge_fitness_app.py(Flask, 127.0.0.1:8093) +forge_fitness_dashboard.html(read at request time, edit without restart) - Unit:
forge-fitness-app.service(systemd, enabled) - Ingress: VR Alliance tunnel (Console), added via
forge_cloudflare_cf.py add fitness justinsforge.com http://127.0.0.1:8093 --tunnel "VR Alliance" - Data sources (all read-only):
data/context.dbfacts_wellness (Eight Sleep + Garmin via ha_poller),data/hevy/raw_hevy_workouts.jsonl+exercise_templates.json(reusesforge_hevy_read._aggregate),data/training_thresholds.json - Recommendation band is the deterministic half of
forge_training_recommendation.py(readiness band + HRV/stress/body-battery/recovery corrections), recomputed per request, no LLM - Eight Sleep side mapping: backfilled rows are left/right (Justin = right), live rows justin/krystal; app merges with justin winning
- Garmin card falls back to the latest date with >=3 metrics and flags "last sync MM-DD" when the watch has not synced today
- Monitored:
business_urls.fitnessin monitor_expected_state.json + tile in Dashboards section of the justinsforge.com landing - Companion one-off:
scripts/forge_wellness_gap_repair.pyrebuilds Wellness Daily Notion rows from facts_wellness after backfills - v2 sections (2026-06-10 evening): strength est-1RM chart + all-time PR table + 90d recent PRs (Epley, reps capped 12, computed from raw Hevy jsonl, 10-min cache); InBody body comp trend; nutrition card from Notion Food Log (forge_food_log reuse, 5-min cache); Hevy
body_measurementsAPI (pageSize max 10, 1h cache) - v3 drill-downs (2026-06-10 night): modal layer; cards with a
+h2 prefix are clickable. Endpoints:/api/detail/sleep+/api/detail/garmin(180d series + 30-night/activity tables),/api/detail/exercise/<name>(full e1RM history + per-session sets),/api/detail/workout/<id>(all sets + matched Garmin). PR rows and session rows open modals; Escape/backdrop closes. - Garmin activities pipeline: forge_garmin_poll.py now dumps last 30 activities (HR, max HR, training load, calories, TE) merged by activity_id into
data/garmin/activities.jsonlevery poll. Dashboard matches them to Hevy workouts by >5-min time overlap (_match_activity); matched HR shows in the sessions table and workout modal. - InBody record keeping:
scripts/forge_inbody_log.py add --date ... --weight-lb ...writes facts_wellness source=inbody via /ingest (idempotent). 8 scans imported 2026-06-10: 6 from Drive sheet "2023-09-12_InBody-Scan-Results.xlsx" (2022-11..2023-09) + 2026-03-24 InBody570 + 2026-06-09 InBody580 Onnit. New scan = run the CLI (or ask a session); no Notion copy, forge is canonical per routing test
Related: [[wellness-pollers]], [[hevy-pipeline]], [[training-recommendation]]
[Claude Code]