9 Lessons from a newfound Vibe Coder
A listicle for our modern times.
Time to come clean.
I’ve been vibe coding.1 I’ve been vibe coding…a lot.
It’s actually a problem. I have a bunch of house projects to do before the weather turns here in Oregon. Only have a couple of weeks of sun and yet here I am, spending too much of my time obsessively thinking about my side project. Sometimes you have to go where the energy takes you.
I figure I’m not the first to come to vibe coding but I also know that I won’t be the last. So I want to just drop a few simple(?) nuggets of wisdom I’ve learned in the process.
Note that I have intentionally not looked at anyone else’s vibe coding tips and tricks. I’ve gotten a few recommendations from a friend and probably gleaned a bit here and there from Twitter but I’ve mostly avoided looking for advice because I wanted to learn the process organically, from the ground up, tabula rasa. Which means I might have the exact same advice as everyone else and that advice is super elementary, or I may have come to radically different conclusions from others. Perhaps it’s just right! I’ll let you be the judge.
Lesson 1: From the 10k foot view, vibe coding really is a kind of magic.
My side project is a bit silly. I’m building a word game, the details of which I won’t go into but suffice to say it’s vaguely Wordle-like (in that you’re guessing a word) but more complex and difficult.
I’ve been thinking about building this game for years. It’s a pen and paper game that I’ve been playing with my father-in-law for at least a decade and for most of that time I’ve said to myself “it would be cool to turn this into an app!”.
But I also knew how much of a pain in the ass that would be. I’m a Product Manager by trade. I have a CS degree2 but I’ve never really coded professionally and I’m pretty rusty. I was pretty solid back in college but these days? I figured it would take me at least a month to learn javascript well enough to build the basic prototype-level app that I could play with my FIL.
With Claude doing the heavy lifting, I was able to build that prototype in two days. Not two 8-hour days –3 more like two 2-hour days.
I’m obviously not the first to say “hey, capable Product Managers can prototype with AI now”. At some workplaces, that’s become the standard. But it’s still worth remarking upon because it is remarkable!
Lesson 2: it’s … fun?
I won’t evangelize too much here. I’ll just say that I find, after I’ve spent some time working a feature and I finally nail it, that it feels good. It feels like the old days, back when I was a CS student and I cracked a hard problem. It feels like when someone on my team demos their work and it looks great, working just the way we want it to.
Outcomes over outputs: you don’t have to be the one coding to find the joy in the code. If you’re doing it right you’ll find yourself energized by the experience.
Lesson 3: It’s not just for Prototypes but you have to know enough to be dangerous.
Last week, I decided to:
Restructure my app into logical concerns
Start using a build process (Vite)
Convert all of the code from Javascript to TypeScript
Add in a test Framework (Jest)
Build coherent tests for all the features I had thus far.
Build a significant new feature, using a Test Driven Development approach4
For the engineers among you, you’ll probably recognize that list as something a little different than “prototype”.
To be sure, there’s work left to do. I need to clean up the CSS (I’m thinking Tailwind?) I need to integrate analytics (I’ve settled on Posthog, at least for now). Proper authentication will introduce a lot more complexity. But what was previously a prototype is now something a bit more “real”.5
Thinking back to the prototype, I doubt my father-in-law could do it, even with AI. “Computers” aren’t his strong suit. But my wife? She almost certainly could, despite having neither formal nor informal coding experience.
Yet, I don’t think she’d ever get past the prototype phase. Enough iterations and she’d have something that looked cool but was complete spaghetti underneath.6
Our paths diverge because I know enough to be dangerous. Enough time in the industry and you learn a lot through osmosis. I’d never heard of Vite before but I knew enough to ask the right questions and determine Vite passed the smell test.
The space is dynamic. Perhaps in six months, a year, two, a true neophyte could build production-ready code. Today, though, real domain expertise is still required. The domain is less about where to put the curly braces now but it‘s still about architectures and frameworks and trade-offs and best practices
Put another way: effective vibe coding is still the domain of developers, of PMs, of Engineering Managers, of people with sufficient exposure to coding practices to have a sense of how software development actually works.
Lesson 4: Embrace the inelegance
Still though, I’m not going to pretend what I have is bug-free, or perfectly maintainable, or anything like that. But to my eyes, it’s Good Enough. A real developer could come in, look through the codebase, understand what’s going on and make incremental changes, with or without AI assistance.
Note that this isn’t good. It’s Good Enough.
Does it solve the user problem? Have we tested all the branching logic? No linting errors? Does it meet our performance, accessibility, and security requirements. It may just be Good Enough.
Think about every enterprise codebase you’ve ever worked in? They pretty much all have some warts. Something was rushed, some area is in need of a refactor. That’s the nature of the game.
Let’s be honest with ourselves, we’re still making trade-offs here, of speed over elegance.
Lesson 5: Seriously though, it’s dumb a lot
LLMs have a bunch of failure modes. Many of them aren’t dramatically different than an overeager intern with too much time on its hands. The AI tends to lose the forest for the trees. It’s often overconfident. It occasionally rabbit holes into weird places. It’s often sycophantic. (That last one is new to me but the first three sound like 80% of the engineers I’ve ever worked with.)
Navigating these failure modes is the tricky part. It’s not always even clear you’re experiencing a failure mode. My heuristic is, “if it feels harder than it should be, it probably is”. So far this all seems more art than science to me. But perhaps I’m just too new to it to know better?
Lesson 6: Zoom in, and then out, and then zoom in again
One of the best ways I’ve found to handle both the forest-for-trees problem, and the overconfidence? Force the LLM to change its perspective. Or give its work to another model, and see what that model says.
I find myself frequently asking the LLM something like:
Ok, now step back. Consider <this aspect>. Have we built this feature in the best way possible? What trade-offs have we made, and what are the pros and cons of that approach?
Or I find myself asking a different LLM from the one I’m coding with:
Hey, I have <this code>. Read through and tell me what it does. Then, suppose I want to add features X, Y, and Z in the future. What architectural changes will I need to make, and when?
Repeatedly digging down to the line or the test level and then back, to the feature level and then back again, to the architecture level is incredibly helpful — for both me and for the LLM. It will frequently find fault with its previous work or reveal a trade-off I wasn’t aware of from its choice. (Here again, having a sense of modern coding practices is extremely helpful.)
The domain is less about where to put the curly braces now but it‘s still about architectures and frameworks and trade-offs and best practices
Lesson 7: Context is king
The LLM has a tendency to be anchored to certain ideas, and it can be hard to break it out of once it’s settled there. As well, the longer you spend on a particular task with the LLM, the quality of output degrades, sometimes dramatically. Context rot, they call it, and I can assure you it’s real.
I don’t have great solutions besides “start a new conversation” and “choose your words/context wisely, especially when you open conversation” but the difference between “one-shotting” a problem and slogging through it for several hours can often come down to word choice and to knowing when to step back and start afresh.
What I will say is that a structured input, where you explain the purpose of your code snippet, the broader context, and the relevant roadmap right at the start of the conversation helps avoid architectural pitfalls.
Lesson 8: Ask questions first; shoot later
Whenever I’m planning a feature I never regret telling the LLM something to the effect of:
Explain how you intend to tackle this feature. Ask follow-up questions before you start making any code changes.
We iron out edge cases and avoid entire circuitous paths this way.
Lesson 9: Smaller problems are smaller
The last lesson is the easiest, but also, maybe the hardest? It won’t be new to anyone with software experience: when it doubt, break it down.
Sometimes you can say “hey, LLM, do these 5 things” and it will Just Work.
But often it doesn’t.
It’s why I think there’s a lot of value in TDD when vibe coding but the lesson is broader. When in doubt, break a big problem into smaller ones and take them one by one. You’ll get there faster in the end.
Conclusion
Thanks to Netlify, my little app deploys automatically whenever I commit/merge to main. It’s very convenient and really does feel like magic. And it means I have a real thing that my friends and family are beta testing, giving me super useful feedback.
It also means I have something that I can take to market. Not a prototype — a real app, today.
But it’s also little more than a bundle of HTML, CSS, and Javascript. I’m not ready to declare software engineering over. If anything, the concepts I learned in the industry are the reason it’s still going so well. Software engineering is alive and well, just different.
It’s early days for me vibe coding, for vibe coding as a thing. But I do think it’s worth scratching the itch, if only to see how you like it. You might learn something.
— Mort, Product @ Liminal Labs
Editor’s Note:
The engineers at Liminal have been using LLMs as part of their coding process for years now and have built cutting edge, AI-native tooling both for clients and for ourselves. However, our Product guy had not used it much for software development work until last month.
While these are his thoughts, they do tend to broadly track the experience our engineers have had as they’ve worked in an AI-assisted world, and really in software more generally.
Shout out Eric Chown a.k.a. Chown-dog and Laura Toma!
This post is genuine, from the dome, human-writing. The LLMs can take the em-dash — a beautiful piece of punctuation — from my cold, dead hands.
AI-assisted, I knocked this out in two days. Two! I estimate that same scope of work would have taken a front-end engineer at my old job three to four weeks to complete. The tests alone would have taken at least a week and a half. Hell, writing the Jira tickets up would have taken me the better part of an hour, maybe more. For all its warts: remarkable!
Is it vibe coding any longer if you’re writing closer-to-production code? That is a semantic debate I don’t wish to dive into.
No shade to her, of course. She works in medicine. She saves a hell of a lot more lives than I do.



