Climb Bandits

Summer 2020

  • Django
  • Leaflet
  • Mapbox
  • React
  • Strava
Browser bar illustration

A few of my friends have been getting into cycling this year, and we’re getting a bit competitive. We’ve found we all enjoy riding up hills – unfortunately there aren’t that many in London. Notable among the few that are nearby is Swains Lane, a low-traffic gem of a climb that has become a training fixture for us. It’s also become part of an ongoing contest to see who can get up it the fastest.

Swains Lane features on the 100 Greatest Cycling Climbs list (no. 27) and I soon realised we were inevitably going to have to spread our competition to some of the other nearby entries. You can buy the official book, and there’s an official paid app that connects with Strava and ticks off the climbs as you conquer them, but as I discovered this my DIY-sense was tingling, and inevitably I started figuring out how I might roll my own way to track this wide-ranging contest.

The result is Climb Bandits – currently in closed beta – a React app running atop a Django backend which uses the Strava API and a list of the official Strava segments that accompany the official “greatest” climbs to build and maintain a leaderboard across the whole list for our little group. The segment and effort data is all present in Strava, but keeping track of multiple segments and leaderboards on their site or app is clunky, and I wasn’t going to punch up my React skills staring at someone else’s work.

After a couple of evenings of tinkering, I had a minimal Django app that implemented an OAuth flow against the Strava API, and a set of scheduled tasks that would retrieve and refresh segment and effort data for all athletes registered with the app. I exposed this data via a JSON endpoint, and then built a React app to load this data and present it in a neat, responsive front-end – using the experience I gained working on Roadsage to include a Leaflet map that displays the selected segment as you browse.

I’m super pleased with how the front-end app came together, and what a great opportunity it’s provided to improve my React skills and implement some new techniques. The app uses Hooks, a new-ish React API that I missed out on using when building Roadsage, as well React Router and a lightweight Redux integration (a library/workflow I was previously a bit scared of). I’m using goober, a lightweight CSS-in-JS library, and SVGR to provide a really nifty SVG icon system. I’m also making heavy use of some of the features of webpack-dev-server to provide a fast-cycle dev environment where I can work on the React app in isolation from the Django backend, and have webpack serve example JSON fixtures in a way that mimics my live data endpoint.

Mobile device illustration

This preview is scrollable!

I deliberately set up the front-end toolchain from scratch rather than using Create React App, as I wanted to gain a better understanding of some of the underlying tools that I felt like I was missing by using those ready-rolled configurations. As a result much of that machinery is less scary and I feel better able to make changes and optimisations now that I’ve built that setup piece-by-piece.

One final aspect I’m really proud of is the design tokens system I’ve implemented to share things like colour palettes and font definitions between the Django and React apps. This is based on an approach I was shown while working at Applied Works, and involves a common JSON file where these tokens are defined, which can be imported into JavaScript-land as well as being converted into SASS variables for use in that environment. The Django app has its own stylesheets for layout and some of the non-app templates, and this system ensures I’m not duplicating definitions between the two worlds.

At some point I may open up the currently closed beta – I need to work out how to scale the UI for more users (perhaps allowing users to define small clubs/teams) and implement an automatically-scaling rate-limited approach to querying the Strava API (perhaps using webhooks instead of polling).

Overall working on this app has been a super useful learning exercise for me, as well as providing great encouragement to get out on my bike and smash it up some hills. An excellent example of how web development can have real-world benefits!

Browser bar illustration