Garmin Analyzer is a 100% client-side, open-source tool that turns the raw .fit / .tcx / .gpx files your Garmin (or Wahoo, Coros, Bryton, Suunto, Polar, …) device exports into beautiful, shareable posters and short animated videos — the kind you actually want to put on Instagram Stories, your WeChat Moments, or Strava.
Garmin Connect's charts are functional. Strava's stats stickers are basic. Relive is great but paywalled. Garmin Analyzer is the love child that's free, open source, and never uploads your data anywhere.
Pick the look that matches the ride. Each theme renders at native print resolution and exports as PNG / JPG / WebM-MP4.
| Theme | Vibe | Best for |
|---|---|---|
| Dark Race | Neon-on-black, racing telemetry | Crit / interval session / KOM attempt |
| Light Mono | Editorial, oversized type, b&w | "Sunday long ride", clean aesthetic |
| Retro Map | Vintage paper, hand-drawn route | Bikepacking, exploration, gravel |
| Neon Cyber | Magenta/cyan gradient, scanlines | Indoor trainer PRs, late-night Zwift |
Each theme exports at:
1080×1920— Instagram Stories, WeChat Moments, RED (Xiaohongshu)1080×1080— Instagram feed, Twitter/X
Plus an 8-second animated WebM/MP4 with route-draw, count-up numbers, and elevation reveal.
→ https://guanxiaol.github.io/garmin-analyzer/
Drag your .fit / .tcx / .gpx onto the page. Done. Your file never leaves your browser.
git clone https://github.com/guanxiaol/garmin-analyzer.git
cd garmin-analyzer
pnpm install
pnpm dev # → http://localhost:5173pnpm typecheck # strict TypeScript
pnpm build # production bundle in dist/
pnpm preview # preview the production buildRequires Node 18+ and pnpm 9+ (npm/yarn also work).
Not just pretty charts — Garmin Analyzer ships proper sports-science math used by coaches:
| Metric | Formula / Source | Notes |
|---|---|---|
| NP (Normalized Power) | Coggan 30-s rolling, 4th-power average | Industry standard |
| IF (Intensity Factor) | NP / FTP |
Set FTP in Settings |
| TSS (Training Stress Score) | ((duration × NP × IF) / (FTP × 3600)) × 100 |
Coggan |
| Power zones (1–7) | % of FTP — Coggan tiers | Configurable |
| HR zones (1–5) | % of LTHR | Configurable |
| Mean-Maximal Power Curve | Per-second resampled sliding window | 1s / 5s / 30s / 1min / 5min / 20min / 60min |
| Work (kJ) | Σ power × dt / 1000 |
|
| Auto climb detection | Sustained grade ≥ 3 %, length ≥ 300 m, merged gaps ≤ 120 m | Categorized HC / Cat 1-4 by score |
| Hard-effort intervals | 30-s smoothed power ≥ 0.9 × FTP, contiguous ≥ 60 s |
All formulas live in src/lib/metrics/ — read the source, file an issue if a number disagrees with your reference tool.
Frontend React 18 · TypeScript (strict) · Vite 5 · TailwindCSS 3
State Zustand 5 (persist middleware for settings)
Charts Apache ECharts 5 (time-series, power curve, zone bars)
Route map Pure SVG with metric-based colouring (zero external dependencies)
Parsers fit-file-parser 3.x · native DOMParser (TCX / GPX)
Image export html-to-image (DOM → PNG/JPG, no canvas re-render)
Video export Canvas 2D + MediaRecorder (browser-native, no FFmpeg)
Hosting GitHub Pages via GitHub Actions
Why this stack?
- 100% in-browser. No server, no backend, no upload. Your Garmin data is yours.
- Tiny deploy. Static files (~470 KB gzipped). Hosting cost: $0/month forever.
- No vendor lock-in. Everything is MIT.
flowchart LR
A[".fit / .tcx / .gpx"] --> B[parsers]
B -- "unified Activity{}" --> C[metrics]
B --> D[SVG route view]
C --> E[poster templates]
C --> F[charts]
E --> G["html-to-image → PNG/JPG"]
E --> H["Canvas 2D + MediaRecorder → WebM/MP4"]
G --> I["📲 IG / WeChat / X / RED"]
H --> I
style A fill:#0c0f14,stroke:#c7ff3a,color:#c7ff3a
style I fill:#0c0f14,stroke:#ff3ec9,color:#ff3ec9
Reading order of the source:
src/types.ts— theActivitytype modelsrc/lib/parsers/— file →Activitysrc/lib/metrics/—Activity+ settings → derived numberssrc/components/posters/—Activity→ JSX postersrc/lib/export/— DOM/Canvas → PNG/MP4
The app has a built-in export guide (click "How to export?" on the home page). Short version:
- Easiest — Open https://connect.garmin.com, find the activity, gear ⚙ menu → "Export Original (.fit)". Drag the file back into Garmin Analyzer.
- USB direct — Plug your device into your computer, look inside
Garmin/Activities/for the.fitfiles. (Note: Edge 840/1040 use MTP protocol and need OpenMTP on macOS.) - Bulk historical export — Account Privacy → "Request your data". Garmin emails you a zip of your entire history in 1–3 days.
- Multi-file batch import (compare 2–4 rides side-by-side)
- Static OSM tile backdrop on posters (currently SVG-only)
- Running-specific template (split pace, cadence overlay)
- Strava one-click upload of generated posters
- Auto-detect best 5-min / 20-min effort and call it out on the poster
- PWA — install as a native app, work offline
- Custom poster editor (drag elements, change colours, custom fonts)
- Importing from Apple Health / Strava direct API
- More languages (FR / DE / JA / ES)
- Team posters — race day group rides
- Yearly review animation (Spotify Wrapped style for cyclists)
- Power-meter accuracy regression suite — compare against TrainerRoad / WKO5
- Optional self-hosted backend for users who want long-term storage
Open an issue to suggest a feature or vote with 👍 on existing ones.
Designers, cyclists, data nerds, frontend engineers — all welcome.
- New poster theme? PR a new file under
src/components/posters/. - Spot a metric mismatch with Intervals.icu or your power-meter app? File an issue with the
.fitfile. - Translation? Add a locale to
src/i18n/index.ts.
See CONTRIBUTING.md for the full guide.
Q: Does Garmin Analyzer upload my files anywhere? No. Files are parsed in your browser. No server. Open DevTools → Network and watch.
Q: My Garmin Edge 840/1040 doesn't show up on macOS over USB. Edge 840/1040 use MTP protocol — macOS doesn't support it natively. Install OpenMTP (free), or just export via the Garmin Connect website.
Q: Why isn't my power data showing?
Garmin Analyzer reads the standard power field in FIT/TCX. If your bike computer recorded power but you don't see numbers, file an issue with a sample file — most likely a vendor-specific extension we haven't seen yet.
Q: Can I host this myself?
Yes — pnpm build outputs static files. Deploy to any static host (Vercel, Cloudflare Pages, Netlify, your own nginx).
Q: Is there a mobile app? Not yet, but the Web app is responsive and works in Safari/Chrome on iOS/Android. PWA support is on the roadmap.
Q: Will you add running / hiking / swimming support? The parser handles them already. UI/templates optimised for those sports are on the roadmap.
Standing on the shoulders of giants:
- Garmin FIT SDK — the binary spec and reference test files
- fit-file-parser — the FIT decoder we use
- ECharts — beautiful, fast charts
- Andrew Coggan & Hunter Allen — for NP/IF/TSS, the math that makes structured training a science
- Strava, Intervals.icu, Golden Cheetah, Relive — for showing what's possible
MIT © 2026 Garmin Analyzer contributors.
Means you can use it commercially, modify it, distribute it, host it for your team — all free. We'd love a star ⭐ if it helped you.
Built with 🧡 for cyclists who care about how their data looks.