Skip to content

Repository files navigation

Milon

Milon

Local-first personal fitness dashboard with an LLM coach.
Eine Frage im Zentrum: „Wo werde ich besser, wo schlechter?"

license CC0-1.0 local-first FastAPI Next.js 16 SQLite MCP


Was macht das Projekt?

Milon zieht deine über viele Apps verstreuten Fitnessdaten an einem Ort zusammen — Körperdaten, Schritte, Laufen & Radfahren (Health Connect), Krafttraining (Hevy) und Ernährung (FDDB) — und beantwortet die eine Frage, die zählt: werde ich besser oder schlechter? Vier Bereiche (Körper · Laufen · Kraft + ein LLM-Coach) zeigen Trends, Prognosen und ehrliche Auswertungen.

Alles läuft lokal auf dem eigenen Rechner — die Gesundheitsdaten verlassen die Maschine nie. UI deutsch, Code englisch. Bewusst schlank.

Körper · Laufen · Kraft

Screenshots

Kraft-Analyse: Gesamtstärke-Index und Stärke ↔ Energiebilanz
Kraft-Analyse — drift-freier Gesamtstärke-Index, Stärke ↔ Energiebilanz, Tonnage & RPE.

Trainings-Konsistenz-Heatmap mit Streak
Trainings-Konsistenz (Übersicht) — GitHub-Style-Heatmap über 365 Tage + aktueller Streak.

Welche Funktionen bietet es?

Bereich Highlights
Übersicht Wochenvergleich (rollierende 7 Tage), Konsistenz-Heatmap + Streak, PR-Trophäen, letzte Aktivitäten
Körper Gewichts-/KFA-Trends (roh · 7-Tage · EWMA), adaptives TDEE, Magermasse/Recomp, Komposition-Prognose
Ernährung kcal + Makros (Protein/KH/Fett), Protein Ø/Tag vs. Ziel, Defizit vs. TDEE
Gesundheit Schritte (Galaxy-Watch-genau), Radfahren
Laufen Wochenvolumen, Pace-Trend, VO₂max
Kraft alle Übungen nach Muskelgruppe, e1RM/Tonnage/RPE, Übungs-Detailseiten, drift-freier Gesamtstärke-Index, Stärke ↔ Energiebilanz
Fortschritt Foto-Timeline mit Browser-Crop (3:4) + Silhouetten-/Pose-Schablonen
Coach LLM-Coach mit Tool-Calling (ruft die echten Kennzahlen selbst ab) + Kosten/Token-Statistik
Einstellungen Keys maskiert, Modellwahl, Scheduler-Toggle

Zwei analytische Schmuckstücke:

  • Gesamtstärke-Indexein Wert für „werde ich insgesamt stärker?". Wöchentlich aufgelöst und drift-frei: ein monatlicher, muskel-balancierter, verketteter e1RM-Index als Rückgrat plus eine monatsverankerte Wochenspur (Methodik per Design-Panel validiert & adversarial reviewed).
  • Stärke ↔ Energiebilanz — korreliert den Index mit TDEE/Defizit und sagt ehrlich, was belastbar ist (Woche-zu-Woche ≈ 0) und was nur Schein-Trend (Niveau-Korrelation), plus ein Phasen-Read (Cut/Recomp).

Wie ist die Architektur aufgebaut?

„Eine Abfrageschicht, drei Gesichter": die metrics/-Funktionen sind die einzige Wahrheit und speisen REST, den Coach und den MCP-Server — alle lesen dieselbe lokale SQLite-DB.

flowchart LR
  HC["Health Connect"] --> ING
  HV["Hevy API"] --> ING
  FD["FDDB"] --> ING
  ING["ingest/ (inkrementell)"] --> DB[("SQLite · data/tracker.db")]
  DB --> M["metrics/ Schicht"]
  M --> REST["REST /metrics/*"]
  M --> CO["LLM-Coach (Tool-Calling)"]
  M --> MCP["MCP-Server (20 Tools)"]
  REST --> UI["Next.js Dashboard"]
Loading
  • Backend server/ — FastAPI · SQLModel/SQLite · pandas/numpy · APScheduler · FastMCP · OpenAI-SDK (OpenRouter)
  • Frontend client/ — Next.js 16 (App Router, TS) · Tailwind v4 · Inline-SVG-Charts (keine Chart-Lib)
  • Coach — OpenRouter (OpenAI-kompatibel), Context-Injection und Tool-Calling
  • Design design/ — Studie „Klar & Klinisch" + gpt-image-2-Asset-Tooling

Welche Datenquellen können angebunden werden?

Quelle Was Wie / benötigte API
Health Connect (Android) Gewicht, KFA, Schritte, Laufen, Radfahren, VO₂max automatischer Drive-Pull der täglichen Export-Zip (öffentlicher Datei-Link → HC_DRIVE_FILE_ID, keylos via gdown) oder Zip manuell nach data/incoming/ legen
Hevy Krafttraining (Sätze, Gewicht, Reps, RPE) offizielle Hevy-API (HEVY_API_KEY), echter Inkrement-Sync via /v1/workouts/events
FDDB Ernährung (kcal + Makros) Login-Cookie fddb (oder Auto-Login mit FDDB_USER/FDDB_PW), CSV-Export
OpenRouter LLM-Coach OpenAI-kompatibler Endpunkt (OPENROUTER_API_KEY, Modell frei wählbar)

Alle Quellen sind optional — Milon läuft auch nur mit einer davon. Importe sind idempotent (?full=true erzwingt eine Voll-Reconciliation).

Wie erfolgt die Einrichtung?

1) Secrets anlegen

Vorlagen kopieren und echte Werte eintragen — die echten .env werden nie committet (gitignored):

cp .env.example .env                 # OPENAI_API_KEY (nur Design-Asset-Generierung)
cp server/.env.example server/.env   # App-Secrets (siehe Tabelle)
Datei Variable Zweck
server/.env OPENROUTER_API_KEY LLM-Coach (OpenRouter)
OPENROUTER_MODEL Modell-ID, z. B. deepseek/deepseek-v4-flash
HEVY_API_KEY Hevy-Krafttraining-Sync
FDDB_USER / FDDB_PW FDDB-Auto-Login (Ernährung)
FDDB_COOKIE alternativ: fddb-Cookie (userid,token)
HC_DRIVE_FILE_ID Health-Connect-Auto-Pull: Datei-ID aus dem Drive-Freigabelink der Export-Zip
DATABASE_URL optional, Default sqlite:///./data/tracker.db
.env (Root) OPENAI_API_KEY nur für gpt-image-2-Design-Assets
client/.env NEXT_PUBLIC_API_URL optional (Default: /api-Proxy)

2) Backend (FastAPI)

cd server
python -m venv .venv && .venv/Scripts/pip install -e .   # Linux/Mac: .venv/bin/pip
.venv/Scripts/python -m uvicorn app.main:app --host 0.0.0.0 --port 8000   # Docs: /docs

3) Frontend (Next.js)

cd client
npm install && npm run dev          # http://localhost:3000

In VS Code gibt es fertige Tasks (Start: Server + Client, Design: HTML-Server). Das Handy erreicht das Dashboard im Heim-WLAN über http://<PC-IP>:3000 — das Frontend proxyt /api/* serverseitig ans Backend (kein CORS, keine Firewall-Freigabe für :8000 nötig).

4) Daten importieren

curl -X POST http://localhost:8000/ingest/hevy            # Hevy
curl -X POST http://localhost:8000/ingest/fddb            # FDDB
# Health Connect aus Google Drive ziehen (HC_DRIVE_FILE_ID gesetzt):
curl -X POST http://localhost:8000/ingest/health-connect-pull
# ...oder die Export-Zip manuell nach data/incoming/ legen und:
curl -X POST http://localhost:8000/ingest/health-connect
curl -X POST "http://localhost:8000/ingest/refresh"       # alle Quellen + Status

Ab Phase 2 erledigt das ein Scheduler automatisch (Hevy alle 6 h, FDDB täglich, HC-Drive-Pull täglich 05:00 + Ordner-Scan). Für den Drive-Pull: die Export-Zip in Drive auf „Jeder mit dem Link" freigeben, den Datei-Link kopieren und die ID daraus als HC_DRIVE_FILE_ID in server/.env.

5) Alternativ: Docker (docker-compose)

Statt Backend und Frontend einzeln zu starten, gibt es ein schlankes Zwei-Container-Setup für Docker Desktop. Voraussetzung: server/.env existiert (siehe Schritt 1).

docker compose up -d --build      # baut & startet server + client
docker compose logs -f            # Logs verfolgen
docker compose down               # stoppen

Aufruf danach: http://localhost (Port 80). Im Heim-WLAN erreicht das Handy das Dashboard über http://<PC-IP> — z. B. http://192.168.0.26.

  • Nur das Frontend ist von außen erreichbar. Der FastAPI-Server hat keinen Host-Port; er lebt nur im internen Compose-Netz (Servicename server) und wird vom Frontend serverseitig unter /api/* angesprochen. Die Host-Ports 3000 und 8000 bleiben frei für andere Projekte.
  • Frontend-Port ist per WEB_PORT überschreibbar (z. B. WEB_PORT=8080 in einer .env im Repo-Root, falls Port 80 belegt ist).
  • Persistenz: data/ (SQLite-DB, incoming/, Fortschritts-Fotos) und server/.env sind als Volumes gemountet — Daten und Secrets überleben Rebuilds; die Settings-Seite schreibt nach server/.env zurück.
  • RAM: ~150 MB im Leerlauf (Server ~110 MB, Client ~35 MB), kurze Spitzen beim großen Health-Connect-Import. Das Grundrauschen von Docker Desktop selbst (WSL2-VM, ~1–2 GB) kommt hinzu.
  • Der MCP-Server läuft nicht im Container — er liest data/tracker.db direkt und wird über .mcp.json gestartet (siehe Beispiel-Workflows).

Der Next-Rewrite-Proxy backt sein Backend-Ziel zur Build-Zeit ein; das Compose reicht es daher als Build-Arg API_PROXY_TARGET=http://server:8000 durch. Wer den Server unter anderem Namen/Port fährt, baut den Client neu (docker compose up -d --build client).

Beispiel-Workflows

  • Frag deine Daten: Reiter Coach → „Wie ist mein Kraft-Trend diese Woche?" — der Coach ruft per Tool-Calling die echten Kennzahlen ab und antwortet ehrlich-motivierend (Markdown).
  • Täglicher/Wöchentlicher Report: ein Klick erzeugt einen kompakten Lagebericht; Kosten/Token werden je Report mitgeschrieben.
  • Stärke über Zeit: Reiter Kraft → Gesamtstärke-Index mit Umschalter 1M/3M/6M/12M, dazu die Treiber-/Bremse-Übungen und die Stärke-↔-Energiebilanz-Karte.
  • Aus Claude/Cursor heraus (MCP): der MCP-Server (python -m app.mcp.server, registriert über .mcp.json) exponiert 20 Tools über dieselbe Datenschicht — die Fitnessdaten lassen sich so direkt im Editor/Chat befragen.

Projektstruktur

server/   FastAPI: ingest/ · metrics/ · coach/ · mcp/ · sync/ · api/
client/   Next.js: app/ (9 Seiten) · components/ · lib/
design/   „Klar & Klinisch"-Studie + Foto-Schablonen + Asset-Tooling
data/     tracker.db + incoming/ (lokal, gitignored)
docs/     README-Bilder
docker-compose.yml · server/Dockerfile · client/Dockerfile   schlankes Container-Setup

Sicherheit & Privatsphäre

  • Secrets liegen ausschließlich in .env (jede Ebene gitignored); committet werden nur die *.env.example-Vorlagen mit leeren Platzhaltern.
  • Gesundheitsdaten (data/, *.db, Fortschritts-Fotos) sind gitignored und werden nie committet.
  • Local-first: keine Cloud, keine Telemetrie. Der einzige ausgehende Aufruf ist der LLM-Coach (OpenRouter) — und nur, wenn du ihn nutzt.

Lizenz

Veröffentlicht unter der CC0 1.0 Universal Public-Domain-Dedication — gemeinfrei, ohne Gewährleistung. Du darfst alles damit machen: nutzen, ändern, weitergeben, auch kommerziell, ohne Namensnennung. (Marken-/Patentrechte sind davon nicht berührt.)

Status

Phasen 1–3 umgesetzt: Ingest (inkl. Health-Connect-Auto-Pull aus Google Drive) + Metriken + Dashboards · Auto-Syncs (Scheduler) · MCP-Server. Phase 4 (Hosting) angefangen: schlankes docker-compose-Setup für Docker Desktop (nur das Frontend nach außen, Server intern).

Source of Truth für Architektur & Plan: ARCHITECTURE.md. Projekt-Memory: CLAUDE.md.

About

Local-first personal fitness dashboard with an LLM coach — unifies Health Connect, Hevy & FDDB into Body · Running · Strength analytics. FastAPI + Next.js, MCP server included.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages