Modern Creator
Sean Kochel · YouTube

11 Things That Separate Vibe-Coded Toys From Real Apps

A one-hour engineering checklist for builders who can ship prototypes but keep breaking production.

Posted
2 days ago
Duration
Format
Tutorial
educational
Views
2.2K
101 likes
Big Idea

The argument in one line.

The difference between a vibe-coded toy and a production app is not the AI model you use or how fast you can prompt -- it is whether you have systematic processes for building on rails, catching failures, and knowing what is happening after you ship.

Who This Is For

Read if. Skip if.

READ IF YOU ARE…
  • You have built several AI-assisted apps and can get an MVP running quickly but keep running into problems the moment real users show up.
  • You are self-taught or bootcamp-trained, comfortable with vibe coding tools like Claude Code or Cursor, and want to understand what production-grade engineering actually requires.
  • You are preparing to ship an app publicly and want a comprehensive checklist of what to harden before launch.
  • You want specific tool recommendations -- not just principles -- for testing, security, observability, and deployment pipelines.
SKIP IF…
  • You are a senior software engineer with production deployment experience -- most of this will be review.
  • You are still in the idea or early prototype stage and are not yet thinking about users -- come back when you are closer to shipping.
TL;DR

The full version, fast.

Vibe coding without engineering guardrails produces apps that break the moment they reach users. The presenter organizes the gap into 11 areas -- spec-driven development, documentation, version control, testing, auth, error handling, databases, security, hosting, deployment, and observability -- and gives two to three concrete tool or process recommendations per area. The through-line is a gate-vs-net mental model: gates (SDD, typed schemas, migrations, CI pipelines) prevent bad code from reaching production; nets (error boundaries, Sentry, observability dashboards) catch what slips through. Most failures traced back to skipping one of these areas, often because the LLM builds only the happy path.

Free for members

Chat with this breakdown — free.

Sign in and you get 23 free chat messages on us — ask for the hook, quote a framework, find the exact transcript moment, generate a markdown action plan. Bring your own key when you want unlimited.

Create a free account →
Chapters

Where the time goes.

00:0001:47

01 · Intro: Gate vs. Net

Cold open hook, the two-types-of-vibe-coders framing, the gate-vs-net mental model that structures the whole video.

01:4707:04

02 · 1. Spec-Driven Development

OpenSpec and GitHub Spec Kit as daily drivers; three reasons SDD wins; pairing with TDD skill for red-green-refactor task generation.

07:0413:27

03 · 2. Project Documentation

Anti-patterns and non-inferables in CLAUDE.md; nested per-directory markdown files; intent-layers skill; the stale-docs trap.

13:2717:56

04 · 3. Version Control

Atomic commits with why-messages; feature-branch and PR flow; rollbacks and recovery as a documented system.

17:5623:01

05 · 4. Testing

Red-green-refactor via Obra TDD skill; test pyramid (unit/integration/e2e via Playwright); regression testing per bug fix; model testing anti-patterns.

23:0126:33

06 · 5. Authentication vs. Authorization

AuthN = who are you, AuthZ = what can you do; models are poor at inferring authorization; defense in depth via API + Supabase RLS.

26:3332:02

07 · 6. Error Handling

Expected vs. unexpected errors; global fallback handlers; Sentry for error routing; input validation; API call timeouts and retries.

32:0237:44

08 · 7. Databases

Migration systems vs. raw updates; Expand-Migrate-Contract convention; indexes for query performance; N+1 query problem; RLS reinforcement.

37:4444:06

09 · 8. Security

DeepSec security harness; Trail of Bits skills library (sharp_edges); OWASP Top 10; secrets management and pre-commit scanning; business logic flaws and fail-open scenarios.

44:0648:04

10 · 9. Hosting

PaaS-first recommendation for non-engineers; environment separation (dev/staging/prod); scaling cost analysis via model before committing to a host.

48:0454:25

11 · 10. Deployment

GitHub Actions CI/CD pipeline (lint + type check + tests + build on every PR); Expand-Migrate-Contract for zero-downtime schema changes; safe releases via preview URLs.

54:251:00:19

12 · 11. Observability

Logs (centralized, with request IDs and user IDs), metrics (dashboards + alerts), traces (call-chain from global error handlers); AppSignal and Sentry as recommended tools.

Atomic Insights

Lines worth screenshotting.

  • Language models follow the happy path by default -- error handling, input validation, and authorization require explicit instructions or skills to get built.
  • Stale documentation in your CLAUDE.md is worse than no documentation -- the model follows outdated rules silently without telling you.
  • The Expand-Migrate-Contract pattern prevents the most common deployment failure: pushing code before the database schema it depends on is live.
  • N+1 queries are endemic in model-generated code -- a waiter making a separate trip to the kitchen for every persons order instead of one.
  • Authorization is not something a language model infers -- you must explicitly enumerate every table and relationship and define who can access what.
  • A pre-commit scanner for secrets is one of the easiest security wins and one of the least practiced -- commit a secret once and it lives in git history forever.
  • Business logic flaws are a real security category: a bug that causes the app to fail open can let free users access paid features and drain your API budget.
  • The reason to use nested CLAUDE.md files per directory is that agents read the nearest markdown file when entering a folder -- you get context-scoped instructions for free.
  • Spec-driven development tools force large tasks into small scoped chunks -- models almost always fail when the ask is too big.
  • Regression testing converts every bug fix into a permanent guard -- the next deploy cannot quietly reintroduce the same failure.
  • Row-level security at the database layer is a second enforcement point -- even if your API layer has a bug, the database rejects unauthorized reads.
  • Observability means you learn about problems from logs and alerts, not from user complaints -- without it you are flying blind after every deploy.
  • Atomic commits with why-not-what messages let you trace exactly what decision was made and why -- invaluable when a regression test fires weeks later.
  • PaaS first is almost always the right hosting call for non-engineers -- the perceived cost savings of a VPS are wiped out by the operational complexity cost.
Takeaway

Eleven disciplines that keep AI-built apps standing.

WHAT TO LEARN

AI makes it trivial to build a prototype -- what it does not do by default is handle errors, enforce authorization, manage migrations, or alert you when things break in production.

02Spec-Driven Development
  • Spec-driven development tools convert a vague idea into a scoped contract before any code is written, preventing models from going off-script on large asks.
03Project Documentation
  • Two categories belong in CLAUDE.md: explicit anti-patterns the model should never do, and non-inferables -- context it cannot derive by reading the codebase alone.
  • Stale documentation is actively dangerous: models silently follow outdated rules, and they will not tell you that is why they keep making the same wrong decision.
04Version Control
  • Atomic commits with why-not-what messages create a traceable lineage that lets you (and the model) understand what was done and why, weeks later when a regression fires.
05Testing
  • Every bug fix should become a regression test -- the next deploy cannot quietly reintroduce the same failure if a test already guards against it.
06Authentication vs. Authorization
  • Authorization -- who can do what inside your app -- is not inferred by models; you must enumerate every table, schema, and relationship and explicitly define access patterns.
07Error Handling
  • Language models build the happy path by default: error handling, input validation, and retries must be specified through skills or explicit instructions.
08Databases
  • The Expand-Migrate-Contract convention prevents the most common deployment failure: code hitting production before the database schema it depends on is live.
  • N+1 queries and missing indexes are endemic in model-generated database code and can cripple performance at even modest scale -- both require explicit review.
09Security
  • Business logic flaws are a real security category: errors that cause the app to fail open can give free users paid-tier access and drain your API budget.
  • A pre-commit scanner for secrets is one of the easiest security wins -- a hardcoded key committed once lives in git history forever.
10Hosting
  • PaaS-first is almost always the right call for non-engineers -- the perceived cost savings of a VPS are wiped out by the operational complexity you introduce.
11Deployment
  • A CI pipeline that runs lint, type checks, tests, and build on every pull request is the minimum gate before anything reaches users.
12Observability
  • Observability means you learn about production problems from logs and alerts, not from user complaints -- without it you are flying blind after every deploy.
Glossary

Terms worth knowing.

Spec-Driven Development (SDD)
A workflow where you generate a formal specification for what you are building before writing any code, creating a contract the AI model must satisfy and a traceable record of every decision.
Non-inferables
Knowledge a coding agent cannot derive by reading the codebase -- architecture decisions, project-specific conventions, or context that would require reading many files to understand -- that belongs in CLAUDE.md instead.
Gate vs. Net
A mental model for production safety: gates are systems that prevent bad code or bad inputs from reaching production in the first place; nets catch and contain failures that slip through anyway.
Expand-Migrate-Contract (EMC)
A database migration convention where you first add new schema without removing old (expand), then ship code and backfill data (migrate), then delete the obsolete schema (contract) -- preventing downtime from code-schema mismatches.
Red-Green-Refactor
A test-driven development cycle where you write a failing test first (red), write the minimum code to make it pass (green), then improve the implementation while keeping the test passing (refactor).
N+1 query
A database performance problem where code makes one query to get a list and then an additional query per item in the list, instead of fetching everything in a single query -- a pattern common in AI-generated code.
Row Level Security (RLS)
A database-layer access control feature (popularized by Supabase/PostgreSQL) that enforces which rows a user can read or write directly at the query level, providing a second line of authorization defense beyond the API.
OWASP Top 10
A widely referenced list of the ten most critical web application security vulnerabilities, published by the Open Web Application Security Project and updated approximately every four years.
Fail open
A security failure mode where an error causes a system to grant more access than intended rather than less -- for example, a bug allowing free-tier users to access paid features.
Observability
The practice of instrumenting a production app with logs, metrics, and traces so you can understand what is happening internally and detect problems without relying on user reports.
Resources

Things they pointed at.

03:14toolOpenSpec
18:32toolObra Superpowers TDD skill
30:32toolSupabase
31:17toolSentry
38:49toolDeepSec
54:25toolAppSignal
Quotables

Lines you could clip.

01:47
Vibe coding without process guardrails is the biggest recipe for disaster I could possibly think of.
Strong declarative thesis, zero setup needed, stands aloneTikTok hook↗ Tweet quote
21:54
Language models are lazy assholes that will try to sidestep this process.
Honest, funny, quotable -- rare candor about model behavior in a tutorial contextIG reel cold open↗ Tweet quote
11:20
Any sort of stale note that exists inside of your system is going to be a kick in the nuts from a steel toad boot.
Memorable metaphor, visceral, specific to a common painful experiencenewsletter pull-quote↗ Tweet quote
41:16
You could have a situation inside of your app where you don't handle errors properly, and someone sends a bad request through to your back end, and it actually breaks -- and when it breaks, what does it allow people to do?
Reframes security from 'keeping people out' to 'what happens when things go wrong' -- counterintuitive angleTikTok hook↗ Tweet quote
The Script

Word for word.

Read-along

Don't just watch it. Burn it in.

See every word as it's spoken — crank it to 2× and still catch all of it. The same dual-channel trick behind Amazon's Kindle + Audible.

metaphoranalogy
00:00There's two types of vibe coders out there in the world. There's the ones that actually ship real stuff, and there's the ones that become the source material for all of those vibe coding memes that people won't shut up about. The difference isn't talent, and it's not tools.
00:13It is the processes they follow and the vocabulary that they have. So in this video, I'm gonna go through the top 11 areas that you need to master if you want to be able to vibe code a production app that doesn't fall down the moment a user even looks at it.
00:30So I'm gonna go through each area, talk about, like, what it is specifically, and give two to three concrete recommendations for each area. And by the way, as you're watching, if any one of these things jump out as something that, like, you'd wanna see a dedicated video on, you can comment below and let me know, and it shall be done.
00:45And as always, this video is sponsored by me. That's right. I go through all of this stuff in detail in my paid community.
00:52Who knew? So before we kick this off, a quick mental model that will kind of frame a lot of this. It's this concept of, like, a a gate versus an a net.
01:02So when we're talking about, like, taking something to production environment, we have things that are going to be gates that we put in place so that bad inputs, to the best of our ability, like, can't actually make it through into the production environment in the first place.
01:19So we're gonna have gates, and then we're gonna have nets. So, like, what do we do once something actually does, you know, hop over our gate and make its way toward our pretty nice looking house.
01:30And so the first thing on this list that to me is absolute king, if you wanna be able to build things that don't break all the time, and, like, you wanna have the confidence to be able to push an app to production, like, with new features and not think like, oh, I wonder if this is gonna, like, completely break for all of my users.
01:47That thing is spec driven development. Vibe coding without process guardrails is the biggest recipe for disaster I could possibly think of.
01:57If you're somebody that, like, only uses, like, some sort of skill plugin without, like, any sort of process around it and you're just relying on, like, the artifacts that they create in their process, I think unless, like, you're an engineer that has, like, a lot of other systems you follow already in place, you're gonna have a really bad time.
02:15So if you are, like, a vibe coder first, you should 100%, I will die on a hill arguing with anybody about this, use a spec driven development tool.
02:26So there are two tools that I use. Uh, one is called open spec. This is like my daily driver right now.
02:31Realistically, this is the one I use most. I should star it. Gonna star it.
02:34Um, the other one that I use is called GitHub spec kit. This is the first one that I ever used way back when, and it is also, like, a really, really, really solid tool.
02:45By the way, both of these tools can be extended to use plugins or skills from other people.
02:51So for example, like, if you really like something the Ober Superpowers library does or Matt Pocock's library or compound engineering or, like, any of those things, you can integrate those skills and commands into how you use these systems. So it's not like a one or the other type of thing.
03:08But there's three reasons really that I I love using these tools, and then we'll talk, like, a little bit about these two tools specifically. Number one, the spec becomes a contract that you can force the model to abide by. Right?
03:20So you can go back and forth, determine, like, exactly what needs to be done, and then have very clear criteria to test if the model actually did the thing the right way. Why?
03:31Because it was all documented in excruciating detail ahead of time. Number two, it really helps you break down larger things that you would want to do into a series of, like, smaller digestible chunks, and that is really valuable.
03:46Most models out there, the only exception to this for me was Fable five when I was using it. They are really bad at taking, like, a giant ask with a lot of background context and actually implementing it successfully on, like, the first or second try.
04:00If the task is too big, they are going to fuck it up, I guarantee halfway through, and then you're gonna have to go through and try to untangle things if you even catch the things that it did in the first place that it wasn't supposed to be doing. And the third one, and this is really valuable, is the traceability of what you are doing.
04:18Every single time you go to build something in either of these tools, it all gets documented. So for example, like in OpenSpec, they have a changes directory.
04:27Inside of that change directory, it is logging, like, all the different artifacts that it had related to that change, any sort of issues that it's related to from GitHub, all of the commits that are associated with the work that has been done, like, all of that stuff can be added into the system so that there's, like, a very clear traceability in, like, lineage of exactly what was being done and why it was being done and why that manifested in, you know, all of the changes that are actually in those commits that you're making.
04:55So then two weeks from now, when you realize that you actually have a bug, you can go back, like, specifically to that point, and all of that context is there for you already. So the OpenSpec, like, approach to this is that you have actions. You don't have phases.
05:10So the way that OpenSpec, like, generally works, if you wanted this to be like a a process, even though it says these are actions, not phases, you generate a proposal. So this is you, like, having, like, whatever your idea is of what you wanna build.
05:22You generate a proposal around that thing. From that proposal, you generate very concrete specs about what needs to be done.
05:30From those specs and the proposal, you generate, like, the design of the system, like, what needs to happen to bring these specs to life. All of that goes into context to create tasks.
05:42And then once you have these tasks, you can simply move forward and implement them. And then after it's implemented, you know, you can verify and do all of that stuff.
05:50But this creates, like, a very clear lineage and, again, like, traceable system that you can move back to at any point in time to know, like, exactly what decisions were made and where. The way, for example, that I use this is that when I'm generating, for example, like, my tasks, I will invoke a test driven development skill so that the tasks that get generated run through like a red green refactor type of cycle, which we will talk about that in a little bit.
06:17So OpenSpec is great, and then so is GitHub's spec kit. They have, like, a slightly different process that they follow where you run this, like, specify plan tasks implement.
06:25So different solutions to solve, like, similar problems. So this helps us solve the problem of, like, building on guardrails so that we're just not going out and doing, like, wild shit that's gonna make its way to production, the app breaks, and then no one wants to use your app anymore. Like, that's what we're trying to avoid with these types of, like, spectrum and development tools.
06:43But what do you do? Like, how do you make sure these tools have the best context possible for them to make their decisions?
06:51That brings us to our second thing that you absolutely need to do if you wanna be able to, like, push things into production and, like, code things that you can be pushing into production in, like, a sensible way is having really good project documentation and making sure it's hooked into your clawed markdown files properly.
07:08So there's been a lot of versions of, like, what people say should be inside of these things over time. I think I've been vibe coding for, like, roughly two years at this point, and there's been, like, a ton of different, like, things that people attempted to do for this. And then as the models got better, some of those things became less relevant, but that doesn't mean that everybody has caught up with the times.
07:28So inside of, like, your Claude markdown files specifically, the best thing in my experience to document in there are your known anti patterns, like things that you have discovered it should specifically not do, and then things that I have made up a word called noninferables, things that cannot be easily inferred from the code base itself.
07:51Meaning, there are things that are, like, knowledge only to you for whatever reason, and that can manifest in a lot of different ways that you need to document so that your coding agent actually has that knowledge as well, or things that in order for it to actually understand it properly, it would have to read a lot of stuff.
08:11It would have to go in and read, like, several different files in order to understand some sort of convention that you could have just told it very simply inside of your Claude Markdown file. Now admittedly, this is like its own video probably unto itself, like how to actually do this properly, and like what do those things look like.
08:29But broadly speaking, again, anti patterns, things that it, like, for sure should not do, and then things that it wouldn't be easy for it to know what to do unless it went through and read a bunch of stuff or read your mind. Now one really valuable thing to do, and, again, this can be included in the Claude markdown file, is context scoping and pointers.
08:49So something that I think a lot of people surprisingly don't actually know is that you can nest Claude Markdown files inside of your project. What that means is, like, if you were to have, like, your root directory here, most people think of having, like, their cloud markdown file in that and, like, hey. That's what gets read.
09:05But if you have, you know, four different subdirectories inside of your project, right, one's for, like, your API endpoints, maybe one's for, like, your actual apps UI, and then you have, like, some other ones. These can all have their own individual clawed markdown files or agent markdown files. So what that means is when an agent goes to, like, work inside of one of these directories, it has to read that markdown file.
09:27Right? It's like almost like adding or giving, like, more instructions to the system as it's moving into those specific areas. So what this means is, like, anytime you have some sort of, like, context that is becoming really important for you to document, you can kind of gather all of that context, describe how everything works, put it in its own markdown file, and then actually link to that context inside of your cloud markdown file.
09:54A good example of this in the wild is this skill library called, uh, intent layers, and it does exactly that. So it will go through your project.
10:04It will understand where there are directories that are, like, very big, and I think they define that by, like, 20,000 tokens. And then what it'll do is it'll create you a custom agent markdown file that explains all of the different, like, files and services and logic that exist inside of that, and then it'll actually link to that file that it created in your agent markdown file or a markdown file in your project.
10:26So now if it goes out and knows it needs to make an update, for example, to your payment service, it knows exactly where to go to read the documentation about that specific layer. Now brief aside, I've heard from some people on my channel that, uh, this skill doesn't actually work anymore. I have this on my GitHub repo.
10:43I cloned it over, and so you can go check that out if you wanna mess around with this. And so the last thing here is that inevitably, like, as your project grows over time and you're trying to, like, push stuff to real users and, like, do all of that, you are going to forget things that you did. And the problem becomes, if you documented things that are no longer actually relevant or up to date or are now wrong and you don't catch that, you are gonna have a very hard time.
11:11Any sort of, like, stale note that exists inside of your system about, like, an architecture decision or why a certain component is the way that it is or, like, anything is going to be a kick in the nuts from a steel toad boot. It is one of, like, the most annoying failure modes of these models that, like, I guarantee you are going to run into if you're not constantly updating your Claude Markdown files and any documentation you have there or any other sort of mechanism by which you document things that are happening.
11:42This is part of the reason I love to use OpenSpec specifically because every single change that gets made becomes the living documentation over time. And you can only change that with structured changes that move through the open spec process.
11:56So you never run into these situations where you have documentation now that's just completely stale, and it is leading the model astray. And one of the reasons, by the way, that this becomes, a real problem and you might not know it, is that the language model isn't necessarily going to say to you, hey.
12:12Well, yeah, I keep making this decision because in this obscure line over in this file, you have a comment that I could never change this. So I've just been making all of these solutions up because I read that thing. And that's actually kinda reasonable.
12:24It's like, yeah, I did have that documented there, but it's not going to tell you that's the case. And what that means is you're gonna run into these walls where you only end up solving that problem if you actually go in and understand who to thought how things are working inside of your project.
12:40So if you don't get this one ironed out, it's gonna be a really hard time, and it's gonna be super, super, super messy. So if we zoom out to, a thousand foot view here for a second, we've decided that, hey. We need to be, like, brutal about our documentation of how things work inside of our code base, and we need to be building on rails.
13:00We need to have a system that pushes us through a, like, very structured and sometimes opinionated way to build things. But that being said, how do we do it, though?
13:11So this is where we're gonna start getting into a lot of the topics that, like, if you really want to be able to do this stuff and push your app to users in, like, a real way and have confidence that it's not just gonna break all the time, these next, like, nine or so things that I'm gonna go through are, um, a lot of, like, the meat and bones of it.
13:27So the first thing we're gonna talk about is version control. If you do not use a, like, structured version controlling system for what you are building, you will never ever have an app that actually makes its hands into real users that they continue to stay in.
13:42It it will not happen. Why is that the case? Because version controlling helps us make sure that we have systems and structures processes in place to know what we are building, building it in, like, a safe contained environment, and then having systems for rolling back to other states when something does in fact break.
14:01So there's three recommendations on this list. Number one, atomic commits. Again, this is something that's annoying that, like, language models will not do this by by default.
14:11And so you have to have, like, some sort of skill or some sort of instruction for it to actually do this. But what we mean when we say atomic commits is, like, one scoped logical change per commit that gets made.
14:24Now the other thing that makes this very helpful, especially for use in language models, is having a good commit message. I don't know why I decided to, you know, draw that out.
14:36Having a good commit message that explains why we made the changes related to this commit.
14:44This is valuable because when you do those adversarial review passes and all of those other things, or you're using tools like OpenSpec and you're going back through verification phases, you want it to be able to look at what was the commit that was made, and what was the rationale behind why the model did that thing specifically.
15:03So atomic commits are really, really, really important. Number two, branching and your pull request flows. So this one's, like, pretty straightforward.
15:13You should always be using feature branches or work trees to, like, do your feature work, never committing onto main. And you should actually have a documented, like, guarded structure for how these changes actually make their way into your app.
15:30So for example, in one of my projects, I have a rule where a regular user or agent or like so me on my computer cannot open a direct poll request to the main branch of the project. It has to flow through from one of my feature branches into my development branch, and then only the development branch can open a pull request into main to promote all of the changes after, like, the tests and everything have passed.
15:59So, again, if you want to be able to put your app in people's hands, you have to have, like, a good strategy for how you're gonna do pull requests and how you're gonna manage, like, your branching strategy for fixing bugs and making features and all of that stuff. And then last but not least, rollbacks and recovery. Like, something will break for sure.
16:17Even in the best companies, like, things break. And so you need to have a system for understanding what versions actually worked inside of the app and being able to, like, roll back or recover the app to that point in time. So this really, like, it's it's not one of those things that you just pay lip service to and pretend you do it because you have one skill that does a piece of this.
16:39Because if that describes what you do, you're gonna have, like, a a horrible time trying to actually make something that, again, does not just break all of the time for users. But not having any strategy is, uh, not a good strategy. So in a bit, we're gonna talk about, like, what do you actually do when something does break in production?
17:00And how do you actually, like, use this version controlling that we've been doing to revert back to, a state that actually works? But first, gotta talk about testing. So look, we all know what testing is.
17:10Right? I'm not gonna belabor the point. Like, you build things, and you test that the things that you built actually work.
17:17And then, as we'll talk about in a later section in this video, you can run those tests automatically before you ever deploy your app to make sure that something's not broken. And so the best way to think of these is, like, they are guardrails, uh, number one, like, for you, but also for the for the agent.
17:34Right? These are, like, guardrails. Like, tests will actually drive the agent to build the things properly because the tests that defined what being done properly means were done before the agent decided to, you know, write any of the actual code.
17:49So there's a few different pieces to this. Then the the first one is red green refactor. This one's, like, very, very popular.
17:56If you're a fan of, uh, Obra's superpowers, which I am, he has a test driven development skill that I really do highly recommend you all use, and that is the process that this thing follows.
18:07It follows a red green refactor. And if you don't know what this means, it it simply means first you write a failing test, and you verify that it does in fact fail.
18:18Then you write the minimum amount of code to actually get the test to pass, so you're, like, building the functionality that now makes the test pass. And then from there, you can refactor it to be, like, the optimized version of the thing that still gets the test to pass. So that's a red green refactor.
18:34I recommend, again, if you're using, a project you actually care about, you should be using this type of, like, test driven approach with, like, a red green refactor. If you're just doing something, like, for yourself and you don't really care that much, then you don't have to do that. But I use this in combination with OpenSpec so that part of the tasks that get generated have this red green refactor built into it.
18:55Number two, it then becomes like, well, what do you actually test? Because there's different types of tests. So for example, you have, like, unit tests, which will test, like, individually contained kind of things.
19:07You have integration tests, which can test when, like, multiple services interact with each other. And then you have things like end to end tests, where you're gonna actually use a tool like Playwright, for example, to, like, actually go in and operate the browser to test critical paths.
19:22I like to put end to end tests in in place for, like, money paths, like, things that are mission critical. Like, for example, a Stripe integration. Like, can a user actually move through and sign up via Stripe and, like, upgrade their account?
19:35And maybe just, like, the core most, like, value adding feature of the app actually work. So the reason that I say this and, like, the concrete recommendation is you wanna make sure that you have tests covering those different areas.
19:46Like, unit tests can run very fast because they tend to test, like, very, like, siloed kind of deterministic type of things. Like, is one plus one two? Cool.
19:56We didn't mess up the sum two numbers function. That would be an example of a unit test. There are other types of tests that I'm not gonna go into here where you can, like, try to actually mutate things inside of the code base and, like, make sure the tests still fail.
20:10There's, like, a lot more advanced stuff. But in general, the reason I say this, you should be paying attention to, like, what are the actual types of tests that your coding agents are using, and do you have, like, good coverage across your your project? The reason I have a question mark here is that there's, like, debate, I guess, about, like, how many of each type should you have?
20:29What type of cover how much of the code base should be covered in tests? I don't know. That type of stuff's a little bit up for debate, but I think if you're, like, directionally moving toward, like, trying to have tests in critical places and then just adding them as they make sense while you're building things, I think you'll be in a pretty, uh, pretty good spot.
20:44The last thing is this concept of regression testing. And so if you were to think about, like, anytime you experience a bug inside of your app, that is now, like, a new test case.
20:54Right? I can write a test that kind of shows why that bug is failing, then we can fix it. And now every new PR that ships is not going to make that same bug come about because we have tests in place that actually now check for that thing.
21:09So that's a good habit to get into anytime you're moving through and doing bug fixes, creating an actual test for that bug that you found so that, again, it does not reintroduce itself. And so you can pair this with, like, the version control stuff we talked about earlier, having, like, commit messages that explain why things were done so that if if ever, like, this regression test starts failing again, the model can go back and actually read, like, why did it fix it last time?
21:34How did it fix it? And, like, oh, now it understands, like, what the new issue is that it introduced, and it can fix the thing. And so a little bonus tip here, language models are lazy assholes that will try to sidestep this process, and so you need to be really deliberate about having, like, skills that force it away from those anti patterns.
21:53And, again, that's part of the reason I like Obra's test driven development stuff because he has this entire testing anti patterns, uh, section, which can, like, help us with a lot of, uh, a lot of this stuff. Not everything, but it can help you with a lot of this stuff. So you just need to watch out for, like, language models, writing tests that, like, it passes because it can never fail.
22:14Right? It's not actually testing anything. You wanna watch out for that type of stuff.
22:17But if you have a good process and you're instructing those types of things, you should be pretty solid. So the next section is authentication versus authorization.
22:27So this is, like, technically a security topic even though I tend to, like, teach them separately, because I think, like, authentication and authorization is something that, like, a lot of beginners at least, like, don't tend to, like, really get the differences between the two.
22:42And so we're gonna go back to this gate analogy here for a second. And one other thing on this, by the way, like, authorization, which we're gonna talk about in a second, is not something that language models actually do very well.
22:53In my experience, like, vanilla style.
22:56Like, they don't just know what people should be able to do inside of your app or not. So authentication is who are you?
23:04Authorization is what can you do?
23:07So if we were to go back to this, like, this gate that we have here in our image, authentication might be like, are you allowed to even, like, walk through the doors of this app? Like, are you allowed even, like, into my seemingly cool compound? Authorization might be like, what rooms in my home are you actually allowed to walk into?
23:27You you can't walk into the master bedroom. You can't walk into my vault full of golden bars. So, like, a concrete example of this in the wild, like, if you were to think in the context of, like, an app that you have, let's say you have a user named Joe, and he's like, hey.
23:40I'm Joe. And you look at, like, the authentication stuff that you have in place, you say, that is in fact a Joe. What do you wanna do, Joe?
23:47And he says, I wanna access all of Anne's personal information. Should he be able to do that?
23:54I mean, depending on the context of your app that you've built, I don't know. But a lot of the times, the answer to that is no. And that is something that a language model is not just going to automatically do, and it's something that you have to, like, actually have a back and forth with the system to try to understand the authorization patterns inside of your project.
24:14You might have database tables that everybody is able to access because it is a, you know, a public resource. So let's say you had a nutrition app. You might have, like, a public foods database that anybody can read from, but then individual users have their private recipes table that only they should be able to read.
24:32A language model is not necessarily going to just, like, infer what all of that should be. It's something that you need to actually tell it.
24:38And so the way that I like to do this is, like, actually grill back and forth. I like to look through, like, all of the data tables, all of the schemas, all of, like, the interactions, and make sure that for every single one of those things, there's a very clear understanding of the pattern of who should be able to access, like, different entities inside of the project.
24:56The second recommendation here is that you should be enforcing that, like, authorization in multiple places.
25:02So you should be enforcing that on the server side, like, in the API itself. So you should be checking for that in the API, but then also on, like, the database itself.
25:13And so if you're ever inside of Supabase and you see all the row level security conversation, that is what that's that's about.
25:20It's like, say, in this case, that user Joe, maybe there was a bug in your app, maybe they did it maliciously, they were able to bypass the API checking for their for the authorization, and they try to access, you know, Anne's database table, row level security could block that type of thing out.
25:38So you wanna have, like, defense in-depth, like, in layers inside of your application, like, especially when it comes to authorization and authentication. It's something that's, like, not, like, the headiest, most technical thing in the world, and so it really just takes the effort of you to sit there and have that back and forth, try to explore all of the different entities and, like, relationships between things in your app and have the model help you lock down, like, the proper access protocols for all of those things.
26:05And a little bonus tip, Suba Base has this new toggle switch when you create a new project where you can enable row level security by default. I recommend you do that, and you only turn it off on specific tables when you know that you need to. So next up, we're gonna get into, like, another area that unfortunately, I think language models are really bad at building for this type of thing.
26:25Maybe they'll get better over time, but where it stands now, it's not really there. And so I built my own, like, custom skills to help handle this type of stuff. But what we're talking about is error handling.
26:34So what I mean is, like, when something breaks inside of your app, does your entire app break or just the thing specifically in, a contained nice little box?
26:46Like, can someone still use the rest of the app if something breaks on this side? Or is the entire thing completely brick like the blue screen of of death? Shout out to the nineties Windows kids out there.
26:58Again, this is something that, like, a language model doesn't necessarily do by default. So there's really, I mean, two different, like, types of errors, I think.
27:08You have errors that you're expecting could happen, and then you have completely unexpected errors. So when you have an expected error, you could just give the user, like, a nice clean error message. So you could say, hey, failed to connect to mail service.
27:23Click retry to try again. Right? That's like, it's an error that you would expect could happen, and so we're handling that thing, and we have, like, a really graceful way to present the error to the user.
27:34But in the other case, you have unexpected errors. These are things that, like, maybe you haven't actually seen yet, so you're not really expecting them, hence, unexpected. And in these cases, what you typically wanna do is try to actually, like, catch these errors and route them to a, like, global error handler.
27:52So inside of your app, you should have, like, a global fallback handler at certain, like, boundaries inside of your app that when something breaks, that is the thing that actually handles it, and we're not dumping, like, stack traces and other sensitive things that we might not want somebody to see into the error message.
28:13So if you were to think about it, like, you're in the Next. J s project and you accidentally break something and it shows you the big ugly box saying, like, oh, all of the code at all these different places broke. You don't wanna send that to the user.
28:24And if you don't build for these types of things, that type of stuff can and will be sent to the user. So the second thing, don't, like, swallow errors. So you should have front end error boundaries that you build and back end error boundaries that you built.
28:40And inside of those different boundaries that you have, and you can think of those boundaries, like, I don't know, contained pieces, like logical pieces of the code base that if that thing broke, we would want to just contain the breakage to, like, just that area.
28:55We don't wanna just swallow those errors and, like, know nothing about it. Right? And so this is why using tools like Sentry can be valuable, because you can actually pass those error messages to, like, a monitoring tool, and you can see that these types of things are are actually happening inside of your application before, you know, you get a bunch of people churning out of your app, and you have a really, really bad time.
29:19And so the last piece, input validation and retries. So a lot of the time when we're building things, especially again with tools like ClaudeCode or not even just ClaudeCode, like any language model trying to code stuff out of the box tends to follow the happy path. It's just assuming everything is gonna go well a lot of the time.
29:35And so you should be validating your inputs on the front end. And if there's, like, a bad input, you should be rejecting those things.
29:42So if you're expecting someone to input, like, a number and they try to input a string in there, like, you should be rejecting that early so that that stuff doesn't actually make its way to your back end in the first place to cause these issues and errors. And you should also be wrapping any sort of, like, API calls, especially, like, external API calls inside of timeouts and retries.
30:03So for example, let's say you have, like, a language model app where you're whatever you're calling, like, Claude or OpenAI or whatever, you wouldn't want it to be the case that a user just keeps trying to, like, you know, spam something that's broken and then, like, blows your error rate, like, with the language model, like, out of the water.
30:21And next thing you know, everybody in the app is now suspended because people were inadvertently, like, abusing the endpoints.
30:29So, again, these are all different ways that you can handle errors. And by the way, with, like, all of this stuff that I'm going through, I'm not trying to say that this is, like, the exhaustive version of every single one of these topics. This is just like, hey.
30:41If you're not even covering off on any of these topics, like, well, you for sure should, and these are some of the low hanging fruits that you should be aware of. By the way, know we're going through a lot of stuff in this video. Like, I'm using, like, text on here and occasionally showing you libraries.
30:53Uh, inside of my paid community, I do go through all of this in detail inside of real apps, and I give you skills for for all of these things just in case you're curious about what to do with all of this. So, again, just recapping where we're at before we move on so that we're not all getting lost in the sauce. First thing was, like, spectrum in development.
31:11How are we gonna do, like, all of this stuff that we're talking about on rails so that we're really clear about what's being built and why? How are we gonna make sure that we're documenting all of the things that we know and that we learn along the way in such a way that it's, like, a living thing?
31:26And every time the model runs, it has, like, the best fresh context it could need. How do we set up proper version controlling so that when we are trying to, like, push things into, like, production or trying to build new things, we're not having these, like, edge cases where we actually, like, just completely break stuff.
31:42How are we putting testing in place as we move along this process of building things? How are we making sure, like, the, I think, most low hanging fruit of the security conversation for vibe coders at least is handled with authentication and authorization. And then inevitably, when things do break inside of the app or users are running into errors, how are we handling that type of stuff in a graceful way?
32:05All of this stuff is a 100% necessary if you wanna be able to push apps into production.
32:11So in a bit, we're gonna go deeper into things like deployment and more security stuff and and all of that. But first, I wanna talk about something that seems suspiciously like it would be pretty straightforward.
32:23And then the moment you start getting, like, actual people into your application and you're trying to, like, update things, you have, like, a little bit of maybe of, like, a deer in headlights type of situation. And that topic is databases. So I'll come clean here.
32:36Like, databases is one of those things where it seems like it would be, like, just very straightforward, and there's not much really to do about it. You have tools like Supabase.
32:46You just go in there. You create the tables. You add stuff into the tables.
32:49Claude's doing all the work anyway. But then you come to a situation where you're trying to serve a lot of users and also try to make new things.
32:59And so this is one of those areas where you're either blissfully unaware of what some of the potential issues actually are, or you are aware of them, and it's one of the things that's stopping you from actually publishing or working on the app meaningfully because you're just afraid of that eventuality. So the things I'm gonna cover in in this specific section are things that are not immediately obvious to you because some things are.
33:20Right? Like, hey. I'm building a code.
33:21I need to understand my data models. Cloud Code's gonna help me make them anyway. I need to maybe understand the relationships between things.
33:28Like, that stuff I think is, like, a a little bit more straightforward. But there's a few things that I think if you haven't actually experienced them in the wild, they can maybe be, like, a little bit more intimidating or confusing. So the first thing up, and we're gonna talk about this more in the deployment section, is this concept of migrations.
33:45So anytime you need to, like, change the structure of your database, like renaming tables, creating new tables, modifying columns, like, whatever it might be, you really do need to run those through migration system.
34:01So the two paths that you have is number one, don't use a migration system and just, like, make a raw update to those tables, which I would not recommend. And number two is that you use a tool that can handle migrations for you. And so the best way to think about these things, they're kind of like version controlling for your database schema.
34:18Now the reason that this is valuable is that, again, it's like version control, which means if you make some sort of change that breaks something, you have the entire history of all of the changes that were made. You can technically, like, roll back migrations.
34:34You can roll forward into new migration, but it's just a much safer way of working with your actual database. Number two, the the way that you interact with the database itself has a big impact on performance.
34:46So when we think of performance, we're often, like, thinking of, like, just like the code itself or the app itself or, like, the front end. And so there's a few things here that are are really pretty important. Number one is indexing.
34:57So if you have information inside of your app that is constantly used, for example, to, like, look up information or sort by information, you should be creating indexes.
35:09And what that index does, if you were to think of it like a phone book, imagine if you had a phone book that was not organized alphabetically, and you had to go look for someone with a random name. That would suck.
35:19Right? You'd have to just page through everything until you find the name. An index to, like, continue on the analogy is like putting that that in order.
35:28Right? So if I needed to go look up a user named, you know, Sean, I could just flip to the s, flip to s e, flip to s e a, flip to s e a n, and then, like, find where it is.
35:38So that has, like, a huge impact on performance. If you've built apps and you haven't actually built indexes for things, this is, like, a a really easy thing to move forward and do. And, again, staying on the theme of, like, production vibe coding, this is not something that Clogcode is gonna do by itself, and it's something that'll have a huge impact on your application.
35:56The second big thing is this concept of n plus one queries. And, again, not something that Cloud Code will do properly out of the gate.
36:06An n plus one query is basically where based on how you've written the code, you're making, like, way too many round trips back to your database when in reality you didn't need to. A good analogy here, imagine you're at a restaurant, and the waiter comes up to the table to take everybody's orders. And he goes up to you and takes your order, and then runs it back to the kitchen and gives it to the chef, and then runs back to the table and goes to the second person and takes their order, and then runs it back to the chef, and just, like, continues that process.
36:33And then when he needs to take drink orders, he continues that entire process. Now you've taken, you know, ten, fifteen, 20 round trips to do something that you could have potentially just done in one query. Right?
36:44They could have just gotten everybody's order at once and then went to the chef to, like, give what the order is. Um, so this type of convention, honestly, is very common with language models and what they build out of the box, unfortunately, and that is, um, not something that you want to have happening.
37:01And then I'm gonna include this here again even though we talked about it a little bit in the authentication and authorization, but it's security related, so it's important. Row level security is very important.
37:14You need to be able to lock down your database tables so that people can only access the things that they are meant to access. So we're obviously gonna try to lock that down inside of the app logic itself, but we also want that locked down inside of the database.
37:29And so this actually leads us nicely into the next topic, which is security. Now I think out of, like, everything on this list, this is obviously, like, an incredibly important thing to get right. Luckily, there are a lot of really great open source tools that can help you out with this stuff, and I'll call out two of them.
37:46My favorite I'm surprised this doesn't have more stars. Wow.
37:49That's crazy. Deep sec. So deep sec is a security harness for your coding agent.
37:56It is not cheap. I will say that. So I would probably be running this via, like, a a clawed code license or codex license or whatever.
38:04But this thing honestly, like, impressed me with how it was able to find really obscure issues inside of my app or, like, seemingly obscure to me.
38:16That could be a big problem. So if you're looking for, like, a solid security scanning tool, I highly recommend this one. I've done videos on this that you can check out.
38:26I'll link them, uh, below. And if you want more of just, the open source skill side of things, there's this company called Trail of Bits that is a I think they're, like, a security research company, and they have, like, a dope, um, repo where they have tons of plug ins that help with all of this stuff.
38:43There's tons of skills for actually auditing your app for security.
38:47They have, like, auditing tools. They have, like, diff reviews that are specifically looking at security issues. They can look for, like, insecure defaults.
38:56They can run a static analysis. There's, like, tons of stuff this thing can do. So highly recommend this.
39:02This is not one of those areas where I would try to go out and, like, meta prompt a like, what should a security skill look like? And, like, that's what you use to check-in your app. Like, I would not do that.
39:12I would go out and use tools like this. But that being said, there's a few areas that I think are very important to think about.
39:20Um, obviously, we covered authentication and authorization already. The first thing that I will point out is there's this list that gets published. It's called the OWASP top 10, and this lists the top 10 security vulnerabilities that I think they come out, like, every four years with, like, an updated list that, like, you should be aware of.
39:38And there are scanners for this, like Trail of Bits, for example, looks at some of these things. There's, like, there's a ton of different implementations you can go out and Google where people are scanning for, uh, OWASP top 10 stuff. So you a 100% wanna have this as a checklist anytime you're working on, like, anything sensitive really at all.
39:58Uh, the next one is secrets management. And so the way generally that, like, your secrets should be managed, like, they should be in a secure environment. So for example, if you're, like, deploying something on Vercel, that is where you put your important secrets for the app deployment.
40:13Right? So you should have some sort of environment that is, like, locked down and secure that actually manages those secrets so that they're not, like, in the front end code.
40:23Right? And that's, like, a pretty obvious thing you'd think.
40:27But oddly enough, like, language models are still, like, kind of not always great with this stuff. They'll, like, on one hand, tell you that you should not ever paste them a a secret or an environment variable, and then they'll actually go in and read your environment fire file and then say, oops, I accidentally read it.
40:44You need to rotate all of your API keys. So some ways that you can, like, help solve some of these things, I think one of the easiest ones is you can put a pre commit scanner inside of your project. So what that means is, like, before you ever actually commit anything into git, you can have a pre commit that actually scans and makes sure you're not hard coding any secrets or important stuff into the commit itself.
41:06So the reason I include this one on the list is that it's just, like, a very easy to solve for type of thing that not a lot of people really think about, and then they, you know, commit it to GitHub, and then it's in the history, and then you could be boned in the future. And then the last thing that I've included on this, because I I do think this OWASP list plus those other tools that I mentioned, deep sec and trail of bits, they cover off on a lot of this stuff.
41:29But one thing that's, like, a little bit more counterintuitive or, like, not immediately apparent, and this is something that Vercel has caught a lot of for me, which is why I like to use it, is flaws in your business logic in your app can actually create huge security issues. And what that means is, like, you can go about with, like, clawed code building something in a way that it's not actually secure based on the way you've built it.
41:54So for example, you could have a situation inside of your app where you're not handling errors properly, and someone sends a bad request through to your back end, and it actually breaks, which is like, okay.
42:07Someone sent something through and broke something. But when it breaks, what does it allow people to do? That's not something a lot of people tend to think about.
42:16And if you don't have systems in place for that, you can have issues where it fails open. So what that means is, like, imagine somebody that's, like, on your free plan, and then something breaks and it fails open where they now have access to all the pro plan features. And they go in and start abusing the shit out of the API.
42:33The next thing you know, you've lost a bunch of money, and you're really sad. Something like that would obviously be a huge issue. And so having the language models think through these types of things, again, is something that is super important, and this is why I like to use security scanning tools that already note, look for these types of things.
42:50Uh, a good example of that inside of this trail of bits skill is they have this skill called sharp edges. And what this does is it identifies error prone APIs, dangerous configurations, and foot gun design.
43:04So it can actually help look for a lot of those things that we were just talking about. So, again, highly recommend you look at these two tools. If you're on, like, a Claude Max plan, I would recommend, like, at least once running through this deep sec thing.
43:16You don't have to run this on a daily basis. Think even, like, a once a month, like, gut check could be really valuable. And then, obviously, we have, like, the lighter version where we have these different skills inside of something like trail of bits.
43:27Alright. So, by the way, if you're still here, congratulations to you, because you have stayed for quite a bit of time.
43:31We got three more pieces that we are going to, uh, move through. The next one up is hosting. So you wanna choose a host that makes sense for you based on, like, two different dimensions, really.
43:42Number one, like, what is your actual experience level? And number two, what is the cost model of your app?
43:48So for example, if you were, like, not an engineer, I would highly recommend you just use a platform as a service. So something like Vercel, for example, where a lot of the, like, engineering y type stuff is handled for you, and they make it really easy for you to deploy your app and have it hosted in, a secure environment.
44:07That is, like, without a doubt, my number one recommendation. You do not need to go out and sign up for these host singer or, like, VPS over here and that thing over there, like an AWS deployed Google Cloud. Like, it'll be expensive when I it'll be cheaper when I'm at a million users.
44:22That's a recipe for disaster, man. Don't do it. So, again, the concrete recommendation here, picking a platform to actually host your app on that makes sense based on, like, you specifically, not what, like, some random person online is recommending you do.
44:36Number two, again, in the context of, like, these platforms that you choose, is making sure that you're separating your environments out.
44:44So for example, if we were to go, like, into Vercel, these are all, like, different versions of the app that I have been, uh, publishing here, and we can preview any of these deployments. So if I were to go back, like, here, for example, and click on preview deployment, if I were to now, like, go and sign in, like, this is not actually the live version of the app.
45:03Right? It's not the live version. This is, like, a preview of what would have been live at this point in time.
45:09And so the reason that this is really valuable is that you you really want to separate out your production environment, where, like, the main app lives there, and your ability to, like, stage changes and test those staged changes.
45:25So the way that, like, I personally do this, I I talked about it earlier in the video. I push everything onto my, uh, dev branch called develop. And once that happens and all of my my tests pass and everything, it builds the app in Vercel, and then it gives me this preview link.
45:42So once I have this preview link, I can go in. I can sign in. I can test all the new functionality of what I've been building.
45:48I can try to break things, make sure it works. And then only once I am cool with it, I can promote this to main.
45:55Right? I can make it like the live version of this thing. So And Vercel gives you these previews for free, though there's really, like, no reason in my opinion not to use them.
46:03But the second thing that I'll say is when you're thinking about a host, you need to, like, really think about how is this thing going to scale to the level you expect it to? How is it going to, like, handle itself under load? And how does that map to, like, the costs of that provider?
46:21Now the way that I like to recommend people do this, again, if you're not someone that knows how to go in and calculate, like, how many edge function calls you're gonna be having and, like, all of this other random shit, ask the language model to explore your code base, understand the different services and functionality as it pertains to, like, things that are gonna be relevant for the host, how many users you plan to scale to, and then actually breaking down, like, a profit margin, like, cost benefit analysis of the different hosts and making your decision from from there.
46:56So just to give you, like, context, inside of this app that I've been building, which is like it's a food tracking app, but it has, um, like, some agent functionality inside of it. I obviously needed to understand, like, okay.
47:07If I'm gonna be I'm gonna be running my my, uh, my database is gonna be hosted on, uh, Supabase. This is obviously gonna get pushed to the App Store.
47:16I'm using Supabase's edge functions for some of the language model calls and things like that. Based on the context of this app, the expected token usage of all the different features and functionality, and all of the different other costs.
47:29Like, what are we expecting that a profit margin is gonna be? And how does the Supabase in this case, as like the host for the database, how does that actually respond to the scale of of users?
47:41You need to, like, really understand that in order to make an informed decision about things so you don't run into a situation where you wake up and you have all of a sudden, like, a a $20,000 bill because you were trying to manage something on Google Cloud when in reality, you shouldn't have been doing that.
47:55So all of this talk of the host, how do we actually, like, manage the process of, okay, we've built all of this stuff. Now it needs to get to the host, though. Right?
48:03Like, we need to actually deploy it. So there's a few different topics here. I'm gonna cover off on some of the ones that I think are really important.
48:08Uh, the first is a continuous integration and deployment pipeline. So what this means is, like, as you're going through and you build you're building things on your computer, how are you pushing them to where your host is and having all of the checks and balances in place so that, like, functional stuff gets to where it needs to go.
48:27So with continuous integration and deployment, the easiest thing that you can do as a beginner or a vibe coder or whatever is use GitHub actions.
48:37So GitHub actions are gonna help you automate this entire process. So here's what that looks like like in practice. So step one is you create one of these GitHub workflows.
48:47Very easy to do. You can prompt the language model to do it. What does it do in this case?
48:51It runs four different things. Number one, it's going to lint the project. So it's gonna run like the p n p m lint command.
48:58It's gonna run the type check command. It's then gonna run our entire test suite. So all of the different tests that we have inside of our project, we're gonna see, like, did any of them fail?
49:09If it fails, then this thing isn't gonna deploy. And then last but not least, we can actually build the build the app itself after those tests have completed. And so what this means is, like, the way that this actually triggers is based on a pull request.
49:22So anytime I create a pull request inside of my app, all of this stuff is going to trigger. So if it triggers and everything runs and it's successful, that's cool. Then we get a preview link spun up for us inside of Vercel in this case, which we can go actually look at it and kind of test things out before we move forward.
49:42And then if it fails, cool. We can move in and fix, like, what it is specifically that was failing. But the whole point of this is that we're not just gonna push stuff all willy nilly into our main project and just, you know, let things break.
49:55Number two, and honestly, I think out of all the things in the video, oddly enough, this is one that I'm most excited about is maybe how you could say it. And the reason for that is that a lot of people, I think, when they are vibe coding something, you don't care if something breaks in your development environment. Right?
50:11Because it's like, hey. This thing broke. Oh, I didn't I didn't run a migration.
50:14I have to run a migration now. That's why the that's why the app was broken on my machine. Yeah.
50:19That that's not cool, though, when it's in, like, a user's hands. Like, you can't have that. And so the reason I bring this up is that there are actually, like, conventions to do migrations properly.
50:31I'm not gonna say this is the be all end all, but I am gonna explain to you guys what my process, uh, looks like. This isn't something I made up either, by the way. So I follow a system of running these migrations.
50:42And, again, in case you need a reminder, migrations mean we've updated our database schema, and, like, we've also updated some code most likely. And we're trying to play this dance of, like, making sure both of those things hit the code base and can work. If we push the database schema, but the code can't read it, app's gonna break.
51:00If we push the code, but the database schema is not there yet, app's gonna break. So the process that I follow here is a convention called expand, migrate, contract.
51:11So what does this mean? The first thing that you're gonna do is just add all the new columns. So whether you intend to, like, uh, change column names or, like, add in new columns to your app entirely or, like, whatever, cool.
51:23We're gonna expand the schema. We're just gonna add those things in, and we're gonna push them. Right?
51:28We're gonna run the migration. No code is trying to read it yet because we haven't pushed the code yet, and so it's fine. Right?
51:35It does it's there's nothing that's going to break there. We just expanded the things that are in there, but nothing's trying to read the expansion anyway, so doesn't matter. So once that is in place and all of the old stuff, by the way, is still left in place because the old code needs to still read the old schema, then we can actually attempt to migrate the sync.
51:55So what this means is, like, we can backfill data if we need to. Maybe we, like, re renamed columns, or we added a new column, but need to, like, move a bunch of data into it, or, like, whatever.
52:04We can backfill any of the data, and then we can also ship the code that now reads from the expanded schema.
52:14So all of the old schema's still there. It's just not telling it like, hey, you're not reading that anymore. Here's the new logic.
52:20Right? We built a new feature. Now you're reading like these database tables, these columns.
52:25But the old stuff, it's technically, it's still there. Again, it's just nothing is attempting to read it, so it's not a problem. Then once that's there and we've, like, tested the new app and everything is working, we can run this contract process, which is where we delete the old schema stuff that we don't need anymore.
52:43And so this solves the problem of, like, I have modifications to the database, but I also have code that needs to read the modifications, and I need to orchestrate the order in which those things land.
52:54Because if you don't, users are going to experience downtime and broken shit inside of your app. So the last thing in this, uh, list as far as, like, deployment goes is safe releases. And so if you were to think in the concept of, like, everything that we've talked about so far realistically in this in this video.
53:13We wanna make sure, ideally, in my opinion, that you're using a host that supports preview URLs. If you're not doing that, you have a a separate, like, staging environment or dev environment that you can test. You're pushing all of your changes to that safe space.
53:28You're testing everything there manually, and only once you are cool with it, you can promote that change up into, like, the main master branch or the production branch. In addition to that, we're doing this type of process down here to make sure we're running the database migrations before we push the code that actually needs those migrations to be in place.
53:51Alright. So we we've now, like, talked about a lot of stuff. Right?
53:54We talked about we're gonna build things properly, how we're gonna document it, how we're gonna version control it, how we're gonna test it, how we're gonna lock down the app, how we're gonna do the error handling when things break. We talked about, like, databases a bit, more of the security and locking things down, how to do the hosting, how to manage deployments the right way.
54:10But how do we know about everything that's actually happening? Right? Let's say that errors do pop up.
54:16How do we know? Let's say that we have we just pushed a new version of the app, and now we're getting elevated errors. How do we know?
54:23How do we know what version? How do we know what commit it's related to? So the last thing up on the list is this topic of observability.
54:30And so what this basically means is, like, how do you know what is actually happening inside of your app? And so there's a, like, a bunch of different products that do this.
54:41I'm showing you this AppSignal one, because I think their landing page is is awesome. It has, like, a ton of personality and, like, explains the features and the benefits, like, super well. There's also Sentry, which I've historically used mostly inside of my projects.
54:54But, basically, there's three different things here that we want to think about. Observability is all about, like, again, of all of this stuff that's happening, how do we know what is actually going on inside of the app? Like, we're not relying on a user to send us a screenshot, right, of their error, and that's how we know to go fix the thing.
55:11Like, how would you actually go about fixing problems and knowing that there are even problems to fix when your app is live and it's out there and it has real people? That's where we get into this concept of observability. So the first thing to set up are logs.
55:26So you wanna have, like, some centralized place, like, inside of Sentry, for example, where important events taking place, they don't have to just be errors. They can be, like, events that are important.
55:36They actually get sent to this system. And with that comes a request ID and maybe some information like the user's ID in your system so that you actually know, like, who is the person making the request and tracing or, like, knowing, like, what was it exactly that they were doing.
55:53So this is literally going to be kind of like you're doing a console dot log, but it's not that, and it actually gets sent off to a place like Sentry. So this is something you can use Sentry as, I believe, like, skills and MCP servers to help you set this stuff up inside of your app. Uh, the second thing is metrics.
56:09So we would wanna have a dashboard, for example, that we can see if all of a sudden let's say that we're using, uh, like, OpenAI for some sort of, like, AI feature that we have, and all of a sudden, you see, like, a huge spike in 500 errors, for example, inside of your app, and you can actually see that it is coming from the OpenAI integration.
56:31So something clearly is broken. Okay. Did I recently deploy a change that might have broken that thing?
56:37Is it a an error coming from OpenAI side? Is there something else going on?
56:42You need to be able to know. Right? So And metrics are really helpful because they allow us to track those sorts of things and create dashboards where we can see all of that stuff, be alerted when certain things are happening, like if errors pass a certain threshold, things like that.
56:58And then last but not least are traces. So when we talked about earlier in, like, error monitoring, when we're, like, handling those errors and catching those errors, we can send those errors to an app like Sentry so that, again, like, we know that it's happening.
57:11Right? We can see what the exact error was. We can see what the messages was.
57:16We have a trace of, like, how data was flowing through the app before that error, like, happened or, like, when that error started to happen. Like, what were all the different steps along the way? And, again, we can get alerts about it so that we know that we need to go in and fix something.
57:30So a concrete example of that might be like, hey. I wanna get alerted anytime there's a new unhandled error inside of the app. So, like, any sort of error that was, like, unexpected that got caught by the global handler, you would wanna get notified of that so that you can move in, see what happened, reach out to the customer if you need to, or ultimately just, like, patch the thing before it becomes, like, a huge, huge, huge issue.
57:53So there you have it, guys. Um, this, by the way, is not, like, the be all end all of any of these topics. They obviously go into, like, a lot more depth, like databases, for example.
58:02I mean, I I touched on, like, two to three things for each of these. There's dozens realistically for each of these, and they're and they're all important. But I think the big thing, if your struggle is, like, how do I have the confidence in taking something from my MVP stage into production?
58:18Again, we go back to that analogy of, like, the gate versus the net. So we wanna make sure that we have the gates in place so that we're building things in, like, a really intelligent way.
58:29And we wanna make sure we have nets in place so that we're catching any issues that happen, and we're able to actually resolve them. So if you were to look at a company, for example, like CalAI that recently got acquired for, like, a bunch of money, and it was a vibe coded app, like, what separates something like that outside of, like, the marketing and all that stuff?
58:46Like, what separates someone being able to do that and, like, get that many users from something that was vibe coded? It's that they're doing these types of things very systematically.
58:56They're building in a systematic way. They have really clear documentation. They're version controlling everything they do.
59:02They're building tests as they go. They're doing what they need to from a security perspective.
59:08They're handling errors so that they can catch things as they crop up and actually, like, address those issues. They're optimizing their database to, like, serve that type of, like, load of user. They're picking hosts that work with, like, their economic model and, like, how things need to work based on, like, their team's experience level, and they have really systematic processes for making sure they're deploying these things effectively in, like, a way that everything that you just spent a lot of time doing isn't gonna completely break and piss off all of your customers.
59:36Now, again, if you wanna see any of this, like, applied end to end, like, all of those topics, I have that inside of my paid community where we go through that in the phase one, like, getting to your MVP, and then the shipping what you've built section, for example, is all of those different topics that we just talked about, but with actual, like, applications and custom skills and the theory more of, like, the theory behind some of the things and, like, all of that type of stuff.
1:00:01But that being said, if you if you wanna see more content like this and maybe one of these categories you wanna see me go deeper into or you wanna see more hands on build or, like, any specific stuff, let me know in the comments below. Uh, make sure to subscribe so you see more of my videos in the future. But that's it for this video.
1:00:16I will see you in the next one.
The Hook

The bait, then the rug-pull.

Two kinds of vibe coders exist. One ships. The other becomes a meme. The difference, according to this breakdown, is not the AI model you pick or how fast you can prompt -- it is whether you have any of the eleven engineering disciplines that keep an app standing when real users show up.

Frameworks

Named ideas worth stealing.

02:21concept

Gate vs. Net

Gates are systems that prevent bad code or bad inputs from entering production. Nets catch and contain what slips through anyway. Every one of the 11 topics maps to one or the other.

Steal forframing any engineering process conversation or production readiness review
03:14model

OpenSpec workflow

  1. Generate proposal
  2. Generate specs
  3. Generate design
  4. Generate tasks
  5. Implement
  6. Verify

Actions-not-phases SDD framework. Each step has a defined output. The changes directory becomes living documentation of every decision and its rationale.

Steal forstructuring AI-assisted feature development from idea to shipped code
49:54model

Expand-Migrate-Contract (EMC)

  1. Expand (add new columns/tables, push migration)
  2. Migrate (backfill data, ship code reading new schema)
  3. Contract (delete old schema)

A three-phase database migration convention that ensures code and schema changes never land out of order, preventing user-facing downtime during deployments.

Steal forany deployment where database schema changes accompany code changes
18:32model

Red-Green-Refactor

  1. Write a failing test (red)
  2. Write minimum code to make it pass (green)
  3. Refactor to optimal implementation (still green)

TDD cycle that drives agents to build functionality against pre-defined acceptance criteria rather than building first and testing after.

Steal forany Claude Code or Cursor task where you want verifiable, regression-safe output
CTA Breakdown

How they asked for the click.

VERBAL ASK
00:30product
this video is sponsored by me -- I go through all of this stuff in detail in my paid community

Self-referential joke lands the pitch early and lightly, then repeated at the end with specific content details (phase one: getting to MVP, shipping section). Low pressure, high specificity.

Storyboard

Visual structure at a glance.

cold open
hookcold open00:00
SDD intro
valueSDD intro03:14
OpenSpec docs
valueOpenSpec docs05:39
documentation
valuedocumentation06:50
version control
valueversion control14:42
TDD cycle
valueTDD cycle21:54
error handling
valueerror handling26:33
indexing analogy
valueindexing analogy35:33
DeepSec
valueDeepSec38:49
hosting
valuehosting46:03
EMC migrations
valueEMC migrations49:54
full checklist
valuefull checklist53:54
full checklist recap
ctafull checklist recap59:11
Frame Gallery

Visual moments.

Chat about this