There's a term floating around developer circles: vibe coding. It means using AI to generate code based on loose descriptions, accepting the output, and moving on. 'Build me a dashboard.' 'Add a login page.' 'Make it look modern.' The AI generates something. It compiles. It kind of works. Ship it.
I use AI every day. Claude Code is my primary development tool. And what I do is not vibe coding. The distinction matters — not as gatekeeping, but because the output quality is fundamentally different, and the difference comes from what happens before the first line of code is written.
What Vibe Coding Looks Like
Open a chat. Type: 'Build me an e-commerce site with a product catalog, shopping cart, and checkout.' Get back 500 lines of code. It renders. Products show up. Cart works. Checkout has fields. Deploy it. Done?
Done if you don't care about: what happens when two people buy the last item simultaneously. How the stock count updates on cancellation. Whether the checkout form validates Malaysian phone number formats. What the admin sees when they need to issue a partial refund. How the payment webhook handles duplicate notifications. What Content Security Policy headers you need. Whether the login endpoint is rate-limited. How customer data is stored, who can access it, and whether you're compliant with local data protection law.
Vibe coding produces demos. Building produces systems.
What Building Looks Like
Before I write code — before I prompt any AI — I do the work that determines whether the code will be worth writing.
I start as a product manager. What problem are we solving? Who is the user? What does success look like? What are the constraints — budget, timeline, technical limitations? What's in scope and, critically, what's out of scope? I write this down. A proper requirements document with user stories, acceptance criteria, and explicit boundaries. Not because I enjoy documentation — because I've shipped enough projects to know that the most expensive changes happen when you're building the wrong thing.
Then I shift to architect. Given these requirements, what's the system design? What are the data models? What are the API boundaries? Where does state live? What are the failure modes? What happens at 10x the expected load? I draw this on paper. I think about it in the shower. I argue with myself about whether PostgreSQL or SQLite is the right choice for this specific project with this specific deployment target.
Then UX. How does the user move through this system? What do they see first? Where do they get stuck? What's the minimal path from landing on the page to completing their goal? How does it work on a phone in bright sunlight with one thumb? I think through every screen, every interaction, every error state.
Only then do I build. And when I build, I have a spec. I have data models. I have user flows. I have acceptance criteria. The AI gets context, not vibes.
The Pipeline
My development pipeline has distinct phases, each with different thinking and different outputs:
- Discovery — understand the problem, the user, the constraints. Output: requirements document with scope boundaries.
- Architecture — design the system, data models, API contracts, security model. Output: architecture decision records.
- Design — user flows, component hierarchy, responsive breakpoints, accessibility requirements. Output: design specification.
- Implementation — write the code, build the features, integrate the services. This is where AI accelerates dramatically.
- Review — test edge cases, verify security, validate against requirements, check performance. Output: a list of things to fix.
- Ship — deploy, monitor, document, hand off. Output: a working system with documentation.
AI is most powerful in phase 4. It's useful in phases 2 and 3 as a thinking partner. It's nearly useless in phase 1 because discovery requires understanding a specific business, a specific user, a specific context — not generating generic requirements. The entire pipeline matters. Skipping to phase 4 is vibe coding.
Being Every Role
As a solo developer, I don't have a product manager, an architect, a designer, and a QA engineer. I am all of them. But I don't try to be all of them simultaneously. I context-switch deliberately.
When I'm wearing the PM hat, I'm thinking about user value and scope. When I'm wearing the architect hat, I'm thinking about data flow and system boundaries. When I'm reviewing, I'm actively trying to break what I just built. These are different modes of thinking, and conflating them produces mediocre output across all dimensions.
I use Claude Code as a counterpart in each role. As a PM, I present my requirements and ask Claude to challenge the scope — are there features I'm including that don't serve the core goal? As an architect, I present my design and ask Claude to find weaknesses — what happens when this service is unavailable? As QA, I ask Claude to enumerate edge cases I might have missed. It's not always right. Sometimes I disagree and explain why. Sometimes it convinces me. The back-and-forth is the value, not the initial output.
Fighting Your Own Decisions
The hardest part of being a solo developer isn't writing code. It's challenging your own decisions when there's nobody else in the room to push back.
I've learned to argue with myself explicitly. I write a scope document. Then I read it as if I'm the client and ask: 'Is this what I actually need, or is this what the developer wants to build?' I design an architecture. Then I read it as if I'm a junior developer who has to maintain it: 'Would I understand this in six months?' I price a project. Then I check it against the value delivered: 'Would I pay this?'
Using Claude as a sounding board makes this more rigorous. I can present my architecture and ask for a critique. I can present my pricing rationale and ask where the weaknesses are. I can present my scope and ask what I'm missing. The AI doesn't have personal stakes. It doesn't care about my ego. It just responds to what I give it. That dispassionate perspective is genuinely useful — not as a replacement for judgment, but as a mirror that reflects your thinking back at you without the emotional bias.
Where AI Fits in This Process
Claude Code with a PRD, architecture document, and design specification produces production-quality code. Claude Code with 'build me an app' produces a demo. The input determines the output. This is the most important thing I've learned about AI-assisted development.
When I hand Claude a task, it has context. It knows the data models because I defined them. It knows the API contracts because I designed them. It knows the security requirements because I specified them. It knows the coding patterns because the existing codebase demonstrates them. AI doesn't replace the thinking. It executes the thinking at speed.
When I review Claude's output, I'm not debugging AI code. I'm reviewing a colleague's pull request. Does it match the spec? Does it handle the edge cases? Does it follow the patterns established in the codebase? Does it introduce security vulnerabilities? Sometimes it does, and I catch it because I understand the system at a level that comes from having designed it. That understanding is the thing that can't be automated.
The Output Is Different
Vibe-coded projects have a tell. They work on the happy path. They break on edge cases. They have inconsistent patterns across files. They lack security headers. They don't handle error states gracefully. They feel like they were assembled, not designed.
Built projects feel coherent. The data model is consistent. The error handling follows a pattern. The security is layered. The UI handles loading, empty, error, and success states. The code reads like it was written by someone who understood the whole system, because it was — by a developer who designed the whole system and used AI to help implement it.
The tool is the same. The process is different. The output is different. That's the gap, and it's everything.
“AI doesn't replace the thinking. It executes the thinking at speed. Skip the thinking, and speed just means you build the wrong thing faster.”