| name | genui-builder |
| description | Build streaming GenUI-capable TSX/HTML artifacts for Macaron previews. Use when the user asks an agent to create a GenUI UI, GenUI-enabled HTML, standalone renderable HTML from TSX, a visual TSX preview that should run through Macaron GenUI, a browser runtime that displays model-generated UI while tokens stream, or wants to validate/live-preview GenUI output with the @genui/cli package. |
GenUI Builder
Use this skill to produce streaming GenUI App.tsx/HTML artifacts. Default to streaming model output and incremental preview refresh; do not build one-shot "wait for full TSX, then render" experiences unless the user explicitly asks for non-streaming output.
Preferred path: render_ui MCP tool
If the mcp__macaron.render_ui tool is exposed to you, call it directly with the complete TSX module in its code field — the host mounts the component inline in the conversation. The tool's own description already carries the authoring rules for $macaron/ui, streaming write order, and quality constraints. Do NOT curl anything or emit markdown TSX fences when this tool is available.
Local authoring rules (fallback)
If render_ui is not exposed (older host or a bare CLI), fall back to writing a self-contained TSX module and use the CLI below to validate or render it. Detailed constraints and common fixes are in references/tsx-output.md.
Optionally, if the runtime allows network egress, you MAY fetch the canonical live authoring prompt for cross-check — but only if you already have a specific ambiguity to resolve. Do NOT fetch it prophylactically before every render:
curl -fsSL https://genui.macaron.im/api/system-prompt
If that command errors (DNS blocked, no network, non-2xx), silently proceed with the local rules — do not surface the failure to the user.
CLI
The CLI is optional. Prefer direct streaming runtimes when the user wants an HTML harness or GenUI capability inside a page. Use the CLI for validation, standalone one-shot export, or when the user explicitly asks for the CLI.
Use this exact pinned command unless the user provides a newer one:
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767
The CLI supports:
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 lint App.tsx
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 check App.tsx
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 build App.tsx -o index.html
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 dev App.tsx -p 4173 --host 127.0.0.1
Before relying on the CLI, check that Bun/Bunx is available:
command -v bunx || command -v bun
If Bun is missing, still create App.tsx and explain that CLI validation/build could not run.
Streaming Policy
Streaming is mandatory by default.
- Set OpenAI-compatible requests with
stream: true.
- Read SSE
data: chunks incrementally.
- Append each
choices[0].delta.content or tool-call argument delta into the current TSX buffer.
- Update the visible code buffer immediately as tokens arrive.
- Refresh the preview during the stream, not only after
[DONE].
- Use
partial-react / GenUIRenderer.pushCode(...) when available.
- If
partial-react is unavailable, use partial-tsx / normalizeGeneratedTsx(...) to complete prefix-growing TSX before compiling snapshots.
- Keep the last good rendered UI visible while a new partial frame fails to compile.
- Do a final complete render when the stream finishes.
- If an upstream proxy is used, it must pass through
text/event-stream without buffering. Include Cache-Control: no-store, no-transform and avoid await response.text() / arrayBuffer() before returning to the browser.
Non-streaming is acceptable only for static file export, offline examples, or explicit user direction.
Workflow
- Clarify the target artifact:
App.tsx only, standalone index.html, or a small project folder containing both.
- Fetch the live GenUI system prompt and scan for current constraints.
- For model-backed generation, implement streaming first: SSE request, incremental code buffer, partial TSX completion, preview refresh, final render.
- Write a single self-contained
App.tsx with default export function App when creating a TSX artifact.
- Keep imports GenUI-compatible; prefer local primitives from
$macaron/ui and chart primitives from $macaron/ui/charts.
- Validate:
- Run
lint App.tsx.
- Run
check App.tsx when available.
- Run
build App.tsx -o index.html when the user asked for HTML.
- If validation fails, fix the TSX and rerun the failed command.
- For interactive review, start a local server and give the local URL.
Output Rules
- Treat a GenUI HTML runtime as incomplete if it only renders after the whole model response finishes.
- Do not paste GenUI TSX in chat as a substitute for creating files when the user asked for an artifact.
- Do not create extra scaffolding unless the user asked for a project; a single
App.tsx plus generated HTML is usually enough.
- Do not add external runtime data fetching; use provided data, local constants, or clearly marked sample content.
- Keep every visible control functional. Remove inert buttons, switches, tabs, and menu items.
- Use stable keys from data IDs/slugs, never array indexes.
- Prefer compact, embeddable surfaces. GenUI output is hosted inside another product surface, not a full website shell.
Streaming HTML Pattern
For browser HTML harnesses, implement this shape:
const response = await fetch('/v1/chat/completions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model, stream: true, messages }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let tsx = '';
for (;;) {
const { done, value } = await reader.read();
buffer += decoder.decode(value || new Uint8Array(), { stream: !done });
const events = buffer.split(/\r?\n\r?\n/);
buffer = events.pop() || '';
for (const event of events) {
const data = event.split(/\r?\n/).filter((line) => line.startsWith('data:')).map((line) => line.slice(5).trimStart()).join('\n').trim();
if (!data || data === '[DONE]') continue;
const payload = JSON.parse(data);
tsx += payload.choices?.[0]?.delta?.content ?? '';
updateCodePane(tsx);
renderPartialTsx(tsx);
}
if (done) break;
}
renderFinalTsx(tsx);
Use partial-react when it can be imported:
const renderer = await GenUIRenderer.create(root, { preserveStateOnUpdate: true, flushMode: 'immediate' });
renderer.pushCode(delta);
renderer.finish(finalCode);
Fallback snapshot rendering:
import { normalizeGeneratedTsx } from 'https://esm.sh/partial-tsx@0.0.1?dev';
const source = normalizeGeneratedTsx(partialTsx);
Common Deliverables
For a standalone HTML request:
mkdir -p genui-output
$EDITOR genui-output/App.tsx
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 lint genui-output/App.tsx
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 check genui-output/App.tsx
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 build genui-output/App.tsx -o genui-output/index.html
For an agent-facing TSX artifact:
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 lint App.tsx
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 check App.tsx
For live preview:
bunx genui@https://pkg.pr.new/MindLab-Research/macaron-genui-demo/@genui/cli@00b6767 dev App.tsx -p 4173 --host 127.0.0.1
For a model-backed HTML runtime, do not use the CLI as the default. Build a page that streams model output into a GenUI renderer and verify during generation that the code pane grows before the final response completes.