Building on the Foundations

Our second and third years of building a product from scratch

Jon Bell
8 min readJan 2, 2024

Two years ago, I wrote “Our First Year of Design Decisions,” about all the product work that went into building Replay.io, a time travelling debugger. At the end of the essay, I shared these images of how the product looked as of then, November 2021:

Viewer mode (2021)
DevTools mode (2021)

Pretty straight-forward, yes? In Viewer mode, we show a big video with some comments on the side. In DevTools mode, we show developers things they’re used to seeing, like a console, source viewer, element panel, a call stack, breakpoints, and so forth. If you’re not a developer, worry not! This is a design lesson about the details that emerge when your product gets more mature. If you like to learn about design, product strategy, and herding cats at a small company, you’re the target audience for this article. For more technical stuff, check out our blog.

Ok! It’s design tour time!

How things look as we kick off 2024

These images look pretty similar to 2021. The comments on the left have thumbnails, the icons are a little different, and there are some small differences. Those small differences are where all the good stuff is!

Viewer mode (2024)
DevTools mode (2024)

Jump to code

See this blue button in the image below? It’s absolutely amazing.

Clicking it takes you to the exact line of code that ran when an event happened, which lets you dive right in and figure out what’s what. We’ve even joked about making into a t-shirt because it’s such a great example of what Replay can do, and it saves people tons of time.

I love this feature and use it constantly, usually right when I start investigating something. It’s hard to imagine there was ever a time where we didn’t have this feature!

Hit counts

See the different shades of blue in the image above? Those were a bit controversial! Two years ago, we distinguished between lines of code that were run or not in a binary way. It was either on or off, dark gray or light gray. Today, we show the number of times a line was called, and we use a heat map-style darkening to call out lines that are called more often.

This obvious feature was controversial at first because we never want to clutter the UI unnecessarily. But seeing it in action made it clear that it had earned its place in the product. This isn’t some pie-in-the-sky Tufte dataviz, this has real world implications, every day, for everyone scanning through their code. It’s a great addition.

Version 843 of our print statement panel

Ok, 843 is a slight exaggeration. But even if we had iterated that many times, it’d be worth it. This feature is one of the most important things in our entire product, so it needs to work really well. Here’s how it looked in November 2021, cue the sad trumpet:

Print statement panel, November 2021

And here’s how it looks today, cue the Chariots of Fire soundtrack:

Print statement panel, January 2024

Obviously the visual treatment is better. But without getting into the weeds about bunch of technical/research details, let’s just talk about pure UX for a moment. First things first: it’s really important that people understand the top region is editable, so obviously the previous design was doing a bad job at that and it was addressed in the new design. An easy and obvious win.

Next, related things should be near each other, which is why we moved the little 2/3 indicator to be beside the forward and backward buttons. Again, it seems simple in hindsight, but it took some exploration to get there. Another very helpful step was adding a context menu, but of course you can’t just tuck everything away and call it a day. A lot of code, research, and design effort went into making this seemingly straight-forward menu. (I could probably build out an entire lecture using only this feature as an example, and maybe some day I will!)

Labels (and unicorns!)

Sometimes it can help to figure out what line of code is being called out in your console. A classic “needle in the haystack situation,” which we handled by adding a cute little label selector. I had a lot of fun drawing that pixelated unicorn.

In practice, it works like this. It allows you to set a label at the line of code (left side of this image) and see the results in the console (right side).

Focus Mode

Our app is very timeline-oriented, but you usually don’t watch a video from start to finish the way you might while binge-watching One Piece on Netflix. Often you want to focus on one part of a video while debugging, so we made something called Focus Mode. Rather than repeat myself here, I can just link to the articles we wrote about the feature last year, one when the feature was new and one we wrote when we improved it significantly:

(If you’re wondering if you should go back and read those, I’ll point out it was some of my favourite product writing ever, and I even made my coworker laugh out loud while reading it. Score!)

Our confusing layout button

We informally refer to this set of tabs as our “toolbox.” On top is how things looked two years ago, on bottom is how it looks today. Let’s start by talking about that strange icon on the top right. What the heck is that? A feature that wins the award for “most useful feature zero people discovered on their own.” Yikes.

Old on top, new on bottom. More powerful but simpler!

Clicking that icon adjusts the layout of the page. If you’re familiar with Chrome DevTools, you may have used a similar feature in this menu:

People have a reason to click a kabob (three vertical dots) or a hamburger (three horizontal lines) because they know it means “this is a menu! Good stuff will be tucked away here!” But our icon just looked confusing. It looked like a status indicator rather than an actual thing you can click, so no one did. We put it into the top menu, so now it works like this:

Shout-out to the simple pop animation we implemented there, to add a bit more life to the interaction.

More powerful + more approachable

Let’s bring up this comparison image again. There’s a lot going on here. The product got much more capable thanks to Network and React panels and rewrites of our Console and Elements panels. But this UI also got a lot simpler. We removed the trash can and tucked our menu items into our new hamburger menu. The end result is a product that’s much more powerful yet feels a lot more approachable. Livin’ the dream!

Our new filter menu

Without going into lots of detail, let’s just say this menu on the side is doing a lot of great stuff that didn’t exist in 2021.

Source maps

Great UX doesn’t call attention to itself unnecessarily, which is why I love the simplicity of this feature. It’s so straight-forward that there feels like no other way to handle it. I won’t bore you with the details, but there were a lot of ways to get this wrong, and we iterated past them and got to this seemingly simple bit of UI.

Dark theme, obviously

Of course we lovingly spent time making sure our dark theme looks and feels great too. The majority of our users use the product in this mode, including (nearly) everyone on our team, so we wanted to make sure it get it feeling just right.

Odds and ends for another article

Oh gosh, there are so many other things I wanted to get to, but they’ll be best put into another article. So let’s switch gears and talk about airplane cockpits for a moment.

A story about airplane cockpits

Sometimes designers use the term “airplane cockpit” to explain an overly complex interface. Do people really want hundreds of different buttons and indicators? It seems so complicated and confusing! Most designers have an instinct to reduce the number of buttons, simplify the overall appearance, and make something more streamlined.

It turns out they tried this once, with an actual airplane cockpit, used by actual airline pilots. The polished, simplified, streamlined, “design-led” cockpit redesign failed in practice. Why? Because “simple” and “easy” are two different concepts but it’s easy to confuse them. Powerful and complex things often require complex and powerful UI, but that doesn’t automatically mean they’re poorly designed. Super-simple interfaces look slick in a portfolio, but that doesn’t automatically mean they succeed with real users trying to get real work done.

Which brings us to Replay, a time travelling debugger. Getting our v1 out the door, as difficult as it was, was the easy part. We’re in the thick of the hardest design work now, which is taking a solid UX foundation and adding a bunch of powerful features that developers expect when debugging… while keeping the product easy to understand, fast, and a joy to use.

Our work is never done, but we’ve done a great job with this balance so far, and we’re looking forward to pushing further this year. Onward!

--

--