Your vibe-coded app got serious faster than expected
The dangerous part was not that AI wrote code quickly. It was how easy it became to forget which shortcuts were only safe while the app was still a toy.
I did the thing everyone says they are doing now. I vibe-coded.
Not in the fake LinkedIn way where someone says they built a SaaS in eleven minutes and then quietly spends three days fixing the login page. I mean the normal version. I had an idea. I opened an AI coding tool. I described what I wanted. It started building. I kept nudging it along. A button here. A route there. A little database change. A "just make this work for now" moment that felt harmless at the time.
And then the app worked. Which was both wonderful and slightly terrifying. Because there is a specific moment in AI-assisted development where your brain shifts from "wow, this is amazing" to "wait, this thing might actually be real software now." That is the moment this post is about.
i.The magic phase is real
At first, vibe coding feels like cheating in the best possible way. You describe the idea, the agent builds the scaffolding, you ask for polish, it adds the polish, you ask for the bug fix, it confidently creates three new bugs while fixing the first one. Very normal. Very artisanal.
But the speed is intoxicating. The distance between "I have an idea" and "I can click around a working version" gets compressed so much that your judgment can lag behind the output.
That was the first thing I noticed. The AI did not just help me write code faster. It helped me postpone asking boring adult questions.
- Should this route be public?
- Is this still demo data, or did it quietly become real data?
- Did we hardcode anything weird?
- Is this temporary schema now permanent?
- Did I accept this dependency because it made sense, or because I was tired?
- Did the agent already warn me about this in some buried chat?
- Where did that warning go?
The agent didn't need a bigger prompt. It needed a better memory of what hurt last time.
That last question was the one that stuck. Because the app had memory-shaped problems. Not database memory. Not auth memory. Human memory. Project memory. The kind of memory that knows we only did it this way because we were trying to get a demo working. The kind that says this needs a security pass before anyone else touches it. The kind that remembers do not regenerate this component from scratch because the first version looked right but broke the edge case.
The most dangerous part of vibe coding is not always the code the AI writes. Sometimes it is the context the human forgets.
ii.What happens when it works
This is not just a personal problem. A year ago the interesting question was "can AI build the thing?" Now the more useful question is "what happens when the thing works?"
Because working is not the same as safe. Working is not the same as maintainable. Working is not the same as production-ready. And working is definitely not the same as "I understand every decision that led to this."
That drift is the scary part. A local tool becomes a hosted app. A demo gets shared with a few people. A few people become users. A harmless table starts holding data you care about. The project goes from "look what I made" to "oh no, I am responsible for this now."
“A lot of security is contextual.”
Jack Cable
Security researcher
The internet is noticing“Speed without control is a liability, not an advantage.”
Manav Khurana
GitLab
There's also a clean line you cross without noticing: the moment your app touches someone else's personal data. Before that, a bug is your problem. After that, a bug is their problem. It becomes a fundamentally different kind of responsibility even if the code did not change at all.
AI code is moving faster than control.
Generation got faster. Accountability did not automatically come along for the ride.
Source: GitLab research. Manav Khurana put the problem cleanly: speed without control is "a liability, not an advantage."
iii.The surprise was not insecure code
That would be too easy. There are already plenty of posts saying AI-generated code can be insecure. And yes, that matters. But my more interesting realization was different: I had trouble reconstructing the story of the app.
Not the code. The story.
- Why did we add this table?
- Why did we skip this check?
- Why did the agent choose this dependency?
- What was the weird bug in the first implementation?
- Which files were fragile?
- Which route was temporary?
- What did I tell the agent never to do again?
That stuff matters because software is not just code. Software is code plus decisions. Code plus tradeoffs. Code plus scars. Code plus "please do not touch this unless you enjoy sadness." And with AI coding, a lot of those decisions happen inside chat sessions that are easy to lose, hard to search, and weirdly detached from the actual project.
iii.The maturity curve has a dark sense of humor
Every vibe-coded app seems to go through the same emotional arc.
The Vibe-Coded App Maturity Curve
Fun -> consequencesThe demo loads.
Shortcuts affect other people.
Fake data becomes real stakes.
Review and auth suddenly matter.
Fragile fixes become tribal knowledge.
Warnings need somewhere durable to live.
iv.The actual problem was forgotten risk
I started noticing a pattern. The app did not need me to remember everything. It needed me to remember the things that would hurt later. That is a much smaller and more useful category.
Things like this feature was built quickly for a demo. This endpoint should not be exposed publicly yet. This data model works for one user but probably not for teams. This auth path needs another review. This dependency was accepted quickly and should be checked later. This whole area needs a human review before launch.
That is not documentation exactly. It is not a ticket exactly. It is not a code comment exactly. It is more like a project conscience. A small voice that says: hey, before you ship this, you should remember what happened here.
Vibe coding creates software faster than it creates shared understanding.
v.Where memory clicked
This is where Empirical started to make more sense to me in a new way. I was not trying to create some grand AI memory architecture. I was just tired of losing the important little warnings. So I started saving them.
Not entire transcripts. Not every thought. Not a giant context dump. Just the stuff I knew future-me or future-agent would need.
The agent asks what next
I spend ten minutes re-explaining what the app is, what we already tried, what broke, what I am nervous about, and what should not be touched.
The session starts with risk
Known project risks, launch blockers, previous failed approaches, important UI decisions, security-sensitive areas, and unresolved technical debt are already there.
I started saving these warnings in Empirical because I did not want them buried in a chat transcript.
Empirical was not useful because it remembered everything. It was useful because it gave the project a place to remember what was easy to forget. That does not make the agent perfect. It just makes the conversation less amnesiac. Which, frankly, is a low bar. But a surprisingly useful one.
| Thing | Where it belongs |
|---|---|
| How to run the app | README |
| Current task | Prompt |
| Permanent repo rules | AGENTS.md / project instructions |
| Product decisions | Docs or issues |
| Repeated agent mistakes | Memory |
| “Don't forget this before launch” warnings | Memory |
| Security concerns tied to past decisions | Memory |
| Temporary implementation shortcuts | Memory or issue tracker |
| Human-facing explanations | Docs |
| “I was tired and said yes to this” | Therapy, then memory |
vi.Security is contextual
The security lesson here is not that AI-generated code is automatically bad. That is too easy, and not very useful.
The better lesson is that AI makes it extremely easy to create working software before you have created the habits that normally surround working software: review, threat modeling, access control, traceability, test coverage, deployment hygiene, ownership, and remembering why something was built the way it was.
Working code answers can this run? It does not answer should this ship?
That is why Cable's framing matters. The same code can be fine for a local prototype and reckless for a public app. The same shortcut can be harmless with fake data and dangerous with user data. The same route can be tolerable behind admin auth and terrifying on the open internet wearing a little hello-world hat.
The question is not just "is this code secure?" The better question is "secure for what use, with what data, under what assumptions?" Those assumptions need somewhere to live.
There is a very specific flavor of shame that comes from finding your own TODO comment in code the AI wrote after you asked it to clean things up. It is like getting haunted by a ghost you personally hired. Nothing humbles a person like realizing the warning label was written by past-you, ignored by current-you, and about to be rediscovered by future-you during a production incident.
This is why memory started to feel less like a feature and more like a seatbelt. Not exciting. Not flashy. But you notice when it is missing.
A transcript remembers what was said. A scar remembers what it cost.
| Layer | Question it answers |
|---|---|
| Current prompt | What am I doing right now? |
| Project memory | What should not be forgotten? |
| Docs / repo / issues | What is the durable source of truth? |
Save the scar, not the transcript. Save the assumption, not the entire discussion. Save the launch warning. Save the repeated correction. Save the boundary. If you have told the AI the same thing twice, it probably belongs in memory.
vii.The boring practical conclusion
I am still bullish on vibe coding. I love how fast it turns an idea into something you can click. But I am less casual about it now, because the more useful the app becomes, the more expensive forgotten context gets.
When an AI-generated app is just a sketch, forgetting is annoying. When it has users, forgetting is risk. When it has data, forgetting is liability. When it has a future, forgetting becomes debt.
Vibe coding did not just make me faster. It made memory more important. Not memory as in save every chat. Memory as in what did we learn that we will regret losing?
That is where Empirical clicked for me: not as a magic fix, not as a replacement for security review, not as an excuse to ship sloppy code, just as a place for the project to remember the warnings, decisions, scars, and assumptions that usually disappear between sessions.
Vibe coding gave me speed. Memory gave me a little bit of judgment back.
Give the project a place to remember.
Empirical holds the contextual decisions, launch-day warnings, and the "this is load-bearing, don't touch it" notes so the next session sees the scar before it reopens the wound.