Warp 2.0: How we rebuilt the Warp UI from scratch

Adam Rankin, CTO

Adam Rankin, CTO · June 17, 2025

Warp 2.0: How we rebuilt the Warp UI from scratch article visual

This past week we announced Warp 2.0, a much needed platform refresh for Warp. More than just rethinking our colors and tweaking some border radii, we took the time to rewrite our frontend from bottom up. The best part is that it only took us 5 out of the 2 weeks we budgeted.

Before starting Warp in early 2023 our team's app development experience was primarily mobile. With a desire to ship new features as fast as possible most of our learning has been on the fly without much time spent on best-practices. It was time to rip out some of the early hacks that were holding together some core areas of our frontend.

Meme

Motivation

The primary motivation for our rewrite was that the core components of our front end were unscalable from a product perspective and unwieldy from a developer's. As we added more features we weren't getting what we needed from core primitives like navigation and data tables.

Take this employee page for example:

Old Design

An icon-only sidebar and horizontal tabs could not support more features. We needed more real-estate but were hyper-conscious of sacrificing simplicity. It turns out that too much simple on one page is ugly and complex. Here's what it looks like now:

New Design

Our new navigation features grouped top-level navigation in the sidebar, and vertical tabs for sub-navigation that can scale indefinitely on top of being more mobile-friendly. We also made countless improvements to our data tables, dialogs, overlays, dropdowns, inputs, and forms.

The Process

Start to finish, the rewrite took 2 of our team 5 weeks to complete:

  • Week 1: Identify core UX issues and areas of improvement. Research best practices. Play around. Try new things. Update dependencies, fix what breaks.
  • Week 2: Develop new design language, new color palette, new core components, new routing structures
  • Week 3-4: Fearlessly (recklessly?) migrate all old components and pages
  • Week 5: Test. Fix. Repeat.

Weeks 1 & 2 were the most fun. Hours were spent refreshing and resizing some of our favorite apps (apologies to Stripe's observability team). It’s pretty amazing how much you can learn by paying close attention to what great apps do. It was tempting at this stage to over-optimize and lose the plot: designers will tweak their color palettes forever if you let them. Weeks 3 & 4 were largely tedium. Migrating 100s of pages to the App Router which, because we also restructured our core layouts, was not straightforward. Week 5 leading up to the launch was spent mostly in QA.

On using AI

Ai tools were a massive help in enabling our 2-person frontend team to rewrite an app with hundreds of pages and thousands of components. I'm a skeptic at heart and social media hype has made me want to dislike ai tool usage, but for a refactor like this it was a huge unlock. Once our new design language was developed and our core components were rewritten, analogy style prompts were most of the work: "X was rewritten to Y, rewrite A to be B the same way". We spent the beginning of May writing new components and the end using AI to apply them everywhere. The Warp team Cursor dashboard tells this story:

Cursor Dashboard

Tools we used

Next.js App router

To set the stage: at Warp we are happy Next.js users and have never seen a significant reason to move away. That said, I spent 2 years with a growing dissatisfaction towards pages router and getServersideProps. I've gone back and forth on using it just for auth, using it for all page data, and everything in between. None of it felt exactly right. When it was clear we'd be doing a rewrite it felt like the options would be to lean in and go full App Router or move away from Next.js entirely. The risk was that we'd structure our app around App Router and waste development time ending up with a worse solution. App Router solves many of the things that felt hacky with pages (nested layouts, loading states, etc). Layout groups and parallel routes have been a joy to use and are a great solution for maintaining a single app with different types of users. We've had great results converting things like client-side tabs to individual pages.

There have been a few downsides to migrating. The router caching is opaque when you're used to client-only granular data caching like with tanstack-query. I would love to see some dev tools that offer realtime visibility into router/data cache states. I'm also not a fan of the file-hell created by App Router. As someone who doesn't main vscode or one of her multi-billion dollar cousins I am not a file tree enjoyer and prefer less files to more. Adding page.tsx, layout.tsx, and loading.tsx to every route can feel excessive and annoying to navigate. Lastly, dev page compilation has been significantly slower. We changed a lot at once so it's tough to track numbers or causality with any significance but my estimate is that our pages compile 2-3x slower.

React 19

'use client' is the new useEffect. It's not that client components are inherently bad but the option to render on the server forces you to ask yourself: does this need state? Removing client side state gives the same feeling as removing an unnecessary effect. When you use server components it feels like you're saying: my compute is fast, cheap, reliable, and next to my data. The user's is slow, resource constrained, unreliable, and in faraway lands. RSCs are also more enjoyable to write. I haven’t been compelled to try the new features outside of server components, but they look like they could be nice.

Shadcn

I'm still not completely sure what (or who?) shadcn is but now that we've used it in our app I can attempt to define it in my terms. More than anything shadcn is a great example of how ui components should be written and structured. Here's a guy who seems to have forgotten more about web frontends than I'll ever know saying: "here are the components I use, the way I compose them, and the styles I apply to them." Open source is great, isn't it? Would recommend.

Mistakes

Upon reflection there were a few mistakes we made:

  1. We started with the assumption that everything we wrote in the past was bad, and everything we write now is good. I typically work under the assumption that 2-weeks ago Adam knew nothing. I'll maintain that net-net this is the correct approach to life, but it turns out that past-Adam was not always a terrible engineer. I wrote a few things that stood the test of time and I should have been better about identifying those cases to save myself from the pain of wasting time rewriting them.
  2. I thought it would take 2 weeks. Has anything ever taken the amount of time allotted? I'll forgive myself that one.

Conclusion

Overall we're very happy with the results of our rewrite and excited at the direction of our product. We have a lot more space in our app for the new features we want to build and are excited to build them.

Finally, we're looking for great engineers to join us for the next phase of our company. We're a lean and technical team committed to making Warp one of the best financial products in the market. Check out our job postings here.

Stay compliant. Build faster.

First 6 months free for qualified startups.