Guide

Vibe coded apps never ship because the deploy gauntlet is a separate skill set, and nobody crosses it on willpower.

The prompt loop is fast and joyful. The deploy loop is slow and full of tiny decisions about tools you have not used before. That is not a discipline problem. That is the gap between "preview works" and "URL someone can open," and most builders quit somewhere inside it.

M
Matthew Diakonov
6 min

Direct answer (verified 2026-05-02)

Vibe coded apps never ship for one structural reason: between "preview works on my machine" and "URL someone can use" sit five different tools (hosting account, Git, build config, env vars, DNS), each one with its own learning curve, none of them part of the prompt loop the builder just enjoyed. The fix is not motivation; it is removing the gauntlet. mk0r does it by serving every preview at <vmId>.mk0r.com from the second the first prompt finishes (proxy at src/proxy.ts, 53 lines). Trade: the URL has a one hour TTL, set as E2B_TIMEOUT_MS = 3_600_000 at src/core/e2b.ts line 33.

The five-step gauntlet, named honestly

Pull up the last five vibe coded projects you abandoned. Ask which step they died on. The answers cluster, badly. The reason they cluster is that the gauntlet is the same shape on every platform, and the second or third step is always the cliff. Here is the actual sequence.

1

Sign up for a hosting platform

Pick one of five reasonable options, none of which you have used before. Decide whether the free tier is good enough. Read three different pages of pricing fine print. Verify your email. Set up two-factor.

2

Connect a Git repository

Realize you never initialized git on the prototype. Init it. Decide whether you want this on GitHub or GitLab. Create a new repo. Push. Authorize the hosting platform to read your repo. Pick the right branch.

3

Configure the build

Find out the hosting platform guessed the framework wrong. Override the build command. Set the output directory. Watch the first deploy fail because the Node version on the platform is older than the one you used locally. Pin it.

4

Add environment variables

Open every file in the project that calls process.env. Make a list. Go to the hosting dashboard. Add each one, hoping you remember which value goes with which key. Trigger a redeploy. The first redeploy fails because one of them has a trailing newline you cannot see.

5

Point a domain (optional but the whole point)

Buy a domain at a registrar. Find the DNS settings. Add an A record or a CNAME (you have to look up which). Wait for propagation. Add the domain in the hosting dashboard. Wait for SSL provisioning. Open the URL. Get a 'site not found' page. Wait some more.

Read that list and notice what is not on it: writing code. The hard part of shipping a vibe coded app is not the part you were enjoying. It is five different settings dashboards, in series, each one with a small surprise. A person who has done this twenty times calls it twenty minutes. A person who has done it twice calls it a Saturday. Most vibe coded projects belong to people who have done it twice.

What changes when the gauntlet is gone

The thing worth saying out loud is that this gap is not a law of physics. It exists because the tools that generate code and the tools that host code grew up separately. A tool that does both can collapse the gap. Below is the same project, on the gauntlet vs. without it.

Same project, two paths to a shareable URL

You finish the prompt loop at hour two. You pick a host. You sign up. You push to GitHub. You wire the build. You hit a Node version mismatch. You fix it. You add env vars. One has a hidden trailing newline. You debug. You buy a domain. You wait for DNS. You wait for SSL. It is now Sunday night. You have not shown anyone.

  • Five different dashboards to learn
  • Two of the five steps fail on first try
  • Total wall clock: a weekend, on a good run
  • Most projects die inside this section

The honest part: where mk0r still hands off to a human

The preview URL is the win. A custom domain like myapp.com is the part the codebase does not yet automate end-to-end. If you read src/core/e2b.ts at line 1862, you will find startDomainVerificationthrows the literal string "Domain publishing is not yet supported on the E2B backend." That is on purpose; it would be worse to fake the feature than to be honest about it.

What works instead lives at src/app/api/publish/route.ts line 85: you submit the domain through the UI, the server sends an email to NOTIFY_TO = 'i@m13v.com' (line 11) with your session details, and a human wires the domain. It is slower than self-serve. It is also strictly faster than the version where the project never gets that far.

What actually counts as "shipped"

Strip the word back to what you can verify. Here is the test that decides whether something shipped, and it is the same five conditions whether you used a hosting platform or not.

The shipped test

  • There is a URL.
  • The URL has https.
  • Someone who is not you can open it on their phone.
  • The first screen renders without you explaining anything first.
  • Tapping one thing produces a visible reaction.

If the answer is no on any line, you have not shipped, and the reason almost always lives inside the gauntlet. If the answer is yes on every line, you shipped, even if the URL looks like a subdomain of someone else's service. The next worry (auth, payments, retention, custom domains) is real, but it is the next one. The first one is whether you have a URL at all.

Frequently asked questions

What does 'never ship' actually mean here?

Three states qualify: a localhost link the builder cannot share with anyone else, a working preview inside one specific tool that nobody outside it can open, and a stalled half-deployed thing on a hosting account where the env vars never got set. None of the three are 'live URL someone can use.' All three feel close, which is the reason the project sits in that state for weeks. The builder keeps thinking the next 30 minutes of work will close the gap. The 30 minutes never finishes because the gap is not 30 minutes long.

Is the problem really not psychology?

Psychology is downstream. People do not abandon things they enjoy and that work. They abandon things where the next concrete step is unclear and probably an hour of reading on a topic they did not sign up for. Vibe coding's appeal is that the prompt loop is fast, joyful, and the feedback is instant. The deploy loop is none of those things. It is slow, requires reading documentation, and the feedback is a 502 page with no useful error. The motivational gap between those two loops is real, but the cause is structural: the tools were designed by different people for different audiences.

Why do tutorials make this look easier than it is?

Because tutorials hide the part where you have to make a decision. A tutorial says 'now run vercel deploy.' It does not show you the moment where you stare at the dashboard with three projects in it, two of which you forgot about, and try to remember which Git account you were logged in as. The deploy gauntlet is full of tiny decisions like that. Each one takes thirty seconds for someone who has done it a hundred times and ten minutes for someone who has not, plus context-switching cost back to whatever you were trying to ship. By step three you are no longer building, you are doing IT.

How is mk0r different from 'just use Vercel'?

Vercel is excellent at the deploy step if you have already done the four steps before it. mk0r removes the four steps. There is no signup at the start. The preview that streams while the model generates is already at a public URL on the open internet, of the shape <code>&lt;vmId&gt;.mk0r.com</code>. The proxy that makes that work lives at src/proxy.ts and it is 53 lines. There is nothing to configure, no DNS to point, no SSL to wait for. The trade is honest: that URL has a one hour TTL, set as <code>E2B_TIMEOUT_MS = 3_600_000</code> at src/core/e2b.ts line 33. If you want it to live longer than an hour you need to act, but the act is small.

What about a real custom domain like myapp.com?

That is the part mk0r does not pretend to fully automate yet. The codebase has a function <code>startDomainVerification</code> at src/core/e2b.ts line 1862 that throws the literal string 'Domain publishing is not yet supported on the E2B backend.' What does work is a notification flow at src/app/api/publish/route.ts line 85: you submit a domain through the UI, the server emails the operator at <code>NOTIFY_TO = 'i@m13v.com'</code> with your session details, and a human wires the domain. Slow but honest. The point is that you do not get blocked at this step thinking you have to figure DNS out yourself. Either the preview URL is enough (it usually is, for a demo), or someone with practice does the last step for you.

Won't the apps still die because they have no auth or database?

Often, yes. That is a different wall and there are dedicated guides for it: the auth wall and the cross-file state wall both have separate pages on this site. But the never-ship problem is the prior one. Most apps do not even reach the point of needing auth because they never reach the point of having a URL someone outside the builder can open. Solving the deploy gauntlet does not solve everything. It just removes the first wall, so the next wall becomes a real choice instead of an abstract one.

Is a preview URL really 'shipping'?

It depends on what you wanted to ship. For a demo to a friend, an investor, a stranger on X, a hiring manager, or a customer-discovery interview, a public reachable URL is shipping. For a paid product with retained users it is not. Be honest about which one you are doing. Most vibe-coded projects that 'never ship' were the first kind in disguise: the goal was to show one person, not to run a business. Treating them as the second kind is what makes them die unstarted.

What is the smallest test of 'shipped'?

Send the URL to one person you do not live with, in a chat thread you cannot delete. They open it on their phone. It loads. They tap one thing. The screen reacts. That is the test. If your project cannot pass that test today, you have not shipped. If it can, the rest is iteration, and iteration is the part you were already enjoying.

Want help getting a vibe coded prototype to a real URL?

Twenty minutes with the team. We will look at where your project sits in the gauntlet and what the smallest move is to get it past.

mk0r.AI app builder
© 2026 mk0r. All rights reserved.