A GitHub-style contribution heatmap widget for your Strava running data.
the green border and black background are not part of the widget styling.
This repo is split into two parts:
producer/
Strava auth + sync + aggregation. Generatesproducer/dist/heatmap-data.json.consumer-example/
Minimal website-side example showing how to render that JSON at runtime.
- Go to https://www.strava.com/settings/api.
- Create a new app.
- Set callback domain to
localhost. - Save your:
Client IDClient Secret
git clone <your-repo-url>
cd <repo-folder>
npm installCreate a local .env file:
cp producer/.env.example .envThen fill in:
STRAVA_CLIENT_ID(from your Strava app page)STRAVA_CLIENT_SECRET(from your Strava app page)STRAVA_REDIRECT_URI(example:http://localhost:4242/callback)
Run:
npm run authorize:stravaThe script will:
- Print an authorization URL.
- Ask you to open it and approve access.
- Ask you to paste back the
codefrom the callback URL.
It will save private tokens to:
producer/data/strava-tokens.json(gitignored)
Run:
npm run sync:stravaThis creates/updates:
producer/dist/heatmap-data.json
The sync fetches your full Strava run history, then rebuilds the JSON from that complete dataset.
Your website should read the generated JSON at runtime.
- Copy the contents of
consumer-example/widget/into your website project's static assets so they are served as:
/widget/run-heatmap.js/widget/run-heatmap.css
- Keep both files in the same folder. The widget JS will automatically load
run-heatmap.cssinto the component's Shadow DOM. - Paste this snippet into the target HTML page:
Example web component usage:
<run-heatmap
data-url="https://your-data-host.example/heatmap-data.json"
theme="light"
unit="km"
></run-heatmap>
<script src="/widget/run-heatmap.js"></script>Theme options:
theme="light"theme="dark"
Unit options:
unit="km"unit="mi"
If you want to serve run-heatmap.css from a different URL than the folder that serves run-heatmap.js, set an explicit override with the css-href attribute:
<run-heatmap
data-url="https://your-data-host.example/heatmap-data.json"
theme="dark"
unit="mi"
css-href="/assets/widgets/run-heatmap.css"
></run-heatmap>
<script src="/assets/widgets/run-heatmap.js"></script>You can check consumer-example/ as a complete reference example.
If you run npm run sync:strava only once, your JSON will stay static.
If you want it to auto-update, use one of these approaches:
Set up a cron job in whatever environment is running your producer code.
That cron job should run npm run sync:strava on a schedule so heatmap-data.json keeps updating from that host.
Make sure that hosted heatmap-data.json location is accessible by your website at runtime (same domain or an allowed cross-origin URL).
- Put the producer code in a public GitHub repo.
- Keep the workflow file:
.github/workflows/sync-heatmap.ymlUncomment theschedule:block in that workflow and adjust the cron expression if you want automatic syncs.
- In GitHub repo settings, add these Repository Secrets:
STRAVA_CLIENT_ID(same value you put in.env, from your Strava app page)STRAVA_CLIENT_SECRET(same value you put in.env, from your Strava app page)STRAVA_REFRESH_TOKEN(fromproducer/data/strava-tokens.json, generated after authorization; this file is gitignored)
- Run the workflow once manually from the Actions tab.
- The workflow will keep updating:
producer/dist/heatmap-data.json
Then use the direct public file URL of that JSON in your website component data-url.
For GitHub, this is typically the file URL from the Raw view for producer/dist/heatmap-data.json (or your GitHub Pages file URL if you publish it there).
