Preface
I am not a software engineer. I don't have a CS degree. I couldn't have written a React component from scratch two years ago. Today I run a live SaaS platform — multi-platform social media scheduler, AI tools, payments, background jobs, the whole thing — that I built at a deli counter and shipped from a laptop at midnight.
The thing that changed everything wasn't a bootcamp. It wasn't a YouTube series. It was learning to work with AI the right way — not as a search engine, not as a code generator, but as a development partner that moves as fast as you can think.
"Vibe coding" is a term some people use mockingly. I use it earnestly. It means: you understand what you want to build, you can communicate it clearly, and you can iterate and debug until it works — even if you can't write the underlying syntax from memory. Vision over syntax. Clarity over credentials.
This guide is everything I learned. What stack to use, how to prompt, what to do when it breaks, and the mental game of shipping imperfect things into the world on purpose. Let's go.
What Vibe Coding Actually Is
The Real Definition
Vibe coding is not a shortcut. It is not "have AI write everything while you sit back." That approach produces unusable garbage fast, and you won't understand it when it breaks — and it will break.
Vibe coding is a discipline: you hold the architecture in your head, you understand what each piece does at the functional level (even if not the syntactic level), and you use AI to accelerate the execution of your vision. You are the product manager, the architect, and the QA lead. AI is your senior engineer who never sleeps.
✗ What fails
- "Write me an app that does X" — too vague
- Copy-pasting AI output without reading it
- Not understanding what a function does
- Skipping testing because "AI wrote it"
- No version control, no rollback plan
✓ What works
- Specific, scoped tasks with clear requirements
- Reading every line before you accept it
- Understanding the "why" of each change
- Testing every feature in a real browser
- Committing frequently, branching for every change
What You Actually Need to Know
You don't need to memorize syntax. You do need to understand concepts:
How the web works
Client vs. server. What happens when you hit a URL. What an API is. What JSON is. You can learn all of this in a few hours — it's not optional.
Data flow
Where does data come from, where does it go, who can see it. If you can draw this for your app on a whiteboard, you can build it.
Functions and state
A function takes input and returns output. State is data that changes over time. That's 80% of what you need to know about programming at the conceptual level.
What a database does
It stores things persistently. A table is a spreadsheet. A row is a record. SQL is just asking questions about the spreadsheet in a specific language.
Errors are feedback
A red error message is not a failure. It's the computer telling you exactly what's wrong. Learn to read them. They're specific and they're honest.
The Permission Fallacy
The old gatekeeping argument was: "You can't build real software without a CS degree." That argument existed to protect a scarcity that no longer exists. AI tools didn't lower the bar — they redistributed the bottleneck. The bottleneck is no longer syntax knowledge. It's now clarity of vision, quality of communication, and willingness to iterate.
If you can describe exactly what you want to build, explain why it needs to work a certain way, and communicate what's broken when something goes wrong — you can build software. That's the whole unlock.
The Stack — What I Actually Use
I'm going to tell you exactly what I use to run a live production SaaS. I'm not going to recommend anything I haven't personally shipped with. Every free tier noted.
Next.js (App Router)
Full-stack in one codebase. API routes + frontend + server components. Deploys to Vercel in one click. The AI tools know it better than any other framework — you'll get better completions.
TypeScript
Types catch bugs before they happen. When AI generates code with types, you can read the shape of data without running the app. More readable, more debuggable.
Supabase
Postgres database, row-level security, auth, file storage, and real-time subscriptions — all managed, all with a generous free tier. You don't manage servers. The AI knows Supabase extremely well.
Tailwind CSS
Write styles in the HTML. No separate CSS files to manage. AI generates Tailwind perfectly. Dark mode, responsive design, animations — all built-in utilities.
Vercel
Push to GitHub, it deploys. Preview URLs for every PR. Environment variables in a UI. Domain management. Zero DevOps. Free tier is genuinely usable for early products.
Stripe
The industry standard. Subscriptions, one-time payments, webhooks, customer portal. The docs are excellent. AI can write Stripe integration from a description.
Inngest
Scheduled functions, event-driven workflows, retries, observability. Critical for anything that needs to run on a schedule (like scheduled posts). Free tier is solid.
Google Gemini API
Extremely cheap per token. Generous free tier. 1M+ context window. Good for generation tasks. For coding assistance itself, use Claude.
Resend
Developer-first transactional email. Clean API. React email templates. Dead simple to wire up for welcome emails, notifications, etc.
Claude Code
This is the one. Not a browser copilot — an agentic CLI that reads your whole codebase, edits files, runs commands, opens PRs. It's how I built everything in this stack at 2am.
Total monthly cost when starting out
Infrastructure: $0. The free tiers on this stack can handle your first 1,000 users comfortably. The only non-optional cost is Stripe's transaction fee on revenue. I spent $0/month on infrastructure for the first 6 months of SocialMate's life.
The Workflow — How a Build Session Actually Goes
Before You Open Your Editor
The most expensive mistake in vibe coding is starting to build before you know what you're building. AI moves fast. If your direction is wrong, you'll be fast in the wrong direction — and unwinding AI-generated code is harder than writing it.
Before every feature, I answer three questions on paper (or in a note):
- What is the user experience? Describe every click, input, and state change from the user's perspective. No code, just behavior.
- What data is involved? What do I need to store? Where does it come from? Who can see it?
- What's the simplest version? What's the minimum that could ship tonight? Strip everything that's not essential to the core function.
The Build Loop
1. Write the DB schema first
Before a single line of frontend code, define your table. What columns do you need? What types? What relationships? Run it in Supabase. If the data model is wrong, everything built on top of it is wrong.
2. Build the API route
What does the server need to receive? What does it return? Wire the database query. Test it with a raw fetch() call in the browser console before touching the UI.
3. Build the UI last
Now that data flows correctly, connect the frontend. The UI is the least important part to get right first — it's also the easiest to change.
4. Test in a real browser
Not in the AI's imagination. Not in a unit test. In Chrome, with real clicks, on the actual page. AI can generate tests — but it cannot feel whether the UX is confusing.
5. Commit and move on
Small commits. Descriptive messages. Every working state is a checkpoint you can return to. Never accumulate three weeks of changes before committing.
Context is Everything
The single biggest performance difference between vibe coders is how well they manage AI context. A tool like Claude Code reads your whole codebase — it knows your patterns, your variable names, your existing components. This context makes every subsequent prompt smarter.
Things that kill context quality:
- Switching topics mid-session without resetting
- Asking questions that are too vague ("fix this")
- Not telling the AI about your existing patterns ("use the same auth pattern as in /api/posts")
- Letting a session go too long without a checkpoint commit
Practical habit
Keep a CLAUDE.md file in your repo root. Put your tech stack, gotchas, coding rules, and key architectural decisions in it. Claude Code reads this automatically every session — it's like a project brief that you only write once.
Prompting That Ships
Prompting is a skill. Vague prompts produce vague code. Specific prompts produce specific code. Here's how I think about it.
The Anatomy of a Good Prompt
Example: Adding a feature
Context: "I have a posts table with columns id, content, user_id, scheduled_at, status."
What I want: "Add a retry button to failed posts in the queue page. When clicked, it should reset status to 'scheduled' and set scheduled_at to 5 minutes from now."
Constraints: "Use the existing PATCH /api/posts/[id] route. Match the existing button style in the queue. Don't break the published posts section."
Edge cases: "Show a spinner while the request is in flight. Show a success toast after. Don't show the retry button if status is 'published'."
Prompt Patterns That Work
"Use the same pattern as..."
Point to existing working code. "Use the same auth check as in /api/posts/publish" tells the AI to follow your established patterns instead of inventing new ones.
"Don't touch X"
Explicitly protect working parts. "Don't modify the Stripe webhook handler" or "don't change the sidebar layout" prevents well-intentioned but destructive edits.
"The simplest possible version"
AI tends to over-engineer. Explicitly asking for the simplest approach prevents abstraction you don't need yet.
"Step by step"
For complex features, ask the AI to explain its plan before writing code. Catching a wrong architectural decision in the plan stage is free. Catching it after 200 lines of code is expensive.
"This is what the error says exactly"
Paste the full error message, not your interpretation of it. The AI can diagnose from the raw output better than from your paraphrase.
What to Never Do
- Never ask for everything at once. "Build me a full social media scheduler" is not a prompt. Break it into: auth, then post creation, then scheduling, then publishing. One thing at a time.
- Never skip reading the output. Every line of AI-generated code is a line you're responsible for. Read it. Understand what it does. If you can't explain it, you don't own it yet.
- Never ignore warnings. TypeScript errors, console warnings, deprecation notices — these are the AI's way of telling you something is fragile. Fix them before moving on.
- Never assume correctness. The AI will confidently generate code that does the wrong thing. Your job is to test every feature as if you expect it to be broken.
When It Breaks — Debugging Without Panic
Everything breaks. Your job isn't to prevent breakage — it's to fix it fast. Here's the framework.
The Debugging Hierarchy
Is it a syntax error?
The error message tells you the file and line number. Go there. Read the line above and below. 80% of syntax errors are a missing bracket, comma, or semicolon.
Is it a runtime error?
Open the browser console (F12). Read the error. Copy the full stack trace into Claude Code. Paste the relevant code. Ask "what's wrong?" with the specific error.
Is the data wrong?
console.log() everything. Log the API response before you render it. Log the database query result before you return it. Don't guess — observe.
Is it a build error?
Run the build locally. npm run build tells you every TypeScript error with file and line number. Fix one at a time, starting from the top — later errors often cascade from earlier ones.
Is it a deployment error?
Check your environment variables first. Missing env vars are responsible for ~40% of "works locally, broken in prod" issues. Second: check the deployment logs in Vercel for the actual server error.
The Nuclear Option: Git Reset
This is why you commit frequently. If you've been working for 30 minutes and something is deeply broken and you can't figure out what the AI changed to break it — roll back. git diff HEAD shows every change since your last commit. git stash saves your current state temporarily. git checkout -- . discards all changes and returns to the last commit.
The rule that saves sessions
Every time a feature works — commit immediately. "feat: X working" is a valid commit message at midnight. You can clean it up later. The working state is what matters. Every commit is a checkpoint. Every checkpoint is irreversible protection.
Knowing When to Stop Fighting
If you've been debugging the same issue for more than 45 minutes and you're going in circles — stop. Write down exactly what the error is and what you've already tried. Sleep on it, or come back after a break. Your brain will have processed it. The error will look different.
Some bugs also need a completely different approach — not a fix to the current approach, but abandoning it. If AI-generated solution A keeps breaking, ask for a completely different implementation strategy for the same outcome.
Going Live — The First Deploy
The Minimum Viable Deploy
You don't need to be "ready" to go live. You need to be safe enough that you're not going to hurt anyone or leak data. The bar is lower than you think.
Auth works
Users can sign up, sign in, and sign out. Their data is isolated. Row-level security is enabled in Supabase.
No exposed secrets
API keys are in environment variables, not in code. Your repo is private or secrets are in .gitignore.
Payments work (if charging)
Run a real $1 test charge through Stripe. Don't soft-launch with payments you haven't personally tested end-to-end.
The core loop works
The one thing your app is supposed to do — it actually does it, reliably, in production. Not just locally.
You can recover from a crash
If everything breaks, can you roll back? Do you have your last working commit? Do you know how to redeploy the previous version?
Ship Imperfect on Purpose
The most dangerous thing you can do is wait until it's perfect. It will never be perfect. Every day you delay is a day you're not getting real feedback from real users.
SocialMate launched with a broken Twitter integration, a UI that was half-finished on mobile, and zero marketing. Those things got fixed because real users hit them and reported them. The things I thought were problems before launch — most of them weren't. The real problems I couldn't have predicted from inside my own head.
The feedback loop advantage
A polished product with zero users gives you zero feedback. A rough product with 10 real users gives you 10 feedback loops. Each loop tightens your next build iteration. Ship the rough thing. Fix fast. That compounding feedback is worth more than any amount of pre-launch polishing.
Domain, Analytics, Error Tracking
- Domain: Get a real domain from Porkbun or Namecheap ($10–$15/year). Vercel handles SSL automatically. Point your domain to Vercel's nameservers in 10 minutes.
- Analytics: Vercel Analytics is built-in and free. Install it. Know how many people are actually using each page before you decide what to build next.
- Error tracking: Sentry has a free tier. Wire it in on day one. You want to know when something breaks in production before a user emails you about it.
The Mindset
The Comparison Trap
At some point you will compare your code to a "real engineer's" code and feel like a fraud. The code will look different. It will be structured differently. A trained engineer would have done it differently.
Here's the thing about that: does it work? Does it ship? Does it serve real users? Does it handle edge cases? Is it secure? If the answers are yes — the "elegance" of the implementation is academic. Software's only job is to work correctly for the people using it.
There is a kind of snobbery in software engineering that equates method with outcome. Ignore it. Judge your work by outcomes, not by how a CS curriculum would grade it.
Building in Stolen Hours
Most of SocialMate was built between 10pm and 2am. I have a full-time job. I have a life. I don't have the luxury of 8-hour build sessions. What I have is consistency: show up to the keyboard when you said you would. Even if it's 45 minutes. Even if you're tired. Especially if you're tired, because tired builds are what separate people who ship from people who talk about shipping.
One small thing shipped is worth more than ten big things planned. The person with a live, imperfect product beats the person with a perfect wireframe every time.
What AI Actually Changes
AI didn't make me a software engineer. It made the software engineering part of my vision executable without me becoming a software engineer first.
The creative work — figuring out what to build, how to position it, what problem it actually solves, what the user experience should feel like — that's still entirely human. AI handles execution. You still have to have the vision worth executing.
If you have a real idea, a genuine problem you want to solve, and the patience to iterate — you can build it now. The tools exist. The free tiers exist. The knowledge exists. The only thing that was ever actually in the way was the belief that you needed permission.
You don't need a CS degree. You need a clear vision and the will to iterate.
That's the whole unlock. The rest is just building.
Scaling Past One Feature — Agents, Crons, and Memory
From One Prompt to a System
When you're starting out, vibe coding looks like this: one prompt, one feature, one file, you watching every line scroll by. That's the right way to learn, and it works fine for the first few months.
But as your product grows, you start needing things that run without you. Things that fire while you're asleep, while you're at work, while you're doing literally anything else. Daily digests. Weekly reports. Recurring content generation. Cleanup jobs. The product needs to keep moving even when you're not at the keyboard — and you need to be able to work on more than one thing at a time. This chapter is about what changes when you cross that line.
Background Agents — Working in Parallel
Modern AI coding tools (Claude Code is the one I use) can spin up sub-agents — separate workers that go research or implement an isolated piece of work while you keep building on the main thread. You're not waiting around for one task to finish before starting the next. You're running two or three lanes at once.
✓ Good for background agents
- "Add this feature across all 10 of these similar files"
- "Find every place this pattern is used and summarize it"
- An isolated bug fix that doesn't touch what you're working on
- Large-scale content or data tasks (writing 30 blog posts, generating SQL inserts)
- Research tasks where you just need an answer, not a conversation
✗ Don't hand off to an agent
- Anything where you need tight context continuity with what you're doing right now
- Decisions that require your judgment — pricing, architecture direction, what ships and what doesn't
- Work that touches the same files as your current session at the same time
- Anything you can't review carefully when it comes back
Think of it like delegating to a capable junior who's great at execution but needs clear scope. Give the agent a self-contained task with enough context to act without you, let it run, and review the result before it merges into your main work. The win isn't that the agent is smarter than you — it's that your time stops being the bottleneck for everything.
Cron Jobs — Things That Happen Without a Click
Once your product has real users, a lot of the most valuable things it does shouldn't require anyone to click a button. A weekly digest email. A daily check for stuck jobs. A recurring content generation run. These need to happen on a schedule, reliably, whether or not you're awake.
I use Inngest for this (it's in the stack from Chapter 2, free tier covers a generous number of runs). The pattern is simple:
1. Write the function
A normal function that does one job — send an email, check a table, generate content. Same code you'd write for an API route.
2. Register it with a cron schedule
Tell the platform when to run it: "every day at 6am UTC", "every Monday at 9am", "every 15 minutes". Cron syntax, no servers to manage.
3. Add an idempotency guard
This is the part people skip and regret. If the job fires twice (it will, eventually — retries, overlaps, edge cases), it must not double-send, double-post, or double-charge. Check a "already done" flag before doing the work.
4. Let the platform handle reliability
Retries, failure logs, observability — that's what you're paying the free tier for. Your job is the function. The platform's job is making sure it actually runs.
SocialMate now runs more than 8 of these automated "agents" on schedules — newsletters, client reports, inbox replies, trend analysis, repurposing old content, and more. Each one is its own small function with its own cron line. None of them require me to be online for the product to keep working for users.
CLAUDE.md — Your Project's Living Memory
Here's the problem nobody warns you about: as your project grows past a handful of features, you start re-explaining your whole product every session. What's the tech stack again? What bug did we already fix in this file? What did we decide about pricing? The AI doesn't remember last week's session, and re-explaining everything burns time and tokens.
The fix is one markdown file in your repo root that the AI reads automatically every session. As your project grows, this file becomes your single source of truth:
- Tech stack and key decisions — so the AI doesn't suggest swapping something you deliberately chose
- Known gotchas — framework-specific bugs you've already hit and fixed, so they don't get reintroduced
- Coding rules — your conventions, what not to touch, how to handle payments/auth/etc.
- What's been built — a running log so the AI knows what already exists
- A "Confirmed Done — stop asking about this" list — closed loops the AI shouldn't keep resurfacing
Why this matters more than it seems
Without a living memory doc, every session starts from zero. The AI re-suggests fixes you already shipped, re-explains patterns you already established, and you spend the first ten minutes of every session just getting it back up to speed. With one, every session starts already caught up — and that compounds across hundreds of sessions.
What Scale Actually Looks Like for One Person
Here's a real number, no exaggeration: 400+ pull requests merged in about two and a half months. Solo. Nights and weekends, around a full-time job. Using exactly the workflow in this chapter — background agents for parallel research and builds, cron-based automation for everything recurring, and a living memory doc to maintain context across hundreds of sessions.
The throughline is this: the AI models didn't get dramatically smarter overnight between when I started and now. The workflow scaled. One person with good systems can operate like a small team — not because the AI replaced the team, but because the AI plus the right systems removed the serial bottleneck that used to require more humans.
Solo Without Systems vs. Solo With Systems
✗ What fails at scale
- Re-explaining your whole project context every session
- Manually doing recurring tasks (sending the digest, checking for stuck jobs)
- One person doing everything serially, one task at a time
- Re-litigating decisions you already made weeks ago
- Losing track of what's already shipped vs. still pending
✓ What works at scale
- CLAUDE.md (or your tool's equivalent) as persistent memory
- Cron automation handling recurring work without you
- Background agents running parallel research and builds
- A "Confirmed Done" list so closed loops stay closed
- You spending your time on judgment calls, not repetition
You don't scale by working more hours. You scale by building systems that work when you're not.
Memory, automation, and parallel work are how one builder starts operating like a team.
All Resources — Bookmarked
Get new guides when they drop
No courses. No upsells. Just the real stuff — straight to your inbox, free forever.
No spam. Unsubscribe anytime.
Power to the people.
The tools exist. The knowledge exists. The only thing that was ever actually in the way was the belief that you needed permission. You don't.
