AI App Maker, No Signup: how mk0r skips the form without faking the auth
Saying no signup is easy. Most tools that advertise it either pop a form the second you press Generate, or they keep your work in browser memory so a refresh wipes it. mk0r took a different route: give every visitor a real backend identity on first paint, warm a VM before they type, and migrate ownership cleanly if they ever decide to sign in.
The trick is not skipping auth, it is making auth invisible
When you load mk0r, the auth provider has already run. Inside src/components/auth-provider.tsx there is an onAuthStateChanged listener that, the moment Firebase reports no current user, calls signInAnonymously(auth) and waits for the next state event. By the time the textarea renders, you are a real Firebase user. You just do not know it.
That distinction matters. A real user has a stable UID and a real ID token, so every API call we make on your behalf can be authenticated server-side, rate-limited the same way a signed-in user is, and attached to documents in Firestore that survive a page refresh. None of that is true for the typical no-signup builder, where the only thing carrying state is whatever you stuffed into window.localStorage.
Two identifiers, one frictionless front door
mk0r actually issues two identifiers on first paint. The first is the Firebase anonymous UID we just discussed. The second is a session key generated by crypto.randomUUID() and written to localStorage under the key mk0r_session_key. That session key is what binds your VM to your tab.
The Firebase UID owns Firestore documents. The session key owns VM lifecycle. Together they are everything an account would have given you, minus the form.
Identity flow on first paint
The VM is already warming before you type
Most builders that say no signup wait until you press Generate before they touch any backend. That is when their cold start shows. mk0r does the opposite. The home page mount fires a POST to /api/vm/prewarm as a fire-and-forget side effect, which calls topupPool() in src/core/vm.ts and ensures an E2B sandbox is on its way before you have decided what to build.
Because the prewarm route accepts requests without any user token in this configuration, an anonymous visitor triggers the same warming behavior a signed-in user would. The pool fills, the VM template (mk0r-app-builder, ID 2yi5lxazr1abcs2ew6h8 in production) is ready, and the only thing left waiting is your keystroke.
What lives in the ID token (this is the part nobody else has)
Every authenticated request to the mk0r backend carries a Firebase ID token. The server verifies it in src/lib/auth-server.ts, and the decoded payload includes a field most no-signup builders never get to see, because they never minted a token in the first place.
Because we know whether the caller is anonymous, we can let an anonymous visitor build, save, and revisit projects, while still gating things that genuinely need accountability (publishing to a custom subdomain, billing, OAuth credential reuse) behind a sign-in upgrade.
What it costs you to skip the form (in numbers)
What happens the first time you actually sign in
Eventually some users want a real account, usually because they want to publish, share between devices, or pay. The interesting part is what happens to all the work they did before they signed in. mk0r does not throw it away and it does not ask you to re-import anything.
When you click Sign in with Google, the client first tries linkWithPopup. That attaches the Google credential to your existing anonymous user, which means the UID does not change at all and every existing document still references the right owner. If linking fails because the Google account already has a different UID (for example, you signed in here from another browser before), the client falls back to /api/auth/migrate. That route runs the function below, which is the actual code that prevents data loss.
One batch, two collections, every document attached to your old anonymous UID gets stamped with the new one. From the user's perspective, all their projects are simply still there.
The seven moments between landing and first generated app
Page mounts
Browser loads /. No cookies, no localStorage, no Firebase user.
Firebase wakes up
onAuthStateChanged fires with null. The auth provider calls signInAnonymously(auth) immediately.
Session key is minted
crypto.randomUUID() generates a fresh UUID and writes it to localStorage under mk0r_session_key.
VM prewarm fires
POST /api/vm/prewarm goes out as fire-and-forget. The server calls topupPool() so an E2B sandbox starts warming before any user input.
Auth provider fires again
onAuthStateChanged returns with the anonymous Firebase user. setUser hydrates. The UI is now interactive and authenticated.
You type a prompt
The textarea sends your first message. Behind it, the Bearer token in the header is the anonymous ID token Firebase already minted.
Build streams back
Quick mode streams HTML into an iframe. VM mode attaches your session key to a warm sandbox and streams the agent's actions back live.
Want to see anonymous mode running live?
Walk through the auth flow, the prewarm, and the migration on a real call. Bring questions about your own onboarding.
mk0r vs. the typical no-signup builder
| Feature | Typical no-signup tool | mk0r |
|---|---|---|
| Backend identity on first paint | None, or browser-only token | Real Firebase UID via signInAnonymously |
| Server-verifiable token for API calls | No token, requests are unauthenticated | Firebase ID token, sign_in_provider: anonymous |
| VM warmed before you type | Cold start on first generation | Yes, /api/vm/prewarm fires on mount |
| Project survives a page refresh | Often lost when browser memory clears | Yes, owned by your anonymous UID in Firestore |
| Upgrade path to a real account | Re-import or start over | linkWithPopup, then batch migration as fallback |
| Code ownership of generated app | Often vendor-locked output | Real HTML/CSS/JS or Vite + React project |
What you can actually build without signing in
The honest trade-off
There is one cost to skipping the form. If you clear your browser storage, you lose the local mk0r_session_key, Firebase signs you out, and on the next paint we sign you back in as a brand new anonymous user with a fresh UID. Anything you built under the previous anonymous UID is still in Firestore but is no longer reachable from this browser, because no one is holding its credentials anymore.
That is the trade we explicitly made. Asking for an email at the front door would solve that one edge case at the cost of making every visitor type before they create. We chose the other side: the front door is empty, and if you want cross-device durability you sign in once, the migration runs, and from then on everything is permanent.
By the time you read this, it has happened 0+ times across mk0r. Most of those visitors never typed an email.
Frequently asked questions
If there is no signup, how does mk0r know it is me when I come back?
On first visit the client generates a UUID with crypto.randomUUID() and writes it to localStorage under the key mk0r_session_key. It also calls signInAnonymously(auth) against Firebase, which mints a real Firebase user with isAnonymous = true. Both identifiers persist across reloads, so when you come back tomorrow your sessions and projects load against the same anonymous UID without you ever filling in an email.
What happens to apps I built anonymously if I sign in later?
When you sign in with Google, the client tries to link the Google credential onto your existing anonymous user with linkWithPopup. That keeps the same UID, so nothing has to move. If linking fails because that Google account already has its own UID, the app falls back to /api/auth/migrate, which runs a single Firestore batch.commit() that updates userId on every doc in app_sessions and ownerUid on every doc in projects from the old anonymous UID to the new permanent UID. Your work is not orphaned.
Is the VM also created without signup?
Yes. When the landing page mounts it fires a POST to /api/vm/prewarm. That endpoint calls topupPool() in src/core/vm.ts, which spins up E2B sandboxes ahead of demand. By the time you finish reading the prompt placeholder, a VM is already warming for you. The route is gated behind POOL_ADMIN_TOKEN in production but happily runs anonymously when the env var is unset, which is exactly the home page case.
Do I need an email to download the code mk0r generates?
Quick mode streams full HTML, CSS, and JavaScript into the preview iframe and you can copy or download it directly. VM mode runs a real Vite + React + TypeScript project inside a cloud sandbox, and you can browse and copy any file in there. Neither flow asks for an email before generation. We do gate publishing to a custom subdomain behind sign-in, because that is the only place an account is genuinely required.
How is this different from tools that just have a free trial without a signup form?
Most tools that advertise no signup either pop a form the second you click Generate, or they store everything in browser-only memory so a refresh wipes your work. mk0r issues you a real Firebase identity from the start, which means the server can authenticate your requests, attach your sessions in Firestore, and rate-limit you the same way it does signed-in users. You get durability and real backend state without the form.
Does anonymous mode have the same model access as signed-in mode?
Anonymous and signed-in users hit the same Claude generation paths through src/app/api/chat/route.ts. The only difference handled in src/app/api/vm/ensure-session/route.ts is that signed-in users with a connected Claude OAuth token can route generation through their own subscription, while anonymous users use the shared key. Output quality and feature set are identical.
What happens if I clear my browser storage?
You lose the local mk0r_session_key and Firebase signs you out, then signs you in again as a brand new anonymous user with a fresh UID on next paint. Anything you generated under the old anonymous UID is still in Firestore but is no longer reachable from this browser, since you no longer hold its credentials. This is the only real cost of skipping signup, and it is the trade we explicitly chose so the front door has zero friction.
Open the home page. The auth provider runs, the VM warms, and a blank textarea waits. That is the entire onboarding.
Build without signing up