Uplift - for Strava athletes
Sindhu15

Sindhu15 @sindhu15

Joined:
Jun 12, 2021

Uplift - for Strava athletes

Publish Date: Jun 18
0 0

I’m a developer who’s into fitness and now slowly falling in love with running.

A few months ago, I joined a small running group guided by a coach. Initially, I couldn’t understand why people enjoyed running so much. I struggled, gasped for air, and mostly kept going because I needed a distraction.

When I hit my first non-stop 10k I couldn't stop comparing it with my very first run and appreciate how far I had come. That moment stuck with me.

The Why

A race was coming up for our group. I couldn’t participate due to an injury, but I knew many were giving it their all — their first 5K or 10K. I wanted to build something to celebrate their progress and efforts. And for myself, it was a chance to practice system design by building something end-to-end.

And so, Uplift was born — a quick weekend project built to celebrate each runner’s journey using their Strava data.

Project Goals

  • Appreciate the effort of runners in my group
  • Show them how far they've come using Strava stats
  • Generate a motivating, AI-powered message based on their data
  • Ship fast and keep it simple

Tech Stack

Backend: Node.js with Koa (my comfort zone)
Frontend: HTML, CSS, Vanilla JS (needed speed)
Integrations:
Strava API (OAuth + Activity fetch)
OpenAI (with fallback to Together AI)
QuickChart for journey graphs
Deployment: Render (simple and quick)
Logging: Google Sheets + Script

Feature Breakdown

Strava OAuth

  • Registered the app to get client_id and client_secret
  • Used OAuth flow to get access and refresh tokens
  • Set up a callback route /callback
  • Read user activities using /athlete/activities
  • Followed their guidelines on logo placements etc


Report Generation
Each report includes:

  • Total runs and distance
  • Longest run
  • Fastest run
  • Recent Run
  • First run (to see the contrast)
  • A chart showing their weekly run stats
  • A motivational AI insight

** AI Insight**
I crafted a detailed prompt asking the AI model to write a personalized, friendly uplifting message celebrating the user’s journey with the data provided to the LLM.

  • OpenAI GPT-3.5 Turbo as the default model
  • Together.ai Mistral-7B-Instruct as fallback
  • Plain text as fallback if both models fail (If we exceed the quota in both models)

Graphs
Used QuickChart to generate a visual summary of the user’s consistency
Simple, fast and suited for small-scale usage

Download the report as an image
Initially added a text asking the user to manually take a screenshot. After I was done with the design tweaks and data I wanted to show, I realised manual screenshot was not very efficient as the user had to scroll down and take 2 images if the report was slightly longer. So now had to support downloading as an image as that was more user friendly. Used html2Canvas to support this usecase.

Strava-hosted profile images didn’t render in the canvas export. I created a proxy route to handle image downloads properly.

Taking it a step further
I tested on my Strava account. With the race just a day away, I wanted to surprise the group. I enabled international transactions on my card and paid around $5 to enable better AI responses (hello, crazy mode 😄), and told the group something exciting was coming up.

Roadblock: Connected Athletes Limit

Everything was ready and I asked a friend to try it out, thats when I realized there was a limit on the number of users allowed to connect.

I panicked. I had already told my group there was a surprise waiting. I really wanted people to use it right after the race. I wrote an email to Strava with the screenshots of my app, my linkedIn profile etc. I activated my linkedIn premium and reached out to support people from Strava requesting if they could do anything to increase it.

Eventually, I calmed down, figured out the right process, and submitted the form. I was transparent and informed my group about it.

Polish & Improvements

With extra time while waiting for the increased limit, started fine tuning a few things.

Refined prompt

Logging
I wanted to understand the basic usage of my app. But I also wanted something very quick and didn't want to spend too much time on this. Google sheets with a script deployment was sufficient for this.
Used Google Sheets + Script deployment to log basic usage info: timestamp, model used, and origin. No user data was stored — just a hashed athlete ID. Privacy first!
Image description

  • Supported error states with friendly messages Image description
  • Created *feedback form *(Google Form)
  • Added email contact for support
  • Replaced the “latest run” with more meaningful milestones

Caching
Added caching to handle Strava's 200-requests-per-15-min rate limit

Design Iterations:
I made n number of tweaks on:

  • Text placement
  • Font sizing
  • Chart layout

Logo:
Spent an unreasonable amount of time creating the logo and the name 😅
Image description

This is a privacy first app. No user data is stored.

End Result

Here goes my report :D

Image description

My takeaways:

  • OAuth
  • Got to explore Strava APIs
  • AI prompting and data feeding for AI insights
  • Starting with an idea, building and launching a product end-to-end
  • Feedback from real users
  • Always check rate limits and access caps
  • Ship fast, but communicate clearly when things go sideways
  • Tiny touches — profile pics, download buttons, fun copy — make a big difference
  • Excitement when users used my app

Try Uplift!

If you’re a runner on Strava, try it out and see your journey celebrated beautifully.
https://sindhus-stride.onrender.com

Pre-requisite: A Strava account with a few runs logged.

Uplift is simple. But it’s made with heart and all the tech I have mentioned in this blog :P A weekend well spent :)

Here's me: LinkedIn
Also published on medium - https://a-sindu15.medium.com/uplift-for-strava-athletes-1317ad5b9645

Comments 0 total

    Add comment