OpenUI is an open source framework (MIT) that makes an LLM respond with interface components (tables, charts, forms, buttons) instead of text, and renders them on screen while the model is still writing. It achieves this with OpenUI Lang, a compact language that, according to its own authors’ benchmark, uses about half the tokens of equivalent JSON. Version 1.0 of the language came out on October 12.

yoDEV Tested · October 18, 2026 We generated a project with the OpenUI 0.6.0 CLI in our sandbox, verified its types, and ran OpenUI Lang programs through the 1.0.1 parser; we did not run chat against a model. The results we report as ours come from that test.
What is generative UI and what does OpenUI do?
Generative UI means that the model’s response is the interface. You ask an assistant for quarterly sales and, instead of a markdown table, you get a real bar chart with a button below it. OpenUI is a framework for building that, created by Thesys, with 11.7K stars on GitHub and runtimes for React, Vue, Svelte, and Angular.
The flow has five steps:
- You define (or reuse) a component library, each with its props typed in Zod.
- OpenUI generates the system prompt from that library, so the model only knows the components you allow.
- The model responds in OpenUI Lang.
- The response arrives at the client in streaming.
- The renderer draws it progressively as tokens arrive.
The control point is in step 2: the model can’t invent a component that isn’t in your library. If it tries, the parser rejects it (we verified this below).
How do you write OpenUI Lang?
It’s one statement per line, name = expression, with components called by position. This is the program we used in our test, written against the default library that comes with the generated project:
root = Stack([card])
card = Card([header, chart, askBtn])
header = CardHeader("Sales by Quarter", "Sample Data")
chart = BarChart(["Q1", "Q2", "Q3"], [Series("Sales", [120, 180, 150])])
askBtn = Button("Explain", @ToAssistant("Explain this chart"))
root is the entry point. Names can be used before they’re defined (card references header, which comes two lines later) and show nothing until they exist. Calls starting with @ are built-ins: @ToAssistant sends a message to the assistant when the user clicks the button.
Why lines and not JSON? Because a half-written JSON object isn’t valid until the last brace closes, while each line of OpenUI Lang is complete on its own. We passed the program to the streaming parser one line at a time, and this is what could be rendered after each one:
| After line | Renderable tree |
|---|---|
| 1 | Stack (empty) |
| 2 | Stack → Card (empty) |
| 3 | Card → [CardHeader] |
| 4 | Card → [CardHeader, BarChart] |
| 5 | Card → [CardHeader, BarChart, Button] |
Two other results from the same test:
- Order matters. With the
rootline moved to the end, nothing could be rendered until the last line arrived. The version 1.0 release notes say exactly that: writerootfirst, as the generated system prompt indicates. - Unknown components are rejected. A program that called
Sparkline, which isn’t in the library, returned anunknown-componenterror with the list of components that do exist, and rendered nothing in its place.
Does it really use half the tokens of JSON?
According to the manufacturer’s measurement, yes: about 52 percent fewer overall, and up to 67 percent fewer in the best case. These are self-reported figures. Thesys measured them with tiktoken (GPT-5 encoder) across seven interface scenarios, comparing OpenUI Lang with two JSON streaming formats: Vercel’s json-render and Thesys’s own C1 JSON.
| Scenario | Vercel JSON-Render | Thesys C1 JSON | OpenUI Lang |
|---|---|---|---|
| simple-table | 340 | 357 | 148 |
| contact-form | 893 | 849 | 294 |
| dashboard | 2,247 | 2,261 | 1,226 |
| Total (7 scenarios) | 10,180 | 9,948 | 4,800 |
The methodology and steps to reproduce it are published in the benchmarks/ folder of the repo, something most manufacturer benchmarks don’t offer. We didn’t reproduce it ourselves.
Fewer tokens matter doubly: you pay less per response, and the interface appears sooner, because the model has less to write to complete the component.
OpenUI, A2UI, or json-render?
All three solve the same problem (getting an agent to respond with interface instead of just text), but with different bets. A2UI is Google’s protocol and json-render is Vercel’s format; both are based on JSON. OpenUI’s README includes this comparison, made by the manufacturer about its competitors, so read it as positioning rather than independent evaluation:
| OpenUI | json-render (Vercel) | A2UI (Google) | CopilotKit OpenGenUI | |
|---|---|---|---|---|
| Tokens | 1x | 3x | 3x | 4x |
| Latency (60 tok/s) | 4.9s | 14.2s | 14.2s | ~20s |
| Components | Library + custom | Library + custom | Custom only | None |
| Platforms | Web, mobile, email | Web, mobile, PDF, email, video | Web, iOS, Android | Web |
| Chat UI included | Yes | No | No | Yes |
Two nuances the table reveals: json-render covers more output formats (PDF and video), and A2UI has native renderers for iOS and Android. OpenUI doesn’t compete only against A2UI: it also integrates it. The @openuidev/a2ui package is an A2UI protocol client that uses OpenUI Lang for component content, so you don’t have to choose one or the other.
How do you install OpenUI?
The fastest path is the CLI, which generates a complete Next.js app with streaming chat, the default component library, and an agent:
npx @openuidev/cli@latest create --name genui-chat-app
Use --name or a folder as an argument, not both: in our test, passing both stopped the CLI with an error. You can choose the agent backend with --backend-framework (langgraph by default, or vercel-ai-sdk).
What we got: a Next.js 16 project with a LangGraph agent, a /api/chat route, a model selector, an example weather tool, and an AGENTS.md file with OpenUI instructions for code agents. The project passed type checking without errors with the 1.0.1 packages.
You don’t need an account to generate the project, but you do to run the chat. The next steps the CLI indicates are:
cd genui-chat-app
npx @openuidev/cli@latest generate-api-key
npm run dev
generate-api-key logs into OpenUI Cloud and writes THESYS_API_KEY to .env. This is because the generated project doesn’t call OpenAI or Anthropic directly: its agent sends all model calls through OpenUI Gateway (Thesys’s API) and saves conversation history in OpenUI Cloud.
One more detail: the CLI collects anonymous usage analytics by default. You can disable them with --no-telemetry or the DO_NOT_TRACK=1 environment variable.
Is OpenUI free?
The framework is: the packages are MIT and you can use them without paying anything. OpenUI Gateway, the service the generated project uses, is commercial. At the time of publishing this note, its pricing page indicated:
- A Free plan with 3,000 API calls per month, which includes bring-your-own-key (BYOK) and a set of free models.
- Build and Grow plans at $49 and $499 per month, with more calls.
- No markup on model tokens: you pay the provider’s price, or the provider bills you directly if you use BYOK.
- Autofix, which repairs invalid OpenUI Lang on the fly, charged per correction.
A detail worth reading for any CTO: according to that same page, free models have usage limits and request data can be used for training, while paid models don’t retain data. It’s good for prototyping; it’s not where your customers’ data should go.
Can you use OpenUI without OpenUI Cloud?
Yes. The documentation has a self-hosting guide where you run your own backend with your own provider keys: a route that reads OPENAI_API_KEY or ANTHROPIC_API_KEY from the server environment, a fetchLLM client that points to your own /api/chat, and restStorage to save conversations in your own database. Anthropic needs an extra step, because OpenUI doesn’t come with an Anthropic adapter: the route translates the stream to AG-UI events and the client uses agUIAdapter().
The nuance is that the defaults point the other way. The generated project is built on top of the Gateway, and the AGENTS.md it creates tells your code agent to send model calls through it. If you want a self-hosted setup, ask your agent explicitly for it when you commission it to build it.
What changes in OpenUI Lang 1.0?
Version 1.0 (PR #1348, released October 12) breaks compatibility and adds three capabilities to component libraries:
- Custom actions with
defineAction, so a button can trigger your own logic (for example, copying an order ID to the clipboard) and your app receives it typed inonAction. - Library functions with
defineFunction, which the model calls just like built-ins, such as@Percent(done, total). library.extend(), to derive a library from another, adding, replacing, or removing components without touching the base.
The upgrade is all-in: @openuidev/lang-core and @openuidev/react-lang 1.0, plus the server that generates the system prompt, because a 1.0 prompt teaches syntax that a 0.x client won’t execute. At the time of publishing this note, the Vue, Svelte, and Angular runtimes were still at version 0.4 (OpenUI Lang 0.x); for now, the 1.0 features are React-only.
Is this the same as OpenUI from Weights & Biases?
No. wandb/openui is an earlier, unrelated project by Weights & Biases: you describe an interface in natural language and it generates HTML you can convert to React or Svelte, a kind of open source v0. Thesys’s OpenUI isn’t a page generator: it’s a language and runtime so your own product responds with interfaces. If you search for “openui” you’ll find both. The README also warns that OpenUI has no official cryptocurrency or token.
How do you use it with Claude Code, Codex, or Cursor?
OpenUI publishes an Agent Skill that teaches your code agent the language, the SDK packages, and how to debug malformed output:
npx skills add thesysdev/skills --skill openui
In an existing project, npx @openuidev/cli@latest setup-agent adds the same instructions to your AGENTS.md, between the markers <!-- openui:start --> and <!-- openui:end -->, so if you run it again it updates them without touching the rest of the file. As we saw before, those instructions favor the Gateway.
Who is OpenUI for?
For teams building assistants, copilots, or agents whose responses today end in a long text the user has to read: dashboards, comparisons, forms, approvals. If your product already parses JSON from an LLM to draw components, OpenUI replaces that fragile layer with a typed, streaming contract the model can’t break. If what you’re looking for is for your interface and your agent to share the same functions, Agent-Native might also interest you. And if you just need a chatbot that responds with text, OpenUI adds complexity you don’t need.
What about you? Does your product already show components generated by an LLM, or does it still only respond with text?
- Text or markdown only
- JSON that I parse into components
- Tool calls that trigger components
- I prefer another option (tell us which)
Comment below or, if this article reached you by email, reply directly to the email: your response will be published here.
Related: Hallmark: The Skill That Makes AI-Generated Interfaces Stop Looking… AI-Generated