Why I Blur the Lines Between Prototype and Real ProductBlurring the Lines Between Prototype and Real Product

What does it take to design digital gear for high-performance athletes? Turns out data and details are at the heart of it all.


Jacky Lee

March 19, 2020

The following is a guest post by Jacky Lee, Product Manager and Software Designer. Jacky is a digital nomad who works and travels across the globe. At Wahoo Fitness he’s helping to create the next generation of fitness devices so high performance athletes can train using data.

Designing with data is becoming the norm and for good reason. Excel spreadsheets, APIs, and data randomizers allow us to test our designs within more realistic scenarios.

At Wahoo Fitness, the data we need to visualize comes from workout activities. A workout consists of timestamps from multiple data streams such as GPS, heart rate, power, cadence, speed and more.

It’s one thing to visualize a completed workout activity, but it’s a different set of challenges designing for a workout in progress.

The experience we’re designing for takes into account a fluctuation of effort, heart rate, perspiration, and mood over a set period of time.

The goal with this project was to create something that looked and behaved like a real product. Using Framer, I was able to create a prototype that streams data in real-time from a Bluetooth enabled heart rate monitor and indoor smart trainer.

Why prototype in Framer

Prototyping a heart rate monitor was a unique challenge. The design couldn’t be just a snapshot of information or a mock-up of how it could possibly work. The prototype had to update in real-time, presenting the user with new information as it came in.

Designing for real-time experiences

Knowing the end experience involved data visualizations that animate according to the user’s biometric input, low fidelity static wireframes simply wouldn’t do. I could have used a keyframe animation tool like Adobe After Effects to compose detailed animations for each interaction, but the animations would be choreographed instead of being triggered by a user interaction. I needed something that would respond based on actions taken by the user. Working with Framer I was able to effortlessly sync real data across components.

Feeding biometric data into components

For the prototype to simulate how the finished product will work, it needed to have the same Bluetooth pairing capabilities. After learning how to use Chrome’s Web Bluetooth API to print my heart rate value into the console, I was able to replicate this same functionality within a component in Framer, something not easily done with other tools.

Looking, feeling, and acting like a real product

This prototype needed to be as close to the real thing as possible so that we could do valuable user testing and assess how it could work in different workout scenarios.

It’s been amazing to be able to use our actual products, namely the Wahoo TICKR Heart Rate Strap and the Wahoo KICKR Smart Indoor Trainer. Testing these prototypes on real devices makes the whole experience a lot more realistic.

Like what you’re reading?

Sign up to our email list to get the best of the Framer blog sent directly to your inbox.

How it all connects and shares data

To funnel heart rate data into any design component in Framer, I used a global state manager library called ReactN. This gives every component the ability to sync with a shared data stream across the entire prototype. The way to do this with ReactN is by using a useGlobal() hook declaration on the top of each component. Before we dive into the examples, let’s quickly look at how data is passed around:

  1. A BluetoothHeartRate code component handles pairing with Bluetooth heart rate monitors. For security reasons, it’s required to trigger this pairing process with a user gesture like a tap. A dialog will open in Chrome where you can select the heart rate hardware from the list and tap ‘Pair’.

  2. If pairing was successful, every time BluetoothHeartRate receives a new heart rate value, we will save that value into a global state manager (ReactN) as an array. Simply put, an array in javascript is a single variable that stores a list of elements. In this case, the array I am storing is a list of my heart rate values, that looks like this: [60, 64, 65, 65, 68, ...]. The example below is a demonstration of how the heart rate array appears in the console every time the component receives a new heart rate value.

  3. Once we have the heart rate array actively saving in the global state manager, any component can use the useGlobal() hook to retrieve the same stream of data. Each component can render the value however it wants. Below is an example of every component using useGlobal() hook at the top level.

Looking at the components

When it comes to athletes, the slightest fluctuations can make all the difference. The process of tracking heart rate and other biometrics throughout a workout enables athletes like Ironman competitors, swimmers, and track runners to maximize the efficiency of their fitness program. For this prototype, I needed a way to serve up both the fluctuations and report of this data over time. Here’s how I did it.

Heart rate values (current and peak)

After retrieving the entire heart rate array from our global state manager, we can perform functions on the array to pick out useful values we want to surface. Here are two component examples that display different things from the same array:

  • CurrentHeartRate: This displays the user’s current heart rate.
  • PeakHeartRate: This displays the user’s highest heart rate recorded since the Bluetooth connection was paired.

Check out the code behind these components.

Heart rate line chart

To plot the entire array with a chart, I used the react-chart-js2 library. Every charting library requires you to format the data differently, but react-chart-js2 can take an array of numbers and effortlessly turn it into a line chart. This was exactly what I needed. I added Framer property controls on top of this component to configure the color, fill, line width, and axes of the charts.

Check out the code behind this component

Heart rate zones

When training, knowing what heart rate zones you’re working within is extremely useful. Every athlete has slightly different zones depending on what their maximum heart rate is. For the ZoneHeartRate component, I used the current heart rate value to determine the zone it belongs in, then animated the shape’s size and color accordingly. I built additional property controls so I can tweak the maximum heart rate and customize the color for each zone on the fly.

Check out the code behind this component

Why hi-fidelity prototyping is worth it

There is one huge benefit to designing in hi-fidelity: speed. Producing this level of work has made things more efficient at many stages of the product design process, meaning we’re able to ship faster.

Communicating ideas

I found that I was able to share my ideas internally more effectively. Presenting a functional prototype or flow rather than a series of flat screens meant there was no room for miscommunication or misinterpretation.

Validating ideas

Hi-fidelity prototypes have helped me validate ideas faster. Making something that actually works quickly shows you where the holes are and whether your idea has any legs. If not, you can move on to the next approach.

User testing

User testing a prototype like this provides much more valuable feedback. Users are able to get the idea faster, the same way as people internally. Because the whole thing is more fleshed out, the feedback you get will generally be more targeted, meaning it’s more actionable.


Once a design has got to that final stage, handoff is going to be a lot more straight-forward too. Because the prototype is so extensive, there’s less room for developers to guess how things should work and fill in the gaps. All going to plan, the final product should be very close to how you imagined it.

The finished prototype

At the end of this exercise, I created 6 heart rate related components. All of them serving as building blocks for larger compositions.

Thanks to Framer’s property controls, I could iterate quickly and produce various compositions and color schemes on the fly. It was great knowing that the data was always in sync between every component.

This was also the first prototype that forced me to do jumping jacks and squats in order to fluctuate my heart rate so that I could test the animations.

In addition to heart rate data, I replicated the exact same components to stream power data from my indoor smart trainer. This meant I could let my bike-riding efforts dictate the animation of the interfaces. Here’s a video demo of it in action.

The end result was a hi-fidelity working prototype that behaved like a finished product. We could mimic a live indoor cycling workout by injecting live data from the Wahoo TICKR Heart Rate Strap and the Wahoo KICKR Smart Indoor Trainer. I had the privilege of demoing this all live at Loupe 2019.

What’s next

Building this prototype has unlocked a lot of potential for what I am currently working on at Wahoo Fitness. Our mission at Wahoo has always been about helping athletes train smarter, with data. Having tools that blur the lines between prototype and end product gives us a unique way to express, test, and iterate ideas without writing any production quality code.

An interesting part of this exercise was the data-first approach—understanding the type and structure of data I could get from the heart rate strap gave me better ideas for how to visualize them.

As designing with data becomes the new norm, I am excited about the future of code-infused design tools and would love to see a day when data binding our interfaces is as simple as picking a typeface or color.

In terms of what’s next in the short-term… I think I’m going to build a simulator so I don’t have to physically do jumping jacks to test my designs.

Like this article? Spread the word.

Bring your best ideas to life

Subscribe to get fresh prototyping stories, tips, and resources delivered straight to your inbox.