Guide

Single sentence HTML app: three things that were already running before you typed

The idea is simple. One English sentence in, a working app out. What most pages on this topic skip is what's running on a server before your sentence ever leaves the browser. On mk0r there are three of those things, and they're the reason a one-sentence build feels instant rather than felt like a thirty-second cold start.

M
Matthew Diakonov
6 min

Direct answer (verified 2026-05-15)

A single sentence HTML app is a working interactive app you describe in one English sentence and run in a browser. On mk0r.com the deliverable is a Vite plus React project inside a sandbox with a live preview URL, not a static .html file. By the time you submit, a sandbox is already prewarmed, /app is already scaffolded, and a one-sentence system prompt is already loaded. Source on GitHub: m13v/appmaker.

The picture, with the upstream parts drawn in

Most diagrams of one-sentence app makers show two boxes: prompt on the left, app on the right. The honest picture has three small things on the left, then your sentence, then the model, then the app. The three small things are the ones the homepage silently sets up before you've thought of what to type.

What feeds the model on turn 1

Prewarmed sandbox
Scaffolded /app
System prompt
Your sentence
Claude Haiku 4.5
Live preview URL
Source you can read

Thing one: the sandbox is warming while you're reading the hero

Cold-starting a Linux VM, installing dependencies, and bringing up a dev server takes thirty to ninety seconds in the worst case. That is a long time to stare at a loading spinner after pressing submit. The fix is to do the boot before submit, during the seconds where you're scanning the page.

On mount, the homepage fires a POST to /api/vm/prewarm. The handler reads VM_POOL_TARGET_SIZE (default 1), checks Firestore for a ready sandbox, and spawns one if missing. By the time your finger hits submit, the sandbox is already idle and waiting.

page-load to ready sandbox (the part you don't see)

Thing two: /app is already a real React project before your sentence arrives

The prewarmed sandbox isn't an empty Linux box. It comes from an E2B template called mk0r-app-builder with the project baked in: Vite plus React plus TypeScript plus Tailwind CSS v4 plus an HMR-enabled dev server on port 5173, plus Playwright MCP for browser testing. The agent inherits a working app, not a blank directory.

This is the reason your one sentence usually outputs a React component instead of a static HTML file. The model is told, literally, that it's working inside a Vite plus React project, so it edits files in that project rather than writing a single self-contained document. If you wanted a single.html file, you would have to override the default in your sentence.

The honest framing of the keyword: 'single sentence HTML app' describes the user-visible artifact (the browser renders HTML) more accurately than it describes the source files (TSX, CSS-via-Tailwind, multi-file Vite project).

Thing three: the system prompt is itself one paragraph

The model needs to know the stack it's working in before your sentence arrives, otherwise it might write Express, or Next.js, or vanilla HTML, and waste a turn fighting the scaffold. mk0r ships a tiny system prompt that names the stack in one breath. It lives at src/core/e2b.ts line 184. Here is the verbatim string with line breaks added for readability.

src/core/e2b.ts

Four facts, eighty-something words. It names the sandbox, the stack, the port, the test tool, and where to find the longer workflow notes. Every first turn rides on top of that paragraph. So when you type 'A habit tracker with daily streaks,' the model's effective input is roughly eighty words of context plus your six.

Why this matters for one-sentence prompts specifically

The whole point of a one-sentence app is speed. Type, watch, react. If any of the three upstream pieces were missing, the loop would feel different in ways that kill the appeal:

  • No prewarm and you'd watch a spinner for thirty seconds before the first character streamed. By then you'd be checking another tab.
  • No scaffold and the model would have to invent a project shape for every prompt. 'A pomodoro timer' would land as vanilla HTML one day and as a Next.js app the next.
  • No system prompt and the model would guess what stack to use, often pick badly, and burn your first iteration turn undoing its own choice.

Together they collapse the apparent latency from 'cold sandbox plus scaffolding plus framework choice plus your sentence' down to 'streaming time on top of an already-loaded context.' That's why one sentence feels enough.

What you're actually typing into

With the upstream stuff in place, your sentence does three jobs. It names the app (the noun phrase). It picks one specific constraint to anchor the first layout (the 'with X' clause). And it gives the model a place to stop, so the first turn doesn't try to do everything.

The four examples hard-coded at src/app/(landing)/page.tsx line 1092 all have this shape:

  • A habit tracker with daily streaks
  • A pomodoro timer with focus sessions
  • A mood journal with weekly insights
  • A flashcard app for language learning

Noun phrase, one specific feature. That's it. Add the rest with the next sentence. You get six anonymous turns before anything asks you to sign in (ANON_TURN_LIMIT in src/app/api/chat/route.ts line 23), and signing in keeps everything you already built.

Where one sentence stops being enough

One sentence handles single-screen utilities very well: trackers, timers, journals, flashcards, calculators, quizzes, generators, single-page games. The model can hold the whole app in its first response and produce something interactive in one streaming pass.

Where it falls short is anything that needs real persistence, real authentication, real payment, or coordinated state between users. Those are not one-sentence shapes. They are many-sentence shapes, and the maker loop is built for that too, you just spend turns adding pieces rather than riding one sentence to the finish.

A useful working rule: if you can describe the whole app on a phone keyboard without scrolling, one sentence is probably enough. If you need bullet points to describe it, plan on iterating.

Want to talk through what your one sentence should be?

Bring an app idea, leave with a sentence that's likely to land on the first try. Twenty minutes, no slides.

Frequently asked questions

What is a single sentence HTML app?

It's a working interactive app you described in one English sentence. You type the sentence, an AI writes the markup and the logic, and a browser renders the result. On mk0r the output runs as a Vite plus React project inside a sandbox with a live preview URL, not as a static .html file you download. The output is real source you can keep, but the default deliverable is a running app, not a file on disk.

Will mk0r actually produce a standalone .html file from one sentence?

Not by default. The sandbox at /app is scaffolded with Vite, React, TypeScript, and Tailwind v4 before your sentence arrives. So your first build lives inside that project. If you specifically ask for a single .html file in your sentence, the agent will write one, but the default shape of the deliverable is a Vite project with a dev server on port 5173. That's a real constraint to know up front: the keyword 'HTML app' is true in spirit (HTML is what your browser renders) but is multi-file React under the hood.

What's the one-sentence system prompt mk0r loads before my sentence?

It's defined at src/core/e2b.ts line 184 as a single string literal: 'You are an expert app builder inside an E2B sandbox with a Vite + React + TypeScript + Tailwind CSS v4 project at /app. The dev server is running on port 5173 with HMR. You have Playwright MCP for browser testing. Read your CLAUDE.md files for detailed workflow, coding standards, and memory instructions.' That paragraph rides in front of your sentence on every first turn. Your one sentence is really sentence-on-top-of-paragraph.

What does 'prewarmed sandbox' mean and how do I know it's real?

When the homepage mounts in your browser, src/app/(landing)/page.tsx line 64 calls fetch('/api/vm/prewarm', { method: 'POST' }). That endpoint runs topupPool() in src/core/e2b.ts, which checks Firestore for a 'warming' or 'ready' sandbox entry and spawns one if missing. The pool target size is read from VM_POOL_TARGET_SIZE on line 2337, defaults to 1. So when you start typing, a sandbox is either already cold-started in the background or waiting in 'ready' state. You don't pay the boot time on submit.

Why does this matter for one-sentence prompts specifically?

Single-sentence prompts are about latency. The whole appeal is type, watch, react. If the model had to wait for a sandbox to boot from cold every time, the first paint would arrive thirty to ninety seconds after submit, and the maker loop would feel broken. The prewarm step front-loads boot time onto the page-load event so the wait by the time you've thought of your sentence is closer to the model's streaming time than the sandbox's start time. It's the unglamorous part of the product that makes one sentence feel instant.

Is the output really HTML if it's React under the hood?

Your browser renders HTML. That part is true. The source files mk0r writes are React TSX components, Tailwind classes, and TypeScript, which Vite compiles into the HTML and JavaScript your browser actually executes. So 'HTML app' in this context is an honest description of the user-visible artifact but a slightly loose description of the source. If you specifically need a single-file .html with everything inline (a script tag, a style tag, no build step), say so in the sentence.

What kinds of one-sentence prompts actually ship working apps?

Noun phrase plus one specific feature. The four sentences hard-coded in the homepage at src/app/(landing)/page.tsx line 1092 are: 'A habit tracker with daily streaks', 'A pomodoro timer with focus sessions', 'A mood journal with weekly insights', 'A flashcard app for language learning'. Each one names exactly one app and exactly one constraint. That's the shape that lands on the first try. 'A productivity app' is too vague. 'A habit tracker with streaks, friends, push notifications, payment, and dark mode' overloads the first turn; the maker loop is built for adding constraints one sentence at a time.

How many follow-up sentences can I send for free?

Six anonymous turns. The constant ANON_TURN_LIMIT is 6 at src/app/api/chat/route.ts line 23. Each completed turn increments anonTurnsCompleted on your Firestore user record. On the seventh turn the API returns a sign_in_required response and the UI shows a one-tap Google sign-in. Signing in upgrades your anonymous account in place; everything you already built stays. So a one-sentence build is genuinely free, and a six-sentence iteration is genuinely free, with no card or email upfront.

What if I just want the raw HTML from a one-sentence prompt?

Two options. The simplest is to put 'as a single .html file' in your sentence, and the agent will write a self-contained document with inline CSS and JS. The other is to let the default React project build, then view source or copy the compiled output. Either way the output is plain web standards. There is no proprietary export format and no lock-in. Right-click view source, copy out, drop into any static host.

Where do I verify any of these claims?

The full source is open at github.com/m13v/appmaker. The five anchor files: src/core/e2b.ts (system prompt, pool, default model), src/app/(landing)/page.tsx (prewarm fire on mount, seed sentences), src/app/api/chat/route.ts (anonymous turn limit), src/app/api/vm/prewarm/route.ts (the pool topup endpoint), and src/core/vm.ts (session lifecycle). Every fact on this page traces to a line number you can open and read.

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

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.