Generative UI benchmark
9
stars
2
commits
TypeScript
primary language
Sep 8, 2026
updated
How reliably do today's models generate working UI?
One catalog of 70 components, 46 screen briefs, four attempts each, and three generative-UI formats judged by their own SDKs: OpenUI Lang, Google A2UI (v0.9), and Vercel json-render (0.19).
Every raw model output and every scored verdict is committed here. Anyone can rescore the data offline and diff against the published results, or add a new model with one command.
catalog/public-catalog.json is the reference surface;
node tools/check-catalogs.ts verifies the three protocol catalogs stay
equivalent to it.The headline board (six models, one seat per company, all three formats) is on the benchmark page. OpenUI-only runs beyond it, same condition:
| Label | Model | Provider | Complete |
|---|---|---|---|
grok | x-ai/grok-4.6 | OpenRouter | 183/184 (99.5%) |
gemini37 | google/gemini-3.7-flash | OpenRouter | 182/184 (98.9%) |
sonnet5 | claude-sonnet-5 | Anthropic | 181/184 (98.4%) |
opus5 | claude-opus-5 | Anthropic | 177/184 (96.2%) |
sonnet46 | claude-sonnet-4-6 | Anthropic | 171/184 (92.9%) |
oxalpha | stealth/ox-alpha | OpenRouter | 169/184 (91.8%) |
glm | z-ai/glm-5.3 | OpenRouter | 167/184 (90.8%) |
qwen27blow | qwen/qwen3.8-27b, reasoning low | OpenRouter | 160/184 (87.0%) |
deepseekflash | deepseek/deepseek-v4-flash-0731 | OpenRouter | 157/183 (85.8%) |
qwen27bmed | qwen/qwen3.8-27b, reasoning medium | OpenRouter | 157/183 (85.8%) |
qwen27bhigh | qwen/qwen3.8-27b, reasoning high | OpenRouter | 157/184 (85.3%) |
deepseekpro | deepseek/deepseek-v4-pro-0813 | OpenRouter | 155/184 (84.2%) |
luna | gpt-5.6-luna | OpenAI | 154/184 (83.7%) |
qwen27b | qwen/qwen3.8-27b, reasoning minimal | OpenRouter | 145/184 (78.8%) |
flashlite | google/gemini-3.5-flash-lite | OpenRouter | 144/184 (78.3%) |
lingtiny | inclusionai/ling-3.0-tiny | local (llama.cpp) | 18/184 (9.8%) |
The four qwen27b* labels are one model at four reasoning efforts. All
committed results are scored under lang-core 0.2.16.
Node >= 22.18; the harness runs TypeScript directly. The openui scorer is
@openuidev/lang-core pinned to exactly 0.2.16; the pin is part of the
published condition.
npm install
# A2UI's scorer needs the official python SDK at the pinned revision:
python3 -m venv .venv
.venv/bin/pip install antlr4-tools
.venv/bin/pip install "a2ui-agent-sdk @ git+https://github.com/a2ui-project/a2ui@29b715fa89fc5bb8351d2ea0116f03d4f2e212f2#subdirectory=agent_sdks/python/a2ui_agent"
A2UI_PYTHON=.venv/bin/python node score.ts # all models
A2UI_PYTHON=.venv/bin/python node score.ts gemini # one model
score.ts rewrites results/results-<model>.json from the raws alone, so a
diff against the committed results is the integrity check. Without
A2UI_PYTHON it scores openui and json-render and leaves results files
untouched. raw/<label>/truncated.json records generations that hit the
output ceiling. Token and cost tables: node tools/count-tokens.ts and
node tools/cost-estimate.ts.
BENCH_MODEL=google/gemini-3.6-flash BENCH_LABEL=gemini \
OPENROUTER_API_KEY=... node run.ts openui jsonrender a2ui
BENCH_PROVIDER selects openrouter (default), openai, anthropic, google, or
local. Raws are idempotent, so an interrupted run resumes by re-running the
same command. See the header of run.ts for every knob. Then
node score.ts <label>. New briefs follow briefs/DESIGN.md; a new protocol
is one folder under protocols/ exposing a system prompt and an
evaluate(text, {reqs}) verdict.
| Path | What it is |
|---|---|
briefs/ | The 46 briefs as data and the band design. |
catalog/public-catalog.json | The shared 70-component catalog. |
protocols/ | One folder per format: catalog, prompt, validator, each built on its own SDK. |
run.ts | Generation runner. |
score.ts | Offline scorer, no API keys needed. |
tools/ | Catalog check, token counts, cost estimates, blank-screen floor. |
raw/ | Every scored model output, verbatim. |
results/ | Scored verdicts per model, one row per run. |
package-lock.json and the python install command
above. The files under raw/ are verbatim model outputs, published as the
benchmark's data record.2 commits
TypeScript
79.8%
Python
20.0%
Generative UI benchmark
9
stars
2
commits
TypeScript
primary language
Sep 8, 2026
updated
How reliably do today's models generate working UI?
One catalog of 70 components, 46 screen briefs, four attempts each, and three generative-UI formats judged by their own SDKs: OpenUI Lang, Google A2UI (v0.9), and Vercel json-render (0.19).
Every raw model output and every scored verdict is committed here. Anyone can rescore the data offline and diff against the published results, or add a new model with one command.
catalog/public-catalog.json is the reference surface;
node tools/check-catalogs.ts verifies the three protocol catalogs stay
equivalent to it.The headline board (six models, one seat per company, all three formats) is on the benchmark page. OpenUI-only runs beyond it, same condition:
| Label | Model | Provider | Complete |
|---|---|---|---|
grok | x-ai/grok-4.6 | OpenRouter | 183/184 (99.5%) |
gemini37 | google/gemini-3.7-flash | OpenRouter | 182/184 (98.9%) |
sonnet5 | claude-sonnet-5 | Anthropic | 181/184 (98.4%) |
opus5 | claude-opus-5 | Anthropic | 177/184 (96.2%) |
sonnet46 | claude-sonnet-4-6 | Anthropic | 171/184 (92.9%) |
oxalpha | stealth/ox-alpha | OpenRouter | 169/184 (91.8%) |
glm | z-ai/glm-5.3 | OpenRouter | 167/184 (90.8%) |
qwen27blow | qwen/qwen3.8-27b, reasoning low | OpenRouter | 160/184 (87.0%) |
deepseekflash | deepseek/deepseek-v4-flash-0731 | OpenRouter | 157/183 (85.8%) |
qwen27bmed | qwen/qwen3.8-27b, reasoning medium | OpenRouter | 157/183 (85.8%) |
qwen27bhigh | qwen/qwen3.8-27b, reasoning high | OpenRouter | 157/184 (85.3%) |
deepseekpro | deepseek/deepseek-v4-pro-0813 | OpenRouter | 155/184 (84.2%) |
luna | gpt-5.6-luna | OpenAI | 154/184 (83.7%) |
qwen27b | qwen/qwen3.8-27b, reasoning minimal | OpenRouter | 145/184 (78.8%) |
flashlite | google/gemini-3.5-flash-lite | OpenRouter | 144/184 (78.3%) |
lingtiny | inclusionai/ling-3.0-tiny | local (llama.cpp) | 18/184 (9.8%) |
The four qwen27b* labels are one model at four reasoning efforts. All
committed results are scored under lang-core 0.2.16.
Node >= 22.18; the harness runs TypeScript directly. The openui scorer is
@openuidev/lang-core pinned to exactly 0.2.16; the pin is part of the
published condition.
npm install
# A2UI's scorer needs the official python SDK at the pinned revision:
python3 -m venv .venv
.venv/bin/pip install antlr4-tools
.venv/bin/pip install "a2ui-agent-sdk @ git+https://github.com/a2ui-project/a2ui@29b715fa89fc5bb8351d2ea0116f03d4f2e212f2#subdirectory=agent_sdks/python/a2ui_agent"
A2UI_PYTHON=.venv/bin/python node score.ts # all models
A2UI_PYTHON=.venv/bin/python node score.ts gemini # one model
score.ts rewrites results/results-<model>.json from the raws alone, so a
diff against the committed results is the integrity check. Without
A2UI_PYTHON it scores openui and json-render and leaves results files
untouched. raw/<label>/truncated.json records generations that hit the
output ceiling. Token and cost tables: node tools/count-tokens.ts and
node tools/cost-estimate.ts.
BENCH_MODEL=google/gemini-3.6-flash BENCH_LABEL=gemini \
OPENROUTER_API_KEY=... node run.ts openui jsonrender a2ui
BENCH_PROVIDER selects openrouter (default), openai, anthropic, google, or
local. Raws are idempotent, so an interrupted run resumes by re-running the
same command. See the header of run.ts for every knob. Then
node score.ts <label>. New briefs follow briefs/DESIGN.md; a new protocol
is one folder under protocols/ exposing a system prompt and an
evaluate(text, {reqs}) verdict.
| Path | What it is |
|---|---|
briefs/ | The 46 briefs as data and the band design. |
catalog/public-catalog.json | The shared 70-component catalog. |
protocols/ | One folder per format: catalog, prompt, validator, each built on its own SDK. |
run.ts | Generation runner. |
score.ts | Offline scorer, no API keys needed. |
tools/ | Catalog check, token counts, cost estimates, blank-screen floor. |
raw/ | Every scored model output, verbatim. |
results/ | Scored verdicts per model, one row per run. |
package-lock.json and the python install command
above. The files under raw/ are verbatim model outputs, published as the
benchmark's data record.2 commits
TypeScript
79.8%
Python
20.0%