#MihiContraMe

Me against myself. A self-hosted AI coach that reads your training data and tells you exactly where you stand — every Monday morning.

The problem

Training apps show you numbers. Distance, pace, heart rate. What they don't do is synthesise those numbers against your recovery signals and tell you what to do next week. You either pay for a human coach, or you guess.

This project is neither. It's a data pipeline that pulls everything I track — rides, health metrics, body composition — and routes it through an LLM prompted to act as a personal endurance coach. Two sentences, every Monday. Building, maintaining, or overreaching. Plus one actionable tip.

How it works

1
Apple Health → PostgreSQL (daily) Health app exports to a webhook. n8n receives it, FastAPI flattens the JSON payload, records upserted into health_metrics — resting HR, HRV, weight, body fat, lean mass, steps, BMI. Each day's data also written as a structured note to Obsidian.
2
Strava → PostgreSQL (on activity) Strava fires a webhook on every completed activity. n8n stores it in strava_activities — distance, elevation, average HR, suffer score, calories, sport type.
3
Weekly query (Monday 9am, Berlin) n8n runs two parallel Postgres queries: current-week Strava stats vs previous week, and current-week health metrics vs 4-week baselines. Results merged into a single flat JSON object.
4
GPT-4.1 coach analysis The merged data goes to GPT-4.1 with a strict prompt: personal endurance coach, exactly 2 sentences. Sentence one classifies the week — building, maintaining, or overreaching — against the baselines. Sentence two gives one specific, actionable tip for next week. No fluff.
5
Delivery → Telegram Two parallel outputs: a formatted text message with trend arrows (↑↓→) comparing this week vs baselines, and a visual summary card generated by the FastAPI sidecar. Both sent to Telegram.

What it tracks

Training load

  • Sessions, distance (km)
  • Elevation gain
  • Moving time, calories
  • Average heart rate
  • Suffer score
  • Year-to-date totals

Recovery signals

  • Resting heart rate
  • Heart rate variability (HRV)
  • Daily step count
  • Weight, body fat %
  • Lean body mass
  • All vs 4-week baselines

Example output

What lands in Telegram every Monday:

📊 Week in Review (2026-06-16 → 2026-06-23) 🏃 4 → sessions | 187.3 km ↑ | 2,340 m elev ↑ | 6.2 hrs → 💓 Avg HR: 142 bpm → | Suffer: 312 ↑ | Calories: 4,890 kcal ↑ 😴 Resting HR: 48 bpm ↓ | HRV: 62 ms ↑ | Steps: 9,240/day ↑ ⚖️ Weight: 78.2 kg → | Fat: 14.1% ↓ | Lean: 67.2 kg ↑ 📈 Body comp vs 4w: gaining muscle (+0.3 kg) 💬 Training load is up meaningfully while recovery markers — lower resting HR and rising HRV — confirm you're absorbing the work rather than accumulating fatigue; you are building. Cap Tuesday's interval session at 85% of threshold power to protect those HRV gains into the following week. #WeeklyReview #MihiContraMe

Plus a visual summary card generated by the FastAPI sidecar and sent as a photo.

Tech stack

n8n PostgreSQL GPT-4.1 FastAPI Python Strava API Apple Health Telegram Bot API Proxmox Docker Obsidian REST API

Infrastructure

Everything runs on a self-hosted Proxmox homelab. n8n and the FastAPI sidecar run as Docker containers inside the same LXC container, on the same Docker network — n8n calls FastAPI over internal HTTP, no external traffic for the core pipeline. PostgreSQL runs alongside them. Cloudflare Tunnel exposes n8n externally for incoming webhooks from Strava and Apple Health.

No subscriptions beyond the OpenAI API. No vendor lock-in. If OpenAI goes down, I swap the model node. If Telegram changes its API, I swap the delivery step. The pipeline is modular by design.