Guide

Mobile app maker online, booted before you arrive

Most tools that call themselves an online mobile app maker just mean an editor that runs in a browser tab. The dev server, the test browser, the network egress, all of those still live somewhere else, usually on your machine. mk0r is online in a stricter sense. The whole pipeline runs in a cloud sandbox, and the sandbox is already warm in a Firestore-backed pool by the time the landing page finishes loading.

m
mk0r
8 min
4.8from 10K+ creators
Cloud sandbox booted before you click
Dev server, Chromium, agent, all online
390 by 844 mobile preview, public phone URL
0Native toolchain installs
0Cloud services per sandbox
0 pxMobile preview width
0 pxMobile preview height

What most online mobile app makers actually mean by online

Open the homepage of a typical online mobile app maker and you land on a sign-up wall. Pick a template. Pick a plan. Watch a spinner while a generic shared web canvas warms up. The drag and drop editor is online, sure, and the published mobile site is served from their CDN. But the iteration loop, the moment to moment build experience, leans heavily on a single shared backend or your local browser to do the work.

The thing every page about this topic glosses over is the architecture under the editor. Where does the dev server run? Where does the test browser run? Where does the agent run? On most platforms the answer is somewhere fuzzy and shared. On mk0r the answer is concrete: each session gets a dedicated cloud sandbox running Vite, headless Chromium, Playwright MCP, and the agent bridge, and that sandbox was already booting while the landing page was still rendering in your tab.

The pre-warm: a sandbox is online before you are

When you open mk0r.com, the home component fires a fetch on mount. The body is empty, the response does not matter, the point is the side effect on the server.

src/app/(landing)/page.tsx

That POST hits a route that calls topupPool(), which in turn calls prewarmSession() until the pool reaches VM_POOL_TARGET_SIZE. Each pre-warmed session is a real E2B sandbox booted from a specific template, with the proxy, Vite, Chromium, MCP, and ACP bridge all up and listening. The sandbox identity and reachable URLs land in a Firestore document so the next user can claim it.

src/core/e2b.ts

The first request your tab sends after submit is a session claim. A Firestore transaction reads one ready row, deletes it, and returns the sandbox metadata. Re-initialize ACP, create a fresh session, and the preview URL is yours. The wait you experience is two round trips, not a cold E2B boot.

From landing page load to first preview paint

Your tabmk0r serverFirestore poolE2B sandboxload mk0r.comPOST /api/vm/prewarmtopupPool() boots E2B sandboxready row written to vm_poolsubmit promptclaimPrewarmedSession (txn)re-initialize ACP, session/newpreviewUrl, acpUrl, sessionIdiframe loads 390 by 844 preview

What is actually running, online, while you read this

Inside every active sandbox there are five long-running services and one reverse proxy that fronts them all on port 3000. SSH into a live sandbox and the listening sockets look like this:

Inside the sandbox

The reverse proxy is the trick that makes this all addressable from one URL. /acp/* lands on the agent bridge. /mcp/* and /sse land on Playwright MCP. /screencast and /input WebSockets relay CDP traffic for the in-VM Chromium. /vnc relays websockify. Every other path falls through to Vite on 5173, including the HMR WebSocket. So the iframe you see in your tab and the screencast of the cloud Chromium and the agent that is editing the project all share one host and one port.

One URL, five online services

Your tab
Your phone
Claude agent
Sandbox :3000
Vite :5173
Chromium :9222
Playwright :3001
ACP bridge :3002
VNC :5901

The reverse proxy, in twenty lines of code

The whole multiplexer is a small Node script written into the sandbox at boot. The interesting part is how it routes everything through one HTTP server and one WebSocket server.

src/core/vm-scripts.ts

Because everything is on one host, the public preview URL works on a phone the same way it works in the desktop iframe. Vite HMR still flows. Screencast still flows. The session is one online place, not a stack of services you have to wire together.

What this online architecture lets you skip

When the dev server, the test browser, and the agent all live in a cloud sandbox, a long list of typical online builder requirements quietly disappears. Side by side:

Typical online mobile app maker vs mk0r

The visible UI looks similar. What runs underneath it does not.

FeatureTypical online buildermk0r
Where the editor runsIn your browser tabIn your browser tab
Where the dev server runsGeneric shared web canvas, your machine, or no real oneVite on port 5173 inside an E2B sandbox per session
Where the test browser runsYour local ChromeHeadless Chromium on port 9222 in the same cloud sandbox
Cold boot waitLogin, plan picker, template, then buildSandbox already booted in a Firestore pool; you claim it
Account required to startYes, email plus tierNo, type and build
Test executionYou click around manuallyAgent drives Playwright MCP, snapshots DOM, reads console
Source code ownershipLocked to the platform formatPlain HTML, or a Vite React project you can download
Open the build on your phoneApp store review queue or sideloadCopy the public preview URL, open in any phone browser

What you can build in this online environment

Anything that fits a 390 by 844 mobile web app fits the cloud sandbox. Quick mode is right when one HTML file does the job. VM mode is right when you want a real Vite project you can keep editing. A few things that work well end to end:

A bottom-tab notes app

Three screens, a sticky bottom nav, local storage. The agent writes the files, the cloud Vite server reloads, the cloud Chromium snapshots the DOM, and the 390 by 844 frame in your tab repaints with HMR.

A camera-driven journal

MediaDevices API, a feed of cards, pull-to-refresh. Built and previewed in the sandbox, opened on your phone via the public preview URL.

A pace-tracking running log

Routing, charts, and persistent state in a Vite plus React project. Lives in /app inside the sandbox and downloads as a normal repo.

A swipe-to-complete checklist

Pointer events, gesture animations, optimistic updates. The agent verifies behavior in the cloud Chromium before reporting done.

A tip calculator one-shot

Quick mode streams a single HTML file with embedded CSS and JS. Done in well under a minute, saveable as one file.

A daily habit ring

SVG strokes, spring physics on completion, haptic-style pulse on tap. Phone-framed in mk0r, real-pixel-perfect on the device.

Specifics about the online sandbox

Vite dev server, port 5173Chromium with CDP, port 9222Playwright MCP, port 3001ACP agent bridge, port 3002Reverse proxy, port 3000VNC relay, port 5901Firestore vm_pool collectionE2B sandbox per session390 by 844 phone framePublic preview URLOptional residential IPVite HMR over WebSocket

Each chip there is a real listening port or a real piece of infrastructure inside the sandbox. None of it is on your laptop. The pool target size is configurable per environment viaVM_POOL_TARGET_SIZEand stale pool entries (older than 45 minutes, or with a mismatched specHash from a redeploy) are cleaned up automatically so claimers always get a fresh, correct sandbox.

Why the wait between submit and first paint feels close to zero

On a cold path, the agent path adds up to roughly five seconds: E2B sandbox cold boot, ACP initialize, session/new, getOrCreateSession bookkeeping, then the first agent turn. On the warm path, four of those five steps already happened in the background while the landing page was rendering. What is left is a Firestore transaction (single round trip), an ACP re-initialize (the bridge respawns the agent subprocess only if your API key fingerprint differs from the warmed one), and a session/new call. That is the entire visible delay, and it is the reason the preview iframe usually starts loading before you have finished reading your own prompt back.

The phone, on your phone, while you build on a desktop

The cloud sandbox publishes the reverse proxy on a public URL. That URL is the one the in-tab iframe loads from, and it is also the one you can paste into the phone browser sitting next to your laptop. Vite HMR runs over WebSockets through the same proxy, so a file change in the agent triggers a repaint on the desktop frame and on the physical phone at the same time. It removes the loop where you build, deploy, install, debug, build, redeploy. The phone is just another viewport pointed at the same online sandbox.

Want to watch a sandbox boot from the pool, live?

Book a 20 minute walkthrough. We will load mk0r in front of you, show the prewarm fire, then build one of your mobile app ideas in the warm sandbox.

Frequently asked questions

What does "online" actually mean for a mobile app maker?

On most platforms it just means "runs in a browser tab." The editor is online, but the dev server, the test browser, and the build chain quietly depend on either your laptop or a generic web canvas. mk0r runs the entire build environment in a cloud sandbox: a Vite dev server on port 5173, a Chromium with Chrome DevTools Protocol on 9222, a Playwright MCP server on 3001, and the Claude agent bridge on 3002. All four are unified behind one reverse proxy on port 3000. Your tab is a thin client streaming a screencast of the cloud Chromium and an iframe of the cloud Vite server.

Why does the wait between submitting a prompt and seeing a preview feel so short?

Because the sandbox is usually already booted. When the landing page loads, the client fires POST /api/vm/prewarm. That route calls topupPool() which calls prewarmSession() and boots fresh E2B sandboxes up to the VM_POOL_TARGET_SIZE limit. Each warm sandbox is stashed in the vm_pool Firestore collection with its sandboxId, host, acpUrl, previewUrl, and sessionId already populated. When you submit, claimPrewarmedSession runs a Firestore transaction that deletes the ready row and hands you the live sandbox. The only remaining cost is re-initialize plus session/new, which is roughly 2 seconds of round trips, not a 5+ second cold boot.

Where does the test browser actually live?

Inside the same E2B sandbox as the dev server. There is a real Chromium running with --remote-debugging-port=9222. The reverse proxy at port 3000 exposes a /screencast WebSocket that relays CDP screencast frames to your tab and an /input WebSocket that relays mouse and keyboard events back the other way. So when you watch the AI agent test the app it just wrote, you are watching a cloud Chrome window streamed to a canvas in your tab. You can take over the browser by clicking the takeover toggle and your inputs are routed through the same socket.

What size is the mobile preview?

390 by 844 CSS pixels, the iPhone 14 Pro logical viewport. The constant lives in DEVICE_SIZE inside src/components/phone-preview.tsx. The frame does not change as content streams, so the layout you design against is the layout a real phone gets. Switch to desktop in the device toggle and the frame is removed.

Do I need to install Xcode, Android Studio, or any SDK?

No. You do not install anything. The build target is a mobile web app, rendered in the 390 by 844 frame and served from a public preview URL. You can wrap the same code in Capacitor or Expo later for a store listing, or install the preview URL as a Progressive Web App from your phone share sheet. The point is that the moment you start building is not delayed by a setup checklist.

How does the same online sandbox stay up while I iterate?

The sandbox keeps Vite running, so each agent file write triggers Vite HMR. The preview iframe in your tab listens for postMessages from a small bridge injected into the generated app and waits up to 800 milliseconds for an hmr:after acknowledgment. If HMR lands inside that window, no reload happens and your scroll position and focus survive. If HMR misses, the iframe cache-busts with the previous frame still rendered underneath. The rule of thumb: file change in the cloud sandbox, repaint in your tab, no flash.

Can I open the app on my actual phone while building from a desktop?

Yes. The reverse proxy on port 3000 in the sandbox is reachable on a public URL. Copy it from the preview panel into your phone browser and you see the same Vite dev server, the same HMR, and the same state. You build on a desktop and watch the changes land on a phone next to you, without any tunneling, ngrok, or USB cable.

Is anything stored on my computer?

No code lives on your machine. The project tree is inside the sandbox at /app. Quick mode generates a single HTML file streamed straight to your tab, which you can save to disk if you want. VM mode keeps a Vite plus React plus TypeScript project in the sandbox that you can download or push to GitHub. Either way, no local install, no node_modules folder on your laptop, no build artifacts to clean up.

What happens to the cloud sandbox when I close the tab?

It pauses. The session record in Firestore preserves the sandbox identifier and pool metadata, and when you come back the next request to the API route restores it. If the sandbox has been idle past the E2B timeout (the pool ages entries out at 45 minutes), it is replaced with a fresh one and your project state is restored from the persisted git history.

The cloud sandbox is probably already warming for you. Type your mobile app idea and watch it land at 390 by 844, no install, no account.

Start building online
mk0r.AI app builder
© 2026 mk0r. All rights reserved.