Building
Horai builds two things: working apps and landing pages. It decides which one you asked for before it writes a line, because they are not the same object.
Two deliverable classes
A landing page is read. An app is used. The difference changes the layout, the structure and what counts as finished.
| Landing page | App | |
|---|---|---|
| What it is | A page you scroll | A tool you operate |
| Structure | Page sections top to bottom — hero, features, call to action | Layout areas — a top bar, an input form, a list or table, summary figures |
| Finished when | It reads well and every section is filled with real copy | You can put your own data in, it comes back out correct, and it survives a reload |
Horai reads the class off your sentence. "A landing page for a weekend market stall" is a landing page. "A bill splitter where I add people and items" is an app, because you operate it. If your wording points both ways, the proposal card is where you correct it — say "make it a landing page" and it re-plans.
The proposal card
Every buildable request produces a card before anything runs. For an app it carries a design plan with three fields:
- palette — one brand colour chosen for your subject, plus neutrals and an accent or two;
- typography — a heading and body font pairing;
- sections — three to five layout areas in reading order for an app, or page sections top to bottom for a landing page.
Plus one question, when there is a real ambiguity worth a sentence of your time. Not a form — a single question, or none.
The plan is a recommendation, not a contract. Say "darker, and drop the chart" and the next card says that. The plan is also an enhancement: if the model that writes it is slow or returns nothing usable, the card renders without it and the build still runs.
The card is inert until you press Start. It is stored with the thread, so reloading the page brings it back as a card rather than as a paragraph, and a card you already started cannot start a second job.
What happens after Start
The agent writes a real multi-file project — components, styles, state, the lot — using a small set of file tools: it writes files, reads back what it wrote, and makes targeted edits. It is working in a real project directory, not emitting one long string.
Then it builds and checks:
- Build. The project is built with
npm run buildinside an isolated sandbox container off a pre-baked toolchain image, with no network access. Dependencies are already in the image, so a build cannot reach out and cannot be changed by anything outside it. A build that runs longer than 200 seconds is stopped. - Verify. The built output is loaded in Chrome and looked at. Not "the build exited 0" — the page has to actually render and paint. An app that answers HTTP 200 with a blank body is a failure, and it is caught here rather than by you.
- Deploy. The verified output goes to a public URL on the app domain, and the full source is saved as a downloadable zip.
Those three are what the ▸ build, ▸ verify and ▸ live lines in the thread mean. Each appears when its stage finishes, not when it starts.
Attaching files
Files you attach to a message are available to the build. An image lands at /uploads/<name>.<ext> inside the project, so the agent can reference it directly:
<img src="/uploads/logo.png" alt="Logo">
A zip is unpacked into /uploads/ and its contents are usable the same way.
What Horai does not build
It builds what runs in a browser: static sites and single-page apps — landing pages, dashboards, trackers, tools, calculators, small games. Anything needing its own server-side backend is outside what it produces.
Horai does not generate images or video.
Next
Iterating covers changing an app once it is live.