Fitness Tracker¶
TL;DR
A personal fitness tracking pipeline. Workout sessions are logged in Obsidian as Markdown files, parsed by a custom Python ingest layer, and stored in PostgreSQL. Nutrition (Cronometer CSV) and habit tracking are next in the pipeline. Stack: Python, PostgreSQL 16, Obsidian, MkDocs Material.
I train three days a week and log every session. For a long time that data lived in a Google Sheet โ workable, but not queryable. I couldn't answer simple questions: am I actually getting stronger on the squat over the last six weeks? How many sessions did I miss in April? How does my training volume correlate with how I've been eating?
I wanted a real answer to those questions, backed by real data. So I built the pipeline.
How It Works¶
graph TB
A["Obsidian Vault\n(.md files)"] --> B["load_workouts_obsidian.py"]
B --> C["PostgreSQL\nfitness_dev"]
C --> D["generate_reports.py"]
D --> E["report.json"]
E --> F["Lab Dashboard"]
Under the Hood¶
Each workout session is a Markdown file in my Obsidian vault. The frontmatter captures session metadata โ date, bodyweight, duration, notes โ and the body uses a compact set notation: 185x3x5 means 185 lbs, 3 sets, 5 reps. Warmup sets are prefixed with w, bodyweight sets with bw, assisted sets with a negative load (-50x3x5), and timed holds in seconds (28sec) for exercises like dead hangs.
A Python parser scans the vault on demand, resolves exercise names against a movement registry in the database, and upserts sessions and sets into PostgreSQL. Nothing is hardcoded in the parser โ category, primary muscle, and equipment all come from the ft.movements table. If a name doesn't resolve, the parser logs a warning and skips that line rather than failing the whole session.
The schema separates session-level data (ft.workout_sessions) from individual set rows (ft.workout_sets), with a ft.cardio_details child table for treadmill metrics. This keeps strength and cardio data clean without flattening them into the same row shape.
Nutrition and habit tracking are the next two ingest layers โ Cronometer CSV export into ft.nutrition_log, and an Android habits app CSV into ft.habit_definitions and ft.habits_log. The reporting layer will tie all three together.
Stack: PostgreSQL 16 ยท Python ยท psycopg2 ยท PyYAML ยท Obsidian ยท MkDocs Material
Active project
The pipeline is live and the data is real. The Lab dashboard is in progress โ reporting design is the current phase.