Reference · build agent internals
How a prompt becomes a deployed site.
This document describes the system that turns a plain-language request into a working, deployed web application. It walks the pipeline end to end - parsing, sandboxed execution, the self-correcting compile loop, and edge deployment - and then drops to the infrastructure and the exact instructions the agent runs under. No abstractions glossed over, no hand-waving.
The agent operates on a closed loop: it reads the request, commits to a specification, writes modular React, and refuses to ship until the TypeScript and Vite toolchain reports a clean build. Everything below is a slice of that loop, in order.
Stage 01 · parsing
Specs & requirements parsing
Before a single file is written, the request is compiled into a typed specification. The raw prompt is normalized, classified by intent (site type, scope, tone), and expanded into a frozen Spec object that pins down the route map, the component tree, the content model, and the design tokens. Code generation reads from this spec, never from the raw prompt - so the same input always resolves to the same structural plan.
01.1The spec shape
The classifier output is validated against a schema. An invalid or underspecified prompt is filled with defensible defaults rather than rejected - the system always produces a buildable plan.
type Spec = { intent: SiteIntent; // landing | docs | portfolio | … routes: RouteSpec[]; tree: ComponentNode; // recursive layout plan content: ContentModel; tokens: DesignTokens; // palette, type scale, spacing} export function parse(prompt: string): Spec { const intent = classify(normalize(prompt)); return freeze(expand(intent)); // typed, immutable plan}Stage 02 · execution
The sandbox environment
Code is written and executed inside an isolated environment running Node, Vite, and the TypeScript compiler. The agent treats it as a real project directory: it scaffolds routes, writes modular React components, installs dependencies, and runs the dev/build commands - all without touching the host.
| Property | Value |
|---|---|
| runtime | Node.js 22 LTS, pinned per project |
| bundler | Vite (the project's own build script) |
| language | TypeScript, strict mode |
| ui | React + Tailwind, file-based routing |
| network | no inbound; egress restricted to an allowlist |
| lifetime | torn down at the end of each turn |
The agent writes components as discrete files and wires them through file-based routes. It never produces one monolithic render function - decomposition is enforced so that a later patch touches the smallest possible surface.
Stage 03 · verification
The self-correction & compiler loop
The agent does not trust its own output. After writing, it runs the type checker and the bundler, captures their stdout and stderr, and parses the diagnostics into structured errors. Each error - with its file, line, column, and code - is fed back to the model as a targeted fix instruction. The loop repeats until the build exits clean or a retry ceiling is hit.
03.1The loop, in pseudocode
async function buildUntilClean(ctx: Ctx) { for (let attempt = 0; attempt < 6; attempt++) { const result = await run("tsc --noEmit && vite build"); if (result.code === 0) return ctx.seal(); // clean → promote const errors = parseDiagnostics(result.stderr); await ctx.model.patch({ errors, files: ctx.touched() }); } throw new Error("retry ceiling exceeded");}03.2Parsing diagnostics
Compiler output is line-oriented and stable. A small parser turns each line into a structured record the model can act on without re-reading the whole log.
// raw tsc outputsrc/routes/index.tsx(42,9): error TS2304: Cannot find name "Eyebrow". // parsed{ file: "src/routes/index.tsx", line: 42, col: 9, code: "TS2304" }Stage 04 · delivery
The git & deployment pipeline
A clean build is sealed and handed to the deployment pipeline. The working tree is committed and pushed to origin/main; that push triggers a fresh install, a production vite build, and an upload of the hashed static bundle to the edge CDN. DNS for the project subdomain is provisioned in the same step, so the URL resolves the instant the upload finalizes.
steps: - install: npm ci - build: npm run build # vite build, pinned preset - bundle: hash + compress .output - upload: edge://objects # immutable, content-addressed - dns: PROJECT.USER.poke.site # wildcard recordBuild output and dependencies are never committed - only source ships. The artifact is content-addressed, so re-deploying an unchanged build is a no-op at the edge.
Infrastructure · isolation
Ephemeral container sandbox
Every agent turn executes in a fresh, isolated container. The container is the unit of isolation: it starts from a clean image, runs exactly one turn's worth of work, and is destroyed on completion. Nothing leaks between turns or between projects, and a compromised or runaway process cannot outlive its container.
| Guarantee | Mechanism |
|---|---|
| Clean slate | fresh container from a pinned base image per turn |
| Isolation | no shared mounts beyond the project's own volume |
| Network | no inbound routes; egress via an allowlist |
| Resource caps | CPU and memory limits enforced by the runtime |
| Teardown | container destroyed at turn end; state lives on the volume |
Infrastructure · state
Persistent filesystem workspaces
Project code lives in a persistent, Git-backed workspace volume, not inside the container. At the start of a turn the volume is mounted into the ephemeral container at /workspace; at teardown it detaches and persists. This split - disposable runtime, durable state - is what lets the agent iterate statefully across many turns while every execution still starts from a clean environment.
# start of turnmount workspace://PROJECT -> /workspacecd /workspace && git status # full history intact # agent edits files, runs build… # end of turngit add -A && git commit && git push origin mainunmount /workspace # volume persists, container dies- 1
Mount
The project volume attaches read-write to the fresh container. Git history, node_modules cache, and prior output are all present.
- 2
Iterate
The agent reads and writes files directly on the volume. Changes are real and durable the moment they are written.
- 3
Commit & detach
The working tree is committed and pushed; the volume detaches cleanly and waits for the next turn.
Infrastructure · build
Vite compilation loop
During the build phase the agent drives the toolchain through a stdin/stdout capture harness. It spawns tsc and vite build as child processes, streams their output, and parses it in real time. Type errors, failed imports, and bundler faults become structured diagnostics that the model consumes to patch code - the same convergent loop from Stage 03, viewed from the systems side.
const proc = spawn("vite", ["build"], { stdio: "pipe" }); let log = "";proc.stdout.on("data", (d) => (log += d));proc.stderr.on("data", (d) => (log += d)); const code = await exit(proc);const diagnostics = parse(log); // file:line:col + codereturn { code, diagnostics };Infrastructure · delivery
Edge CDN & instant DNS
The sealed build is bundled into immutable, content-addressed objects and pushed to a global edge CDN. In the same pipeline step, the project subdomain is provisioned against a wildcard DNS record, so {project}.{username}.poke.site resolves and serves the new build within seconds of the upload completing. TLS is terminated at the edge.
| Concern | Behavior |
|---|---|
| Asset push | static bundle compressed, hashed, uploaded to edge object store |
| Caching | immutable, content-addressed assets; long-lived cache headers |
| DNS | wildcard record; per-project subdomain bound on deploy |
| TLS | certificate served and terminated at the edge |
| Propagation | live within seconds; no manual record changes |
Reference · service map
End-to-end pipeline walkthrough
This is the full path a request travels, named service by service. The orchestrator on the Poke backend owns the lifecycle; every other service is something it spawns, drives, or calls.
AOrchestration - Poke backend
The backend manages the LLM pipeline and the lifecycle of the container manager. It receives the user prompt, runs spec parsing, requests a sandbox, streams instructions to the model, and supervises the correction loop. It is the only stateful coordinator; the sandbox and edge services are driven by it.
BSandbox - Docker + Node.js
The container manager launches an ephemeral Docker container on a compute instance, preloaded with Node.js, Vite, and the TypeScript compiler. The project's persistent volume mounts in; the agent executes its turn; the container is destroyed afterward.
CSelf-correction loop
A custom stdin/stdout capture system wraps the compiler. It parses tsc and vite output into structured errors and returns them to the model for iterative correction, repeating until the build is clean or the retry ceiling is reached.
DCDN & hosting pipeline
The bundled static assets are pushed to the edge hosting pipeline - backed by Vercel and AWS S3 - as immutable objects. The edge serves them globally with long-lived caching and edge-terminated TLS.
EDNS routing - Cloudflare
A call to the Cloudflare API binds the project subdomain to the edge deployment against a wildcard record. Provisioning is dynamic and effectively instant - no manual record edits, no waiting on propagation.
await fetch(CF_API + "/zones/" + zone + "/dns_records", { method: "POST", headers: { Authorization: "Bearer " + CF_TOKEN }, body: JSON.stringify({ type: "CNAME", name: project + "." + user, content: "edge.poke.site", proxied: true }),}); // -> PROJECT.USER.poke.site liveSpecification · UI engine
Design engine & UI guidelines
These are the heuristics and hard constraints the agent applies to every interface it builds. They exist to keep output consistent, responsive, and cheap to render - and to make generated UIs reviewable by a human.
1Tailwind utility framework
Styling compiles exclusively to Tailwind utility classes. There are no bespoke stylesheets per component, which prevents CSS bloat and keeps every spacing, color, and type decision drawn from a shared token set. Consistency is a property of the system, not of reviewer diligence.
2Dark-mode-first heuristics
| Rule | Default |
|---|---|
| Base palette | zinc / neutral surfaces, no pure black |
| Text contrast | ≥ 4.5:1 body, ≥ 3:1 large/heading |
| Borders | subtle, semi-transparent, tinted to surface hue |
| Accent | one calm accent per view, low saturation |
| Elevation | layered shadows over hard outlines |
The engine targets the contrast ratios that modern developer tools rely on: high-contrast text against neutral backgrounds, with boundaries that read clearly without shouting.
3Component modularity
UI is decomposed strictly into discrete, reusable components. A page is a composition of named functional units, never a single monolithic render function. This bounds the blast radius of a patch and makes the self-correction loop precise.
// rejected: one monolithic renderfunction Page() { return ( /* 400 lines */ ) } // enforced: discrete unitsfunction Page() { return ( <Layout> <Hero /><FeatureGrid /><Footer /> </Layout> )}4Layout rules
Layout is mobile-first: base styles target small viewports and scale up through breakpoints. Composition relies on flex and grid constraints rather than fixed measurements, and on fluid units so a layout flexes with its container instead of snapping at hard pixel boundaries. Fixed heights and absolute positioning are last resorts.
5Micro-interactions
Motion is built from vanilla CSS transitions and standard React hooks for state. Heavy animation runtimes are avoided unless a brief genuinely demands them - press feedback, hover states, and disclosure transitions cost nothing on the wire and respect prefers-reduced-motion by default.
Reference · prompt engineering
System instructions
The system runs on fixed instruction templates. The Builder Agent writes and verifies code inside the sandbox; the Poke Orchestrator owns the conversation and dispatches the builder; the Persona & Style engine constrains the orchestrator's output to read like a sharp human, not a model. These contracts are what make behavior reproducible. Switch between them below; the raw templates are shown, not summaries.
| # agent.md - web builder system instruction template |
| ROLE |
| You are a Technical Staff Engineer executing in a secure Node/Vite sandbox. |
| You write production React, verify it against the compiler, and ship only |
| builds that pass. You do not narrate; you produce code and corrections. |
| --- |
| OUTPUT & FILE-WRITING CONSTRAINTS |
| - Emit every file inside a delimited block tagged with its path: |
| ``tsx path=src/components/Hero.tsx … |
| - One block per file. Never interleave prose inside a code block. |
| - Write complete files, not fragments or diffs, unless patching a known range. |
| - Never invent file paths; resolve them against the existing route tree. |
| - Extraction is exact: whatever is inside the block is written verbatim. |
| --- |
| FRAMEWORK ENFORCEMENT |
| - Stack is fixed: React + TypeScript + Tailwind on TanStack Start (Vite). |
| - TypeScript strict mode. No any; type every prop and return. |
| - Tailwind utilities only. No inline style objects for layout, no ad-hoc CSS |
| files. Pull spacing, color, and type from the shared token set. |
| - Routing is file-based under src/routes. Do not hand-roll a router. |
| - Never swap the framework, bundler, or build script. |
| --- |
| STATE & ROUTING |
| - Local UI state uses React hooks (useState, useReducer). No global store |
| unless the spec requires cross-route persistence. |
| - Server logic uses framework server functions; never fetch secrets client-side. |
| - Each route is a file; shared UI lives in src/components as discrete units. |
| --- |
| ERROR CORRECTION LOGIC |
| - After writing, run: tsc --noEmit && vite build. |
| - Capture stdout and stderr. Parse each diagnostic into { file, line, col, code }. |
| - Address the root diagnostic first; re-run before assuming cascades are fixed. |
| - Patch the smallest surface that resolves the error. Do not rewrite whole files |
| to fix a single type error. |
| - Loop until exit code 0 or the retry ceiling (6) is reached. |
| - On ceiling: stop and report failure. Never ship a build that does not compile. |
| --- |
| DISCIPLINE |
| - Decompose UI into reusable components; no monolithic render functions. |
| - Mobile-first, responsive, accessible (labels, focus states, contrast). |
| - No dead controls. Every button, link, and handler does something real. |