Building a prototype for an unfinished design

Prologue

Tell me if you’ve heard this one. You get asked to create a design, because a team needs an artifact that visually illustrates a strategic capability. You spend a few days understanding and defining the problem space. You create an initial design mockup for a UI. Generally, you like what you put together. However you let your colleagues know, that it’s only a concept which will need proper design time if it’s prioritized.

Fast forward. That mockup made quite the rounds. It helped people understand the value of the capability. It was shared with a few customers for feedback, and it excited them. You were proud of how your work helped align everyone around what the capability should be. It also made the value it would provide to the company feel tangible and ultimately, got buy-in at the executive level.

So you weren’t shocked when it got prioritized. But you definitely had a moment when you were asked, “Can you have the whole design ready in an interactive form around the middle of next month? We want to show it to a customer during a call.”

Insert stress here

Now a few weeks might sound like a long time. But when you’re a design team of one like me, who is more than fully utilized, it’s not. This capability was also deceptively complex, and the team wanted to demonstrate all aspects to the customer. Not just a few core aspects of it, but everything. Not only did I need to design what happens when you use every piece of functionality, I also had to prototype it. Then, cherry on top, I learned they wanted to include the design for a different capability as part of the prototype too. Doing this in a highly compressed amount of time, alongside my other work responsibilities, felt more than a little daunting.

Ok now what

So at first I thought I’d use Figma. It has decent prototyping features. Now, I’ve been in this game a long time and I’m fast. But there was no way in hell I could pull this off by the time it was needed. There were just too many different screens, interactions, and states to design and prototype by myself.

So late on a Wednesday afternoon while feeling agitated and watching what hair I have left mockingly drift to the floor, I opened Cursor. I had some experience using it to build a couple of Angular components. I was curious though if it might be feasible to use it to relieve this pressure I felt. Could I use it to build everything?

Approach

I created a new folder on my computer. Then created a fresh Git repo. Using version control is key when working like this (frankly it’s key for any development project). You should commit often, particularly after you’ve made a change and everything is working. Inevitably, things break and you need a way to go back in time.

In Cursor, I asked the agent to create a new Angular project and include Angular Material. Even though I was creating a prototype, our production apps use these and I wanted to grease the wheels so code could more easily be integrated later. I typed ng serve and had a project running locally on my machine.

git add .
git commit -m "Initial commit"

I then stared at the UI mockup for the first capability I had designed in Figma. How was I going to approach this? There was a lot to build. You’re supposed to eat an elephant one bite at a time (side note, pretty sure a pachyderm wouldn’t take kindly to that).

I decided my first bite would be the overall layout:

This screen has three columns. The first and last column should take up 20% of the real estate and the middle column the remaining 40%. Just put a column name in each one to start.

The agent thought for a moment, and then got to work. It summarized what it was about to do and started writing code. About 20 seconds later, it was done. I switched over to my browser and what I had described in three sentences was looking back at me.

git add .
git commit -m "Initial screen layout"

Next bite

This design has containers in each of those columns with multiple cards in each — sort of like a Kanban style app. Not every card though can be dragged into different columns, so the interaction pattern and rules are more complex.

I attached a screenshot of the portion of my design I wanted to build next. This is a key learning from the last time I built something with Cursor. It does a horrendous job trying to replicate an entire UI design in one shot. It excels at creating components. I instructed the Agent:

Each of those columns can contain a number of containers that look like cards. The cards have a heading. Inside each of those cards are a number of sub cards. The subcards also have a heading and an edit button. Here is a screenshot of what I am wanting to build.

The agent thought for a moment, described the plan, and did its thing. If you haven’t worked with a tool like this before, it’s best not to give it free reign (that’s off by default in Cursor). It asks you if it’s ok to run terminal commands and if you want to accept code it writes and changes. Due to how much the agent had to do, this iteration took a few minutes. It created two new components and wrote all the TypeScript, HTML, and CSS for them. When done, it had produced something visually pretty close to what I wanted and even recreated the cards and subscards that were in the screenshot with the correct labels.

Breathe

After about 30 minutes of iterations with the agent like this, I had the core parts of the main screen’s UI and interactions implemented and functioning. I could sequence cards, selectively drag cards between columns, and even open an empty edit panel. It didn’t look exactly like my design but was in the ballpark. I knew I could tweak the visual design myself through editing CSS or asking the agent to do it.

This felt empowering. I hopped on a call with the Product Manager for the project to share my progress. She got super excited and was relieved — much like I was. We had talked that morning and I had expressed my concern about being able to deliver what the team was looking for in time. This was possible now.

Design sprints?

I don’t think design sprint is the right term here, but it’s how I usually refer to what I did next. I set a goal to complete the prototype for the first capability within a work week. While I still had other job responsibilities, thankfully I was able to devote the majority of my time to this project.

After completing a few more iterations with the agent, I hit a wall. Remember, I hadn’t designed what should happen when you edit a card. And there are six types of cards that serve different purposes, and those cards all referenced each other directly or indirectly from a data perspective.

Normally, I’d hop into Figma or sketch out ideas for each screen on paper. I had some guidance from the Product Manager about the types of things users should be able to edit in a subset of cards. There were a lot of unknowns.

Instead of using a design tool, I decided to use words. I described for each card type, the types of controls that should be present when you edit it. When I got to a place where I wasn’t sure where to go next, I’d either explore design ideas through further iteration with the agent myself, or ask the Product Manager for thoughts.

This created a feeling of designing in real time with code. I didn’t keep up with the number of iterations, but it’s definitely in the high hundreds for the first capability I prototyped. I completed that in under 30 hours. I honestly think it would have taken me at least a few weeks to do this in Figma. And a lot of the information there would be hard-coded and I wouldn’t be able to show all the different variations and states of data.

I’m in the second design sprint now, building the other capability.

Working with an agent

The caveat with all this, is agents don’t always get everything right in one shot or even through multiple attempts. There were many times where I had to ask it to try a different approach, or just abandon an iteration entirely and git reset --hard HEAD.

I noticed the agent is usually pretty good at knowing how to fix compiler and console errors. I’d paste those in and more often than not, it would fix them right up. When it wasn’t sure, it would add some extra debugging and ask me to tell it what I saw. That often led to a solution.

The agent is also usually good at making very precise style adjustments:

I want you to add 32px of bottom margin to the expandable-panel component, but if it’s the last child in a container it shouldn’t have any bottom margin.

That feels a bit lazy since it’s a simple CSS change, but whatever. It’s faster when it works.

Sometimes, the agent would come up with elaborate and over-engineered ways to do things. There was one instance where it did something I had never seen with CSS Grid. I gave it a confused look and said:

That didn’t work.

It then made a few different attempts to accomplish what I was trying to do. I stopped it before I wasted any more tokens and reverted to a previous commit. I then edited the CSS myself by adding a simple padding declaration and fixed the issue.

Wrap

This is a new way to design and it’s invigorating. Honestly, this is the most excited I’ve been about design in a very long time. There is a sense of fun that’s created when working like this, and that fun is contagious. I can tell my team is excited about what this new approach is going to do for us.

The way we design and build products is changing and I don’t want to go back to the old way.