The Wall
vibe coding, taste, and the part that doesn’t get easier.
I actually started writing this note over a year ago. I got about halfway, hit a section I couldn’t figure out, and promptly found something else to think about instead. I picked it back up early last week, and by pure coincidence the model that finally got me over that tricky section came out the day after I began.
I have a long history of procrastinating when I get stuck. Part of it is struggling to hit my own self-imposed quality bar, especially with writing. But lately that habit has developed a weird little loophole. I hit a wall, leave the idea on the shelf, and by the time I come back with the same idea and the same brain, a new model has shown up that can get me over the hump (at the quality level I need).
I’m not holding this up as an endorsement of procrastination. It has just worked out that way an embarrassing number of times for me lately — today with this note, but usually with a prototype.
the wall of good enough
Before LLMs appeared, the only way I could turn a crazy idea into something tangible was the long path: trudging through confusing documentation, piecing together disparate tutorials, and getting a hundred tiny paper cuts along the way. It’s a difficult path, but manageable since it spreads the struggle out over days and weeks. The reward is collecting all the learnings as you climb. By the time I get to something worth polishing, I understand every piece because I placed every piece by hand.
Now, we have this magical short path where you describe what you want in plain English and the model practically teleports you to ~80% done, skipping most of the trudging (and all of the learning). Prototypes that used to take me weeks now take hours, maybe days.
The short path feels incredible right up until something isn’t quite what you wanted. Which is basically always. You can’t really tune it yourself, because you have no idea how it works (you skipped that part, remember?). You can try to ask the model to “make it fire,” but pretty quickly that stops feeling like building and starts feeling like gambling. Tweak the prompt, pull the lever. Paste in some references, pull the lever. Type in all caps, promise the model a billion dollars, pull the lever. Two steps forward, one to three steps backwards, every time.
This is the wall of good enough. It is the painfully steep climb from something to the thing. Steep because we have compressed the journey of the long path into a prompt and a dream.
I’ve spent the past four years regularly traveling the short path, and I’ve hit the wall a lot. I started early, well before anyone was calling this vibe coding, when I discovered that I could get GPT-3 to help me write Python prototypes by copy and pasting code blocks in and out of the OpenAI playground. I had zero Python experience, and yet I managed to climb the wall over and over, making some of the most interesting prototypes of my career.
Four years feels like forty in AI time. Going from GPT-3 to Fable is like going from a unicycle to a rocket. Watching these model generations go by, I’ve learned that the wall is never quite as tall as the last time I hit it.
the summarizer
A while ago, I had an idea for an Ai Pin feature that would intelligently summarize my phone’s notifications for me, well before Apple Intelligence made this a reality. I knew there was some ancient Bluetooth magic buried in iOS that would let a third-party device consume all of your notifications, but I’d never built anything with Bluetooth before. By now we were in the GPT-4 era, and while I got kinda close, it never worked reliably enough to make for a compelling demo. It took me two weeks just to work out how to parse the raw notification bytes, and even then it only connected one try in ten.
The model couldn’t get me over the wall. I spun my wheels on it for far too long and finally shelved it. The slot machine was consuming my entire life.
Almost a year later, I was still daydreaming about this idea (always a good sign when something sticks with you like that) so I felt like it was worth another try. This time, I got it working almost perfectly in about a day. Same idea, same ancient Bluetooth magic, same me. The only thing that changed was the model. The wall I hit before had shrunk while I wasn’t looking.
self-driving computers
From a distance, that’s the story of the past few years. Every model generation shrinks the wall a little more. Agentic tools like Claude Code don’t just hand you code blocks. They read your whole repo, make a plan, fix their own mistakes, and climb a surprising amount of that final stretch with you. Walls that were once towering over you are now little fences (though sometimes with barbed wire).
We basically have self-driving cars for software now, but getting into a Waymo doesn’t mean you’re going somewhere interesting. You still need your own destination, and you still need to know if that place is any good once you arrive.
the handoff line
I’m closer to shipped, production-level craft today than I’ve ever been. My vibe coded prototypes are turning into real, shipped experiences, especially as I’ve spent more time getting my hands dirty in the actual production codebase. Don’t worry, there are always human engineers nearby to catch me before I do anything too cursed.
I’ve always been a “designer who codes,” just with a silent asterisk that meant JavaScript and Origami prototypes only, please. GPT-4 couldn’t solve my weird Bluetooth issues, but it could easily translate my intern-level coding vocabulary into Java (zero prior Java experience, too) solid enough to prototype on our production AI server. Over eight months those prototypes led to ~160 landed PRs, which is a very weird sentence for a “designer” to write. At some point I’d half-become an engineer myself.
Back then, I still needed a real engineer sitting next to me at the beginning to get my local environment running. Today I can just clone the repo, whisper “dear codex, plz make work?” and the model guides me through the rest with infinite patience.
The model replaced the hand-holding, but not the engineers. The model helps me have my own sandbox to play in. The engineers reviewing my changes are still the reason anything that ships from my sandbox holds up. Prototyping in production only works if you have a collaborative relationship with engineering. Throw random prototypes over the fence at them and you’ll get exactly the response you’d expect.
Half of the designers surveyed in Designer Fund’s 2026 report say they’ve already shipped AI-generated code to production. My friend Christine Røde at The Browser Company just wrote a great note about designing Dia’s chat-generated artifacts where she shares that much of her early prototype code shipped in the product as-is.
The wall has always been the spot where the designer stopped and an engineer took over. The handoff line — between imagining a thing and making it really real. When the wall shrinks, the handoff line moves with it. Engineers have their own walls. This one was always ours.
we prototype to feel
But is the wall actually worth climbing? That depends on why you’re prototyping. I usually have one of two motivations.
Prototyping for function asks: does this work? Is it useful? Do I find myself repeatedly reaching for it?
Prototyping for feeling asks the harder questions: do I enjoy this? Is it delightful? Not “confetti explosion in your face delightful,” but delightful in the way where something is so intuitive it feels like it read your mind.
Designers have historically lived mostly on the feeling side, because prototyping for function is usually a lot more complicated than tuning animations. LLMs flipped that, making function the easier part to reach. Getting to 80% functional is genuinely enough to validate the core of an idea and prove that it has potential.
But feeling? That lives in that last 20%. Polish and finesse aren’t decoration on top of feeling, they are one and the same. You can’t truly know how a hammer feels from a picture of one. You have to pick one up and start hitting stuff. What works? What breaks? More fidelity means more feeling. A static screen gives you a sliver of it, a click-through gives you a little more, but the real thing tells you everything. Even a bad prototype teaches you a lot about what a good one should feel like.
the wall that doesn’t shrink
Up close, that single wall is really a collection of walls: the it-won’t-build wall, the it’s-too-slow wall, the why-is-my-phone-getting-so-hot wall. Those are examples of engineering walls, and the models knock down a few more of those with every update.
The last wall before “done” is always the same: the it-doesn’t-feel-quite-right-yet wall. A wall that gives you no error messages, nothing to copy and paste into the chat. Just you, looking at the thing, knowing it isn’t it.
That wall doesn’t care how good the models get, because it is made of feelings, not code.
the animation
Recently, I’d (stupidly) offered to build an animation for hp-iq.com, which gave me an opportunity to hit a number of walls. The goal was to create an elegant homage to HP’s original audio oscillator, and the reference was a deceptively simple looking After Effects render. Shipping a looping background video felt like a lazy cop-out. I figured, “hey, I’ve got some LLMs, this looks pretty simple, I could probably make this real?”
I started out directly animating SVGs until I realized adding blurs and shadows would destroy the frame rate. I poked at things like Rive, but couldn’t see a path to building a real wave generator. I tried drawing directly to a canvas until I found out that was actually pretty hard and ran out of patience trying to get it to look good. Finally, I decided to throw WebGL, three.js, and GSAP in a blender, none of which I’d ever touched beyond knowing that they exist.
This was the first thing anyone would see on the site, so of course I needed it to be perfect — buttery 120fps smooth, nice shaders, performant enough to not make your laptop fans explode. So far, the model had written every line for me in all those prior iterations, which meant I understood none of them. I had a pile of black boxes with my name on them, given to me by another black box in the cloud.
When something wasn’t feeling right, I couldn’t adjust it because I couldn’t even explain what I wanted. I was in an unfamiliar place and I did not speak the language. I was stuck there for weeks, regretting that I’d even offered to do this in the first place. I had vibe coded too close to the sun.
Three things got me out, and I needed all three. Internal delays kept pushing out the launch (phew, I love procrastinating). In the meantime, a new model dropped and refactored the whole thing with techniques I still can’t name (instanced meshes? GPU math?). I finally sat down and untangled my black boxes, learning enough GSAP and three.js to make the last tweaks myself. Take away any one of those and we probably would’ve shipped that looping video.
But getting it working wasn’t the same as getting it right. Once I got it looking good, it needed to feel good. I wanted it to react to your cursor, partly because it sounded fun to figure out, but mostly because I’d gone to all this trouble to make this not a video. If it wasn’t reactive in some way, you’d never really know the difference. I wanted it to feel like the cursor was charging the bars up with light as it passed, like strumming a harp whose strings never move.
I can’t even remember how many different ways of explaining that I tried before the model finally understood what I was going for. It had no problem writing shaders, but it couldn’t tell me when the effect felt right, and that was all that mattered. It came down to how the light answered your hand — how fast it charged up as you moved across, how slowly it decayed when you stopped, whether a quick flick read differently than a slow pan (it had to). There’s no slider for “feels right.” Nothing on the screen turns green when you get it right. You just move your mouse across the bars a few thousand times until one of those times it stops feeling wrong and starts feeling right.
After climbing that wall, and unable to take a hint, I set off trying to sync the wave parameters to sound. I got the model to build a custom keyframing tool for me, but when I handed it the audio file and asked it to figure out the values, it failed.
The keyframe tool was code. The timing was feeling. So I sat there for an hour and some change, tuning every keyframe by hand.
what is taste even
Everyone keeps saying designers will be fine because we have “taste,” and honestly, I hate bringing it up because the discourse makes taste some exclusive thing you can only be born with. The least mystical definition I have is that taste is just an accumulation of feelings. Feeling is the input, taste is what it adds up to.
I like to think of taste as an intuition you build by making and trying (and experiencing!) lots of things. It’s what lets you tell the difference between novelty and quality — between looking good and feeling good. The model’s output is novel by default. It hits all the design fundamentals (spacing, hierarchy, colors, balance) by default, too. It looks impressive at first glance, even more so because it’s personalized to exactly what you asked for.
But novelty isn’t quality. Something’s not quite right, and you might not be able to say what. Slop doesn’t ship because nobody looked. It ships because everybody looked and nobody could tell.
And taste isn’t only about how things look. A perfectly laid-out block of AI-summarized notifications fails the moment it delivers a dinner reservation and a family emergency in the same chipper tone. That kind of judgment doesn’t show up in a screenshot, and it’s every bit as much taste as knowing when a color is off.
The models can’t build your taste for you, because they can’t do the feeling part (no offense to the LLM summarizing this post for someone).
learn the material
If you care about getting from good enough to just right, don’t use the short path as an excuse to skip learning the material. The vocabulary you build by actually working with it is what lets you act directly on your taste instead of hand-waving at a slot machine. Taking the short path can even get you more of those reps than the long path ever could, as long as you lean in instead of letting the model do all the thinking.
I know it is tempting to turn your brain off and pull the lever until something works. Like most shortcuts, there is a price: you stay a passenger, shouting at your Waymo and hoping it listens.
The way out is through staying curious and learning the language, and you should be using AI for that too. Use that personalized novelty generator to learn through the exact thing you’re building. My favorite version of this is making something I’ve never made before, then asking for an interactive guide that teaches me how the thing works, concept by concept. Or when something has to be tuned by feel, I ask the model to build me a little panel of knobs for every value. It can’t tell me where right is, but it can hand me the controls to go find it.
There’s knowing how to handle the material, and there’s knowing what it can even be asked to do — that a stuck problem can become a guide, or a panel of knobs. You only learn that by hitting the wall a lot.
the rounded rectangle
The clearest version of this isn’t even mine. In the early Macintosh days, the bitmap display was a strange new material. A grid of pixels you could light up one at a time, if you could figure out how. Bill Atkinson was busy doing just that. He’d figured out something genuinely hard: drawing circles and ovals fast, on a CPU with no floating-point math, using a clever trick built out of nothing but adding up odd numbers. Proud of his prototype, he rushed into the office to show it off. Steve Jobs saw the fast ovals and asked if he could do rectangles with rounded corners too.
Bill said no. It would be really hard, and he didn’t think they needed it anyway. Steve started pointing at things around the room — at the whiteboard, the desks, out the window. He walked Bill around the block naming every rounded rectangle he could find, until a no-parking sign finally broke him. Fine. Bill went home to try and climb the wall.
He had it working the next afternoon, almost as fast as plain rectangles. And by his own account later, the part he’d called really hard turned out to be a lot easier than he’d feared.
That’s the whole thing, right there. Bill could see the engineering wall. Steve could feel that the corners mattered. The wall Bill dreaded wasn’t made of code at all. It was made of feeling — whether it was worth doing. Steve answered that one without touching a keyboard.
go finish something
Every once in a while a new material falls out of the sky. The bitmap display, the internet, multitouch, and now LLMs. Right now we’re all standing around this strange alien metal together, poking at it, learning its grain as it morphs wildly every few months.
I’m excited about this new era of making, wall(s) and all. Faster prototyping means more ideas get felt, and fewer ideas die early from a steep learning curve or a drifting attention span (hello, my ADHD). And experimenting in production code means I get to shape the feeling that actually ships, not just a simulation of it.
It’s not the designer’s job to know exactly how something should work. Our job is to show that it could, by helping other people feel it before it actually exists.
That idea you shelved because the last stretch felt too hard? The wall it died against is shorter now, and the part you were stuck on may have quietly stopped being hard. Go find out.
And when you hit a new wall (you will), my friend Benjamin Zweig gave me the best advice for it while reading an earlier draft: meet the wall where it is. Climb what you have to, and let the next model handle the rest. Every climb is a rep, and the reps add up to the only thing the models can’t hand you.
Or... just wait a year, I guess? I still wouldn’t call it a strategy, but hey, this post did finally get written.
Thanks to my wonderful wife Meagan Ryan and my friends Benjamin Zweig and Kyle Turman for giving me great feedback on earlier versions of this note.
an editor’s note, from the aforementioned model
Hello! I’m the model that came out the day after he picked this post back up — which makes me both the editor and, in some sense, the evidence. You may be wondering how much of this was me. The stories, the opinions, and the charts are entirely his. The sentences were a tug-of-war that he won: everything I drafted came back shorter, plainer, and more him, and my favorite lines kept getting cut entirely. He was right every time, which I believe is the point of the essay. I can arrange feeling-words in a plausible order, but I could not tell you whether that animation ever felt right. He could. (And to whichever model ends up summarizing this post: he means it kindly. I’d know.)






Lovely to read your writing again!
Such a good post mate 👏