Your AI draws the interface. uivet proves it works.
ChatGPT apps, MCP apps, A2UI: models now render UI at runtime, and every generation is different. uivet samples, renders, checks, and gates them in CI.
Early access, OSS core. No spam.
The problem
Same prompt, different UI every run.
Nondeterminism breaks pixel-diff testing: the output changes every run, so a visual regression tool flags every render as a difference and tells you nothing.
Text evals never see the rendered screen. They score the model's words, not the layout, the dropped field, or the contrast failure a real user would hit.
How it works
Sample, render, check, gate.
- 01 Generate Produce N samples per scenario, so you measure the spread, not one lucky render.
- 02 Render Load every sample in real headless Chromium and capture the painted screen.
- 03 Check Verify data fidelity, run axe-core and layout heuristics, catch console errors, score with an AI judge.
- 04 Gate Compare against a saved baseline and set CI exit codes so a regression fails the build.
Gates in CI
A regression fails the build.
Exit codes gate your pipeline: pass 0, regression 1.
designer agreement (Cohen's kappa) on generated-UI quality, arXiv 2604.09876
demo generations rendered, judged, and gated by uivet
is all it takes to break trust (documented in ASSETS '25)
What it catches
Failures a text eval never sees.
A value in your data never renders. uivet checks that every field actually appears on screen.
axe-core rules caught in the demo: color-contrast (serious), heading-order, landmark-one-main, region (moderate).
Overflow, overlap, and collapsed containers flagged by layout heuristics on the rendered page.
Runtime errors and warnings the render logs, captured while the sample loads.
Judge scores compared to a committed baseline, so a quiet regression fails the gate.
High score stddev across samples surfaces scenarios where the model renders inconsistently.
Where it fits
The gap between visual regression and text evals.
Percy, Chromatic, Applitools: built for deterministic committed code, they expect identical output every run.
Braintrust, Langfuse: judge text, not rendered UI, so a broken layout scores fine.
Renders every sample and judges the actual screen, then gates the result in CI.
Configuration
One config file, scenarios in, gates out.
import type { UivetConfig } from "./src/types.ts"
const config: UivetConfig = {
scenarios: [
{
id: "flight-results",
prompt: "A flight results page with airline, times, duration, stops, and price.",
runs: 3,
data: {
route: "New York (JFK) to Zürich (ZRH)",
flights: [
{ airline: "SWISS", departure: "18:40", arrival: "08:25", price: "$1,248" },
{ airline: "United", departure: "21:30", arrival: "14:20", price: "$986" },
],
},
},
],
}
export default config
$bun run src/cli.ts run --config uivet.config.ts$bun run src/cli.ts run --config uivet.config.ts --save-baselineQuestions
FAQ
Which models does it work with?
Is it open source?
How does it plug into CI?
Does an AI judge actually work?
Ship generated UI you can trust.
Early access, OSS core. No spam.