How to turn a client brief into a mobile app prototype
Turn a client brief into a mobile app prototype with a copyable AppX prompt, a practical test checklist, and a focused client-feedback workflow.
Practical guides for turning a clear brief into an app you can test and own.
Turn a client brief into a mobile app prototype with a copyable AppX prompt, a practical test checklist, and a focused client-feedback workflow.
The gap between a great AI-built app and a mediocre one is almost never the idea — it's the describing. The four moves that collapse a vague sentence into your exact app.
A second-by-second walkthrough of using AppX — empty box, one sentence, watch it build, scan a code, and your idea is running in your hand. The experience is the product.
For thirty years, turning an idea into software meant learning to code, hiring, or finding a technical co-founder. AI removed that wall — and the skill that replaced coding is one you probably already have.
The honest founder story behind AppX — the doubt, the pivots, the nights spent fixing the unglamorous two seconds at the end of a forty-step pipeline. Not the architecture. The human part.
Expo Go is a preview surface, not a release artifact. Building the path to .ipa and .aab via EAS — what's shipped, what's still rough, and what we won't do.
Native iOS/Android builds via EAS, custom domains, multi-user collaboration, expanded template gallery, runtime-error-into-chat, voice input. Honest gates and confidence levels — no date promises.
The headline: we found a structural bug in agent-turn persistence (the 0ms-zombie), fixed it across five engineering waves, AND launched this engineering blog, AND shipped a dozen smaller polish items.
Two months of engineering recap. Forge containers stopped getting stuck, Edit Engine v2 made surgical edits the default (+25 pts edit success), Bloom-parity chat closed the visual gap with our closest competitor.
Free-trial sizing is pricing physics, not marketing. We dropped from 350 to 150. Conversion held; cost per signup dropped ~55%. The lesson on what the free tier is actually for.
Naive packing = 12 containers per VPS, swap-bound. Tuned packing = ~80 containers, 80-100MB each. Four wins, one ceiling we hit, and the suspend pattern we wish we'd built earlier.
'Done · 0ms' looked cosmetic. Eight hours of investigation revealed it was a structural bug class. A week of work shipped a 5-wave persistence rearchitecture. The narrative of how a UI screenshot turned into the biggest backend project of the month.
The Railover orchestrator fork, the one-shot bundle server, the V1 chat intent classifier. Each was a real working system in production. Each got deleted when the shape of the problem changed underneath it.
Three architectures in eight months. Each pivot was triggered by failures the prior architecture couldn't fix without adding the next layer. The shape we landed on, and what we think Era 4 looks like.
Three SDK clients, three streaming parsers, three error shapes. We switched to OpenRouter in 48 hours. The dividends — and the honest tradeoffs we're paying for.
Smart retry on critical files, intent detection with word boundaries, planning before generation, and credit holds. None was a single algorithm — each was a structural change to the loop the LLM lives inside.
v1 was a web-first React generator wrapped in Vite hosting. It demoed beautifully and failed in production. The honest autopsy — what stayed, what went, and why the demo and the product are different things.
Sequel to why-we-built-forge. Polling produces a structural drift window. HMAC-signed webhooks on every sandbox transition take state propagation from 5-10s to ~1ms. Idempotent handler, state-machine guard, replay-on-restart, and one slow reconciler kept as safety belt.
Sequel to why-we-built-forge. Sub-2-second cold-to-QR is impossible if every request spawns a fresh container. The warm pool primitive: pre-provisioned idle sandboxes, atomic claim, load-aware sizing, ~80 containers per 24GB VPS.
One-shot bundlers pay cold-start every invocation. Persistent Metro dev server inside each preview container takes file writes to 4ms and warm bundles to 100ms. The pattern generalizes — any incremental build tool with a watch mode wants to be a daemon, not a script.
SIGTERM gives you cleanup time. SIGKILL doesn't. Deploys, OOM, and crashes all skip your graceful-shutdown handler. Your sweeper IS the SIGKILL handler — and its query shape should test for invariant violations, not row age.
Agentic edit loops bleed on whitespace drift and one-character mismatches in SEARCH/REPLACE blocks. Replace 'SEARCH text not found' with the top-3 similar candidates scored by Dice's coefficient — the LLM autocorrects on the next iteration at the cost of one O(n*m) scan.
AI architects emit multi-file plans that compile, run, and crash because the dependency graph has a cycle nobody looked at. Validate the plan with Kahn's algorithm before you spend tokens generating. Twenty lines of TypeScript catches a class of runtime bugs at near-zero compute cost.
Native builds = 60s+ per iteration kills the AI feedback loop. Web preview defeats the mobile-app pitch. Expo Go + Metro gives sub-second hot-reload on a real phone — and that latency budget cascaded into every architectural decision downstream.
Origin story — what AppX's first prototype was, the three architectures we tore down to get here, and the lesson we kept relearning: the AI doesn't need more intelligence, it needs more structure around its outputs.
Every non-trivial bug is one instance of a class. Patching the instance leaves the class alive — and it will mint the next bug. The lens, the patch+class split, the economics, and the trap of fixing classes that don't matter.
Big-bang PRs get skimmed. Multi-week branches drift. Neither works for a hot persistence path. The shape that does: 5 independently-shippable waves, shadow-mirror writers, and a kill-switch wave that turns modernization into actual debt reduction.
Sibling to investigators-before-builders. Here's the concrete case: three parallel read-only investigators caught that only 8 of 32 fields warranted promotion — and turned a new-table refactor into an extend-table refactor, saving two weeks.
Typed query builders catch schema drift everywhere except inside raw sql templates. The string column reference is the hole. Ban it. What's left is enough for every legitimate raw-SQL case — and the bug class becomes structurally impossible.
E2B, Modal, Daytona, Replit, Bloom — we evaluated them all. None fit the shape of an AI app builder that needs sub-2s phone preview, long-lived Expo dev servers, and 80 containers per VPS. So we built Forge.
A frontend clamp papers over a bad column. A backend sweeper catches symptoms not causes. A DB constraint blocks bad writes but doesn't repair existing rows. You need all four — and the order to retrofit them when starting from a broken system.
Every soft field in a JSONB blob looks like flexibility. By month six it's a defensive ?? walk on the frontend and a JSON_EXTRACT join the planner can't index. Three forces pull fields out of JSON — and the migration shape that needs no freeze.
Two-phase write + process death = a row that lies about its own state. We call it the 0ms-zombie. Defines the bug class formally and ranks four mitigations by structural depth, from frontend clamp to DB CHECK constraint.
Every byte you load into an LLM agent's context is a byte it has to keep track of. Dead code looks like signal — and agents preserve, extend, or mimic it. Our rule: a pure-deletion commit before any structural refactor of a file over 300 LOC.
Most teams dispatch coding agents straight to the build. We run a read-only investigator phase first — and the findings have rewritten our plan in 30-40% of cases. Here's the shape, the brief format, and what to do when findings contradict the plan.
Parallel coding agents don't bottleneck on compute — they bottleneck on the merge. Two agents touching the same file cost more than one agent doing both edits. The fix is a partitioning rule we wish we'd adopted earlier.
We ship user input into an LLM architect prompt every turn. A reviewer caught that a 4-backtick string from the user could close our 3-backtick fence and run arbitrary instructions on the model. The fix is one weird Markdown trick.