Skip to main content
Back to Work

Strava Local

Local-first fitness analytics, your data stays on your machine

Live
Python Flask SQLite Leaflet Jinja2
Strava Local dashboard showing activity overview and statistics
Dashboard with summary stats, activity breakdown charts, and recent activities
Heatmap visualization of all running and cycling routes
Interactive heatmap of every GPS-tracked activity
Training metrics showing fitness and fatigue curves
CTL/ATL/TSB fitness and fatigue tracking over time

Overview

A local ingestion and analysis tool for Strava activity data. Import your Strava export, CSV metadata and FIT files, into a local SQLite database for analysis and visualization. All data stays local. Your activity data, GPS tracks, and training metrics are never uploaded anywhere.

The Problem

I wanted to understand how training metrics actually work, not just see numbers, but compute them myself. Strava shows you TSS and fitness curves, but I wanted to dig into the formulas, experiment with different calculations, and query my data in ways the app doesn't support. Building this gave me a deeper understanding of training science and a local archive of years of activity data I can explore however I want.

What I Built

  • FIT file parser that extracts GPS streams, heart rate, altitude, and cadence from years of activity data
  • SQLite database with normalized schema for activities, streams, and computed metrics
  • Dashboard with summary statistics, activity breakdown charts, and recent activity feed
  • Interactive heatmap and route explorer with activity type and date filters
  • Training metrics engine: TSS, TRIMP, intensity factor, and time-in-zone calculations
  • Fitness modeling with daily CTL/ATL/TSB (chronic training load, acute training load, training stress balance)
  • Athlete settings for personalized calculations: max HR, LTHR, resting HR, FTP, weight
  • CLI tools for data ingestion, metric computation, and map generation

Key Decisions

SQLite was the obvious choice, the entire point is local-first simplicity, and it handles years of activity data without breaking a sweat. Flask + Jinja2 keeps the stack minimal and dependency-light. Leaflet with OpenStreetMap tiles over Mapbox because there's no API key to manage and no usage billing to worry about. GPS routes are downsampled to 500 points max to keep storage reasonable without losing visual fidelity.

Back to all projects