GistUI does not call a model for you and does not care which one you use. The contract has two halves:
- Give the model GistUI’s system prompt, where you call it.
- Send the model’s text to the browser, unchanged, as a stream.
import { prompt } from "@gistui/catalog";
const system = prompt().text;
// prompt() the whole reply is one UI
// prompt({ mode: "inline" }) chat text, with the UI in ```gistui fences
// prompt({ mode: "edit" }) the reply is a patch to a UI that is already shownThe prompt is byte-stable: the same options give the same bytes, so provider prompt caching hits.
Pick your setup
| You use | Page | Text stream comes from |
|---|---|---|
The Vercel AI SDK (ai) |
Vercel AI SDK | result.toTextStreamResponse() |
| OpenAI’s API or SDK | OpenAI | textDeltas(res, "openai") |
| Anthropic’s API or SDK | Anthropic | textDeltas(res, "anthropic") |
| Vercel AI Gateway, OpenRouter, Groq, Together, Ollama, vLLM | OpenAI-compatible APIs | textDeltas(res, "openai") |
| Cloudflare Workers AI | Cloudflare Workers AI | the AI SDK provider, or the OpenAI-compatible endpoint |
| An AG-UI agent (LangGraph, CrewAI, Mastra…) | AG-UI | textDeltas(res, "agui") |
Reading a provider’s stream
Providers send server-sent events, not plain text. @gistui/server turns them into text on any JavaScript runtime (Node, Bun, Deno, Edge, Workers).
npm i @gistui/serveryarn add @gistui/serverpnpm add @gistui/serverbun add @gistui/serverimport { textDeltas, toReadable } from "@gistui/server";
// textDeltas(response, format): an async iterable of text
// format: "openai" | "anthropic" | "ai-sdk" | "agui" | "text"
return new Response(toReadable(textDeltas(res, "openai")));textDeltas throws when the provider reports an error (a non-ok response, or an error event in the stream), so a failed call is never an empty answer. Leaving the loop early cancels the upstream request.
Prompt options
| Option | Use |
|---|---|
mode |
"full" (default), "inline" for chat, "edit" for patches |
tools |
Describe the tools @query and @mutation may call: [{ name: "get_sales", args: "{range:str}" }] |
groups |
Only some component groups, for a smaller prompt: ["Layout", "Content", "Data"] |
preamble |
Text placed before everything else: your product, the assistant’s role |
rules |
Extra rules appended to the built-in ones |
examples |
"one" (default), "none", or your own example programs |
guide |
false leaves the design guide out; a string replaces it |
const system = prompt({
mode: "inline",
preamble: "You are the assistant inside Acme Analytics.",
tools: [{ name: "get_sales", args: "{range:str}" }],
}).text;Which models work well
Any model that follows a system prompt and can stream. On the public benchmark, gpt-oss-120b writes 88% of screens valid as written, and 100% after autofix. See Benchmarks for the numbers per model.
Small models make more mistakes on large screens. Autofix repairs them in code, and repairStream with a complete function can ask your model to fix what code could not: see Autofix and repair.