Skip to Content
Vektos
Anecdotes

Valid and empty

Two generated UI specs passed json-render's validation and showed nothing. The root pointed at an element that was never written, and the check that said so was a different function.

Date: 2026-11-09. Context: the generative UI spike (spike/genui, journal ch. 42).

What happened

The spike asked the same free model, three times with each prompt, for the same view: a business account's balance, money in and out, two failed direct debits, three transactions. Our renderer's three answers rendered. json-render's first two came back from catalog.validate with success: true, and rendered as an empty string.

The JSONL told why. The model began with {"op":"add","path":"/root","value":"main"}, the name used in the example of json-render's prompt, then built its view under another name, mainContainer. The root pointed at nothing. catalog.validate checks each element's type and props, not the references between them; validateSpec, a second function, does report "Root element "main" not found"; autoFixSpec does not repair it. The third answer rendered, with every amount written as a $template string ("48,210.55 EUR") instead of a number in a Stat.

What we learned

  • A valid spec can be an empty view. Props that pass their schemas say nothing about whether the tree holds together, or whether anything reaches the screen.
  • A prompt teaches what it describes. json-render's prompt explains state, repeat, dynamic expressions and templates at length, for interactive UIs. Asked for a read-only overview, the model used all of them, and the more machinery a spec has, the more ways it can come apart. Ours describes ten components and one shape.
  • Formatting moves to wherever the spec lets it. Given a template string, the model formatted the amount itself, past FormatNumber: the same mistake the design system exists to prevent, made by a model instead of an agent writing code.

What it means for Vektos

It is the benchmark's own lesson in a new place. A page that compiles is not a page that works, so the benchmark checks mustShow in Chrome; a spec that validates is not a view that works, so generated UI must be judged by what it renders too. The chat evals of GenUI-2 will count what a generated view shows (the figures asked for, formatted), not only whether it parsed.

Follow-ups

  • In packages/genui, a renderer that reports a node it leaves out, so a view never fails silently.
  • A repair step: send the issues back to the model once, as json-render's formatSpecIssues does.
  • Retry the comparison with a paid model when there is a budget for it: a stronger model may follow json-render's longer prompt better. Three tries on one free model is a small sample.

On this page