Field guide

Where vibe coding stops carrying you, in three named seams

Vibe coding tools carry you through a surprisingly long opening stretch. The cliff is real, though. In mk0r the cliff is not one wall, it is three seams, each named in source. Knowing exactly where each one lives turns the cliff into a small number of predictable handoffs.

M
Matthew Diakonov
6 min
Direct answer (verified 2026-04-30)

mk0r carries you through anonymous boot, automatic backend provisioning, and per-turn iteration. It stops carrying at three specific seams: the moment you want the work attached to an identity (handled by requireAuth at src/components/auth-provider.tsx line 172), the moment you want a real custom domain instead of the sandbox preview URL (handled by an email-the-human handler at src/app/api/publish/route.ts line 101), and the one-hour sandbox lifecycle (E2B_TIMEOUT_MS at src/core/e2b.ts line 33). Each seam has a right move on your end. None of them lose committed work.

The carry, then the seam

A typical session in mk0r runs through this sequence. Steps one through five are fully automated. Step six is the first seam, where identity gets attached. Step seven is the second seam, where a human reads an email. Step eight is the third seam, where the one-hour sandbox lifecycle starts mattering.

A session, with the seams marked

Youmk0rSandboxOperatoropen mk0r.comanonymous Firebase uid + sandbox bootfirst promptPromise.allSettled: Neon, Resend, GitHublive preview at <vmId>.mk0r.comclick Publish (seam 1: requireAuth fires)seam 2: sendEmail to operatorseam 3: 1h timeout, auto-pause

Red arrows mark the seams. Green arrows are the carry. The first five steps happen with no signup form, no env var paste, and no deploy script.

Seam 1 of 3: identity, at line 172

The first seam is the smallest one and the easiest to miss. On first paint, the AuthProvider calls Firebase signInAnonymously inside onAuthStateChanged. By the time the landing page is interactive you already have a real Firebase uid that owns an app_sessions document in Firestore. You can prompt, iterate, refresh the tab, come back, and keep going with no form fields ever appearing. That is most of the session.

The seam shows up the first time you click Publish, switch the underlying model away from the default Haiku, or do anything else the product treats as monetized. The function in the way is small:

src/components/auth-provider.tsx

Read it as a queue. If you are signed in with Google, the action runs immediately. If you are still anonymous, the action gets parked in a ref, the sign-in modal opens, and the queued action fires the moment the Google popup resolves. There is no second click. No form to refill. The carry resumes on the same prompt the seam interrupted.

What to do at seam 1

Sign in with Google once when the modal appears. Same Firebase uid, the anonymous app_sessions document is migrated, every preview you built so far is now attached to your account.

Seam 2 of 3: deploy, at line 101

The second seam is the most surprising one. Most app builders try to make deploy feel like a one-click action that lights up a real domain in 30 seconds. mk0r is honest about what is happening underneath. The deploy action sends an email.

src/app/api/publish/route.ts

A real person reads that email and finishes the domain mapping against the static load balancer IP. Until that point you have a working app at https://<vmId>.mk0r.com, served straight from your sandbox via the per-VM preview proxy. The wildcard A record *.mk0r.com points at the load balancer, so every running sandbox gets a real subdomain for free. Custom domains are the explicit handoff.

The honest framing matters. Pretending custom-domain deploy is fully automated would mean shipping a path through arbitrary DNS providers, certificate authorities, and edge configurations that no AI agent should run unattended on behalf of a user it just met. The email is the seam. The right move on your end is to type the domain you actually want, send the request, and expect a real human to respond.

What to do at seam 2

Use the preview subdomain for the entire prototype phase, send the email when you have a real domain you want pointed at the app, and treat the response as a synchronous step rather than a background job.

Seam 3 of 3: the one-hour sandbox lifecycle

The third seam is a single constant. Every E2B sandbox in mk0r is created with a one-hour timeout. The exact value lives at the top of e2b.ts:

const E2B_TIMEOUT_MS = 3_600_000; // 1 hour
src/core/e2b.ts line 33

The sandbox is created with lifecycle: { onTimeout: 'pause', autoResume: true } at line 309, so the hour elapsing is not a death sentence; it is a pause. The next call to Sandbox.connect resumes from the paused state and refreshes the window via setTimeout. There is also a shorter clock you can hit on a fresh prompt: the warm pool entries are evicted after POOL_MAX_AGE_MS at line 1896.

0s
E2B_TIMEOUT_MS in seconds. After this, sandbox auto-pauses.
0 min
POOL_MAX_AGE_MS. Warm pool entries past this age are evicted.
0
Committed turns lost when a sandbox is reaped. State restores from Firestore.

What you actually feel in practice: short sessions never notice anything. Long single-session marathons get one brief reconnect pause as the paused sandbox resumes. Sessions that go truly cold for hours can be reaped, in which case the next prompt restores the project to the head SHA from Firestore and you keep going. None of those failure modes lose committed work, but they are the moments the loop stops feeling instantaneous.

What to do at seam 3

Trust the per-turn commits. If a long pause happens after a long idle, the next prompt either auto-resumes the paused sandbox or restores from the last committed SHA. Refresh the tab if you want to be sure of the connection state.

The carry vs the seam, side by side

The asymmetry between the long carry and the small seams is the easiest way to understand mk0r. The carry is automated fan-out: a Promise.allSettled on four upstream services that gets your app a real Postgres, a real audience, a real GitHub repo, and a PostHog appId before the agent writes a single line. The seam, by contrast, is one email and a human.

Provisioning runs unattended. Publishing does not.

// src/core/service-provisioning.ts
const settled = await Promise.allSettled([
  provisionPostHog(slug),
  provisionResend(slug),
  provisionNeon(slug),
  provisionGitHub(slug),
]);
// All four upstream accounts created. No signup form
// for the user. /app/.env written into the sandbox.
// Agent boots with real DB, real audience, real repo.
-44% lines on each side

Both files are short. The difference is what each one does. The left file runs without you ever touching it, and produces real third-party resources. The right file is gated by requireAuth and ends in a person's inbox.

Where mk0r genuinely cannot carry you

The three seams above are operational handoffs. The product qualification list calls out a different category of limit: app shapes that no current AI app builder will carry through the full production version, regardless of seam handling. Those are worth naming honestly because the wall-vs-seam framing only works for ideas that fit the shape mk0r can build at all.

  • Native iOS or Android. mk0r generates mobile-first HTML, CSS, and JS, not Swift, Kotlin, or React Native. The carry is the mobile web prototype, and that is the carry, not the production ship.
  • Real-time multi-user state. The default Postgres provisioning does not stand in for a Yjs or Liveblocks layer. If your idea depends on shared cursors or live state across clients, the generated app will not get you there.
  • Production-grade auth, payments, and persistence as defaults. Anonymous Firebase auth, an empty Neon database, and a Resend audience are scaffolding, not the finished access control story for a real customer-facing app.

For ideas that fit inside a one-page mobile app with a small Postgres for persistence and a Resend audience for email, the carry stretches surprisingly far. The three seams are the only ones you actually have to notice during the carry.

Frequently asked questions

What does 'where vibe coding stops carrying' actually mean?

It is the moment in a session when the AI app builder can no longer move you forward by itself. You finish a prompt, the model returns a working preview, and the next thing you want is something the tool cannot autocomplete: a real account attached to your work, a custom domain instead of a sandbox URL, or just continuing past the silent point where the sandbox times out. People describe this as a wall, but in any specific tool it is a small number of named seams. In mk0r there are three, each is in source, each behaves differently, and each has a different right move on the user side.

Where is the auth seam in mk0r and what triggers it?

It is the requireAuth function at src/components/auth-provider.tsx line 172. The function takes any action callback. If the current Firebase user exists and is not anonymous, it runs the action immediately. Otherwise it parks the action in a ref, sets showSignIn to true, and the modal appears. The actions that go through requireAuth are the ones that touch persistent identity: switching the underlying model from the default Haiku, clicking Publish, and a few other gated UI surfaces. Anonymous Firebase sign-in already happened on first paint, so up to that line you can prompt, watch the app build, iterate, refresh the tab, come back, and keep iterating without a single form field. The seam is exactly where ownership starts mattering. Sign in with Google once, the action you queued runs immediately, and the same session continues.

Where is the publish seam, and is it really an email to a human?

Yes, today it is. The handler is at src/app/api/publish/route.ts line 101. The deploy action calls sendEmail({ to: 'i@m13v.com', subject: '[mk0r] Deploy request: <domain>' }) with the requested domain, the project name, the session key, the VM ID, the user email, and the live preview URL. A real person reads that email and finishes the domain mapping. Until that point you have a working app at https://<vmId>.mk0r.com, served straight from your sandbox. After that point you have your own domain in front of the same app. The honest framing: the iteration loop is fully automated, the publish-to-real-domain step is human-in-loop on purpose. If you came expecting a one-click deploy that just works for any DNS configuration, this is the seam, and it is the right time to send the email.

What is the one-hour sandbox seam and how does it actually behave?

E2B_TIMEOUT_MS at src/core/e2b.ts line 33 is set to 3,600,000 milliseconds, which is one hour. Sandboxes are created with lifecycle: { onTimeout: 'pause', autoResume: true } at line 309, so when the hour elapses the sandbox pauses rather than dying. Coming back to the tab calls Sandbox.connect, which auto-resumes the paused sandbox and refreshes the timeout window via setTimeout. There is also a warm pool with POOL_MAX_AGE_MS = 45 minutes (line 1896) where unused pool entries are evicted, so cold starts after long idle gaps go through createSandbox again. The seam, in practice: short sessions never notice the timeout, long single-session marathons hit a brief reconnect pause, and sessions that go truly cold can be reaped, at which point the project is restored from the head SHA in Firestore on the next prompt. None of those failure modes lose committed work, but they are the moments where the tool stops feeling instantaneous.

What does mk0r still carry you through that competing tools do not?

The first-prompt fan-out is the unusual part. provisionServices in src/core/service-provisioning.ts uses Promise.allSettled to fire three external API calls in parallel before the agent boots: a Neon Postgres 17 project (constants at lines 47 to 49), a Resend audience plus a sending-only restricted API key (line 45), and a private GitHub repo at m13v/mk0r-{slug} (lines 51 to 52). PostHog runs synchronously and gives the app its own appId. A /app/.env file is written into the sandbox before the agent runs anything. None of those values were ever pasted by you, and none of them require a separate signup with the upstream vendors. Then the iteration loop itself is the second long carry: a persistent ACP session per sandbox (reuse logic around src/core/e2b.ts line 909), per-turn git commits via commitTurn (line 1635), and byte-exact undo via undoTurn (line 1731). That is the long flat stretch where you can stay in the chat without thinking about infrastructure.

Should I treat mk0r as a permanent home for an app or as a first draft?

Honest answer: first draft, plus iteration runway. The product description says it generates full HTML, CSS, and JS mobile apps from a single sentence, and the qualification list is explicit that the right user is fine with a disposable first draft before investing engineering time. The carry is real but bounded, and the bound is precisely the three seams above. If your app idea would need native iOS or Android, real-time multi-user state, or backend logic that generated HTML and JS cannot cover, mk0r will carry you through the prototype and not the production version. If your idea fits inside a one-page mobile app with a small Postgres for persistence and a Resend audience for email, the carry can stretch surprisingly far before any of the three seams force a decision.

What is the right move at each seam?

At the auth seam, sign in once with Google when you want to keep the work attached to an identity. The queued action runs immediately, no second click. At the publish seam, type the domain you actually want, send the request, and expect a real human to respond rather than a status spinner. At the sandbox seam, do not panic when a long pause happens after a long idle, the next prompt either auto-resumes the paused sandbox or restores from the last committed SHA. And the meta move at all three seams is the same: read the file path. Knowing requireAuth lives at line 172 of auth-provider, knowing the publish handler lives at line 101 of route.ts, knowing the timeout constant lives at line 33 of e2b.ts, makes each seam predictable rather than mysterious.

Want a walkthrough of the seams in your own session?

Open mk0r.com, type a prompt, and we can step through where the carry ends in real time.

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