An app mobile maker that gives you a real Postgres database before it shows you a single screen
Every other app mobile maker in the category hands you a canvas and a promise of integrations later. mk0r goes the other direction. By the time your first mobile preview paints, the VM already has a dedicated Postgres project, a scoped email sending key, a private GitHub repo, and an analytics group id sitting in /app/.env. This page is a look under that hood.
What mk0r does before your mobile app paints
0 ms, prompt lands
You type a mobile app idea. The client posts it. A session key is assigned before any service call fires.
The problem this page is actually about
If you have tried to make a mobile app with any of the usual suspects in this category, you already know the trap. The canvas is fine. The preview is fine. Then you want your habit tracker to remember the last seven days across a tab close, and the platform tells you to connect a database. You want the weekly summary to actually email. That is a plan upgrade. You want to know how many users ever opened the bottom tab. Paste this snippet, hope you placed it right.
The mobile preview is the easy part. Backing it with real storage, real mail, and real telemetry is the hard part, and it is almost always where the "maker" part ends and the "actually ship a real mobile app" part begins.
mk0r collapses that gap. A fresh Postgres database, a fresh email audience with a scoped sending key, a private git repo, and a scoped analytics project are all provisioned before you see the first mobile frame. You do not connect anything. Nothing is gated. The agent, on its first turn, is allowed to write insert into runs ... and have it work.
What the orchestrator actually does
The spine of this whole story lives in a single file: src/core/service-provisioning.ts. One exported function, provisionServices(sessionKey), kicks off four upstream calls. PostHog is synchronous because the project key is shared across all mk0r apps and isolation is done via a per-app group id. The other three race in parallel, because the slowest of them sets the wall clock.
Two details worth calling out. First, Promise.allSettled is deliberate. One upstream hiccup does not block the session. If Resend is slow today, you still get the Neon database and the GitHub repo. The missing env var is simply omitted from /app/.env, and the agent's prompts guard every usage with if (RESEND_API_KEY) before touching it.
Second, the whole dance is anonymous. There is no account, no email confirmation, no credit card step. The session key is the tenant. Every resource is scoped to an app slug derived from it.
The four legs, end to end
This is the concrete shape of what is sitting in the VM when your mobile preview paints. Nothing here is a generic label: every value below comes from real provisioning code.
provisionServices(), one call, four outputs
What it looks like in the log
The provisioning pipeline leaves a clean paper trail. Every step emits a structured log line prefixed with [provisioning]. Here is a trimmed version of what a healthy mobile session prints in Cloud Run logs.
The handoff from orchestrator to agent
The moment provisionServices settles, the session orchestrator runs a single execInVm: printf '%s' {env} > /app/.env. That is the entire injection. The env file appears before the agent's first prompt is served, which means the first file the agent writes can already assume the credentials exist.
handoff: prompt to first database insert
What this unlocks that other mobile makers can't
Pre-provisioning changes the shape of what the AI is allowed to build on turn one. Every card below is something the agent is willing to write in its first file, because the credentials are already on disk.
A run tracker that actually saves runs
insert into runs (distance_km, pace_per_km, ran_at) values ($1, $2, now()) talks to a fresh Neon project. Close the tab, reopen on your phone, your runs are still there.
A habit ring that emails the weekly summary
resend.emails.send fires through the per-app restricted API key every Sunday at 18:00. The audience at RESEND_AUDIENCE_ID is pre-created, so adding a contact is one call.
A mobile waitlist that never sees localStorage
Contacts land in both the Neon database and the Resend audience in one turn. Analytics for the submit event land in PostHog, scoped to the app's group id.
A mobile CRUD whose migrations live in git
npx drizzle-kit push writes to the pre-provisioned Postgres project. Commits push to m13v/mk0r-<slug>, a private repo you already own.
A share-sheet notebook with search
Add a Postgres full-text index in one migration; the mobile iframe hits a Vite server route that runs the query on Neon; the response renders back inside the 390 by 844 frame.
An event-tracked bottom-tab app
posthog.capture('tab_opened', { tab: 'home' }) groups under app=mk0r-<slug>, so the mobile app's analytics are isolated from every other mk0r app in the shared project.
Chips in the VM, at a glance
Everything your mobile app can touch, from the moment the preview loads.
Typical app mobile maker vs the mk0r flow
Everything below is about timing: when each of these things is available to the mobile app you are building.
| Feature | Typical app mobile maker | mk0r |
|---|---|---|
| Database on turn one | Connect later, often paid tier | Dedicated Neon Postgres 17 project, created in parallel |
| Transactional email | Bring your own SMTP or third-party plan | Restricted Resend sending key and audience, pre-created |
| Analytics | Paste a snippet, hope you placed it right | PostHog group id isolating the app, already wired |
| Source control | Export a zip if the tier allows | Private GitHub repo at m13v/mk0r-<slug> |
| Credentials live at | Copy-paste through the settings UI | /app/.env inside the VM, before the first prompt |
| Provisioning failure | Setup blocks the whole flow | Promise.allSettled, missing env var is gracefully skipped |
| Leaving the platform | Export denied or schema locked | Plain Vite + React + TS project, repo and DB are yours |
Ownership: you leave with the database, the repo, and the code
The point of pre-provisioning is not just speed, it is ownership. The Neon project is real Postgres you can psql into. The GitHub repo at m13v/mk0r-<slug> is a real remote you can push commits to. The Resend sending key is restricted so you can rotate it without touching anything else. The PostHog group filter app=mk0r-<slug> returns your mobile app's events and nobody else's.
When you move off mk0r later, the mobile app keeps running. It reads DATABASE_URL, RESEND_API_KEY, and VITE_POSTHOG_KEY from env vars like any other app. Set the same vars on your own hosting and the build is done.
Want us to walk you through the provisioning pipeline?
Book a 20 minute call. We will start a fresh mk0r session on the line and show you the /app/.env that lands before the mobile preview paints.
Frequently asked questions
What is actually provisioned the moment a mobile session starts?
Four upstream services, in parallel. A dedicated Postgres 17 project on Neon in aws-us-east-2 under org org-steep-sunset-62973058. A Resend audience named 'mk0r-<slug> Users' with a restricted sending_access API key. A per-app PostHog group id of the form mk0r-<12-char-slug> that isolates your analytics inside the shared mk0r project. And a private GitHub repo at m13v/mk0r-<slug>. The orchestrator is provisionServices in src/core/service-provisioning.ts at line 277. The four calls race via Promise.allSettled, so the slowest of the async three sets the wall clock.
Where do the credentials live inside the mobile app I am building?
Inside the sandbox VM at /app/.env. The file is written by execInVm from src/core/e2b.ts:1305 via printf piped to > /app/.env before the session is handed to the AI agent. Vite exposes VITE_POSTHOG_KEY, VITE_POSTHOG_HOST, and VITE_POSTHOG_APP_ID to client code through import.meta.env. Server-side routes and scripts read DATABASE_URL, RESEND_API_KEY, RESEND_AUDIENCE_ID, NEON_HOST, NEON_ROLE_NAME, NEON_ROLE_PASSWORD, GITHUB_REPO, and GITHUB_REPO_URL from process.env.
Can the agent really write database code on the first turn?
Yes. The agent reads the backend-services skill at /root/.claude/skills/backend-services/SKILL.md, which contains ready-to-paste snippets for drizzle-orm plus @neondatabase/serverless, for resend.emails.send, for posthog.capture, and for git push to the pre-created private repo. Because /app/.env is written before the first prompt is served, the first file the agent creates can import { neon } and call sql`SELECT ...` against a real, empty database the session owns.
What happens if one of the service providers is slow or down?
The orchestrator uses Promise.allSettled, so one failure does not block the others. The failing service is recorded in provResult.errors and its env var is simply omitted from /app/.env. The agent guards every usage with 'if (RESEND_API_KEY)' or 'if (DATABASE_URL)' so the mobile preview still boots and falls back gracefully. For PostHog, the project key is shared, so that leg is synchronous and essentially always succeeds.
Is the Postgres database wiped between mobile app sessions?
No. Each mk0r session creates its own Neon project. That project persists even after the VM sleeps, so when the session is resumed, the Postgres data is still there. The GitHub repo likewise persists. The Resend audience keeps collecting contacts. The VM snapshot goes to sleep when idle and restores on demand, and /run/brd.conf plus /app/.env are rewritten on restore if they were lost.
How is this different from every other 'app mobile maker' with a database add-on?
Timing and ownership. The rest of the category asks you to connect a database after you have clicked around in a canvas for ten minutes, usually gated behind a paid tier, with data locked in a proprietary schema. mk0r provisions a brand-new Neon project, a brand-new Resend key, a brand-new GitHub repo, and a scoped PostHog id before the first mobile screen paints, and the resulting artifacts are all yours: you can psql the database directly, rotate the Resend key, push commits to the GitHub repo yourself, and query PostHog with a filter on group app=mk0r-<slug>.
Do I need an account to trigger provisioning?
No. Typing a prompt at mk0r.com is enough to start a session. No email, no credit card, no confirmation flow. provisionServices fires from the same API path that spins up the VM, so the database, audience, repo, and analytics group are created anonymously on your behalf and scoped to the session key.
Can I take the mobile app off mk0r later?
Yes. The VM mode output is a plain Vite + React + TypeScript project at /app/src. The generated code reads DATABASE_URL, RESEND_API_KEY, VITE_POSTHOG_KEY from process.env and import.meta.env, so you can copy the repo to your own hosting, set the same env vars, and the app keeps working. The GitHub repo at m13v/mk0r-<slug> is a real remote you can push your own commits to. The Neon project id is yours to re-link to a new account on Neon's side.
Open a blank session. Watch the four services light up. Type a mobile app idea. Get a preview with a working database, a working email sender, and a working analytics feed, on turn one.
Build My Mobile App