Beating 81 with GT81

Jan Ustohal
4 min readDec 11, 2020

This summer, after several months of lockdown, I finally caved in and joined Urban Sports Club, the flexible sports membership offering access to a large number of gyms and studios for a fixed monthly fee.

This meant that I could finally try out some of the most hyped workouts from BEAT81, an ambitious Berlin startup with data-focused indoor and outdoor workouts.

The core idea of BEAT81 is based on each person having a HR monitor, which is connected to a central system. For each minute a person spends above 81% of their maximum heart rate, they get a point (the so called GritPoint). Of course, the goal is to get as many of those as you can, engaging in some friendly competition with others in your class.

BEAT81 setup for outdoor workouts, with the screen showing the HR zone and % for each participant (source: BEAT81)

Now, I love data, especially about workouts. I find it fascinating to quantify the physical effort I put into a bike ride or a HIIT workout, and translate the pain into pure numbers. After all, that was one of the reasons why I got my Apple Watch. That’s also why I loved the concept of BEAT81, compared to other class-based studios.

With the second lockdown, gyms and fitness had to close, which meant my workouts were limited to Zwifting on my turbo trainer, running, and HIIT sessions at home.

While it’s hard to transfer the energy of a live workout to your home, implementing the data driven approach should not be. At the end of the day, my Apple Watch shows me the same data, just without the point system.

That’s why, with some extra lockdown time on my hands I decided to build my own version of the BEAT81 dashboard for my personal workout. And just like that, GT81 was born.

What is it

GT81 (as in greater than 81) is a web-based version of the BEAT81 in-workout dashboard for a single person, leveraging (Web) Bluetooth to connect to a generic, BLE-enabled heart rate monitor.

It uses information from the monitor to display the current heart rate and, based on some basic configuration (gender, age, weight), calculate calories burned and the HR zone (in terms of %). Just like in BEAT81, for each minute one spends in the 81–90 or 91–100 zones, a grit point is counted.

GIF of one of the earliest version of the app (with simulated HR)

How I built this

The app is in TypeScript, running on the wonderful React-based Next.js framework from Vercel, however, it could have probably been written in vanilla JS as well. It’s pretty much 100% client-side, with no DB or API dependency and all storage handled through localStorage. The whole (compiled) app would even fit on a floppy disk.

Bluetooth connection is handled via the native Web Bluetooth API, which makes it really easy to discover and pair devices, even going as far as filtering for devices broadcasting support for specific service (heart_rate_measurement in this case).

⚠️ Because of the dependency on Web Bluetooth GT81 does not work in Safari or on iOS/iPad OS devices, as WebKit does not yet implement the Web Bluetooth API (and likely never will).

When it comes to the calculations, I could just leverage the standard formulas for both calorie burn as well as for max. HR calculation On the latter I’ve opted for the more precise formula for active people instead of the standard 220-age.

The HR monitor ticks with a somewhat dynamic frequency, with 0.5/1/1.5 seconds between pulses. Based on that the app awards an appropriate fraction of calorie / grit point for each tick and sums it all up.

For each tick the HR % is also calculated, highlighting the main component in shades of blue for HR between 60 and 80% of the maximum and shades of pink for 81–100%.

Workout results are all saved in the local storage, even though there is currently no way to display them in the app. That might come in v2.0 😂.

How can you use it

There’s a version running on my website — just go to https://gt81.honza.xyz, connect your HR monitor, and get started.

I’ve also decided to make the source code available on my Github, because it’s time the world sees how bad my fronted code is. And perhaps someone will feel like turning this into something more interesting.

If you have any suggestions, drop me a note or just open a new issue at Github.

Have fun working out! 💪

--

--

Jan Ustohal

Building products 🚀 and trying to make the perfect cup of coffee ☕️. Also 🚴‍. Now working on an early-stage stealth product 🤫. Formerly Marley Spoon, Fyber.