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.

uivet render, flight-results, run 1 of 3
A generated flight results page rendered and checked by uivet, showing airlines, times, and prices.

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.

  1. 01 Generate Produce N samples per scenario, so you measure the spread, not one lucky render.
  2. 02 Render Load every sample in real headless Chromium and capture the painted screen.
  3. 03 Check Verify data fidelity, run axe-core and layout heuristics, catch console errors, score with an AI judge.
  4. 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.

uivet run
$ uivet run --config uivet.config.ts
scenario mean min-max stddev fidelity a11y c+s gate
------------------------------------------------------------------------------
flight-results 9 9-9 0 100% 4 PASS
expense-form 9.33 9-10 0.47 100% 3 PASS
metrics-dashboard 9 9-9 0 100% 3 PASS
baseline: compared
result: PASS (exit 0)
$ uivet run --config uivet.config.ts
scenario mean min-max stddev fidelity a11y c+s gate
------------------------------------------------------------------------------
flight-results 9 9-9 0 100% 4 PASS
expense-form 7.9 6-9 1.20 100% 4 FAIL
metrics-dashboard 9 9-9 0 100% 3 PASS
baseline: compared
regression: mean score 9.33 -> 7.9
regression: new a11y rules: color-contrast
result: FAIL (exit 1)

Exit codes gate your pipeline: pass 0, regression 1.

0.25

designer agreement (Cohen's kappa) on generated-UI quality, arXiv 2604.09876

9 of 9

demo generations rendered, judged, and gated by uivet

1 silently dropped field

is all it takes to break trust (documented in ASSETS '25)

What it catches

Failures a text eval never sees.

silent data drops

A value in your data never renders. uivet checks that every field actually appears on screen.

a11y violations

axe-core rules caught in the demo: color-contrast (serious), heading-order, landmark-one-main, region (moderate).

broken layout

Overflow, overlap, and collapsed containers flagged by layout heuristics on the rendered page.

console errors

Runtime errors and warnings the render logs, captured while the sample loads.

quality drift vs baseline

Judge scores compared to a committed baseline, so a quiet regression fails the gate.

flaky generations

High score stddev across samples surfaces scenarios where the model renders inconsistently.

Where it fits

The gap between visual regression and text evals.

visual regression

Percy, Chromatic, Applitools: built for deterministic committed code, they expect identical output every run.

LLM evals

Braintrust, Langfuse: judge text, not rendered UI, so a broken layout scores fine.

uivet

Renders every sample and judges the actual screen, then gates the result in CI.

Configuration

One config file, scenarios in, gates out.

uivet.config.ts
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-baseline

Questions

FAQ

Which models does it work with?
Any generator. The built-in one uses Gemini, or you point it at your own module that returns HTML.
Is it open source?
The core is MIT. The waitlist is for the hosted CI cloud beta.
How does it plug into CI?
One command, exit codes. A baseline file is committed to the repo, and a regression against it fails the build.
Does an AI judge actually work?
Deterministic checks run first: fidelity, axe, layout, console. The judge adds trend signal, calibrated per team.

Ship generated UI you can trust.

Early access, OSS core. No spam.