Engineering

A catalogue beats free-form generation, and the objections say why

Every serious objection to generative UI is an objection to free-form generation. A fixed catalogue answers all four without giving up the idea.

VVoqal · Engineering10 min readPart of Render spec

About this article

The people who dislike generative UI have better arguments than the people who sell it. Their arguments are also, almost without exception, arguments against one specific implementation: a model authoring interface markup from nothing, fresh, per user, per turn.

That implementation deserves the criticism. It is not the only one available.

The objections, stated fairly#

Four objections come up every time. A per-user interface cannot be supported, because nobody can reproduce what the user saw. Users cannot build a habit around something that keeps moving. You cannot write documentation for an interface that does not exist until it is requested. And markup written by a model, from data the model was handed, is an injection surface.

All four are true of free-form generation. None survives a closed catalogue, with one important qualification on the fourth.

Three rows are clean. The fourth depends on a discipline rather than an architecture, which is why it is the row worth arguing about.

A closed catalogue means the app ships a finite set of views, written by your designers and compiled into the binary, and the model’s only power is to name one and fill it. That is what generative UI has to mean on native mobile anyway, because a signed binary cannot evaluate views it was not built with. The security and support properties come along as a consequence of the platform constraint.

A contact sheet showing every widget kind in a render-spec catalogue drawn at once, including stat, progress, list, record, chart, confirm, products, ticket, callback, rating, text and media.
A catalogue is a thing you can print on one page and hand to a reviewer. That property is what the rest of this post is about. It is a contact sheet from the React widget rendering harness on invented sample data, not a capture of the iOS SDK.

Objection one: nobody can support an interface that differs per user#

The sharpest statement of this is a comment on the December 2025 Hacker News thread “What Is Generative UI?”, where marcyb5st imagines the support call: “Yeah, I cannot reproduce your issue because things on my end look different”. A nightmare, as they put it, and they are right about the version they are describing.

Reproducing a catalogue render is easier than reproducing a hand-built screen, because the spec is the entire input and it is a few hundred bytes.

Under a catalogue, two users who ask the same question get the same view. What varies is which view, and that varies because they asked different things. A support engineer does not reproduce by guessing: they read the logged spec, which is small, complete, and the only input to the render. There is no cache, no navigation history and no device state in the way.

This is a better support story than most hand-built screens have. A screen assembled from six data sources with three feature flags is harder to reproduce than a two-hundred-byte payload.

Objection two: users cannot build a mental model of a shifting UI#

Also from that thread, the commenter bccdee: “Personalized interfaces are bad. I don’t want to configure anything, and I don’t want anything automatically configured on my behalf.” And, more precisely: “Your UI should be clear and predictable. A chatbot should not be moving around the buttons.” The commenter tartoran adds the memory cost: “You won’t remember how you got there or did what because there are n permutations of getting there or doing that.”

The word doing the work in that last quote is n. Under free-form generation, n is unbounded. Under a catalogue, n is the number of widget kinds, it is printed in your documentation, and it changes only when your team changes it.

The comparison people reach for is Microsoft’s adaptive menus, and it is apt. Several commenters in that thread bring it up unprompted. Those menus hid items based on how often you used them, so the same action was in a different place on different days, through no action of yours. A catalogue does the opposite: the view changes when you ask a different question, which is the same contract as tapping a different tab. Predictability survives because the mapping from question to view is stable.

Objection three: you cannot document it#

You cannot document an interface authored per turn. You can document twelve widget kinds, the fields each one accepts, and the conditions under which the agent chooses each. That list is a page: finite, under version control, and reviewed like an API, which is exactly what it is.

A search result is the case where this bites first, because an answer assembled from a whole-sentence query is the one a team is most tempted to let the model lay out freely.

The documentation is also the specification the model is held to. The contract itself and the published catalogue are the same artefact viewed from two sides, and a widget that is not in the docs is a widget the validator rejects.

Objection four: generated markup is an injection surface#

This is the objection with real teeth, and it has research behind it rather than intuition. Greshake and colleagues demonstrated in Not what you’ve signed up for (23 February 2023) that “processing retrieved prompts can act as arbitrary code execution, manipulate the application’s functionality, and control how and if other APIs are called”, against real systems including Bing’s GPT-4 powered Chat.

In a consumer app the untrusted text is ordinary product data: a transaction memo, a product title, a message someone else wrote. If a model that has read that text can author markup, it can be talked into authoring a convincing credential prompt. If it can only name a widget kind and supply data fields, the worst available outcome is a real widget containing wrong text, which is a problem your confirm gate handles rather than a new class of attack. The full threat model for an agent that can spend money goes further into what that gate has to look like.

Somebody made this argument independently on the A2UI thread in December 2025, the commenter epec254: “Most HTML is actually HTML+CSS+JS - IMO, accepting this is a code injection attack waiting to happen. By abstracting to JSON, a client can safely render UI without this concern.”

The reply is the important part. From lunar_mycroft, on the same thread: “If the JSON protocol in question supports arbitrary behaviors and styles, then you still have an injection problem even over JSON. If it doesn’t support them you don’t need to support those in an HTML protocol either, and you can solve the injection problem the way we already do: sanitizing the HTML to remove all/some (depending on your specific requirements) script tags, event listeners, etc.”

That is correct, and it is why the fourth row of the table above carries a condition. JSON is not safer than HTML because of its syntax. It is safer when the schema is narrow, and a schema that grows a style field, a customHtml field or an arbitrary properties bag has become a markup language with a JSON accent. The defence is the restriction, and the restriction has to be defended in code review every quarter, because the pressure to widen it never stops.

What a catalogue can promise that markup cannot#

The most concrete version of this is accessibility, because accessibility is made of exactly the promises that a per-turn generator cannot keep.

Each property is tested once per widget and then holds for every answer the agent gives. Under generated markup the same five are re-promised on every turn.

WCAG 2.2, a W3C Recommendation since 12 December 2024, requires under success criterion 2.5.8 that pointer targets be “at least 24 by 24 CSS pixels”, with five named exceptions. You can satisfy that in twelve views and know it holds. You cannot satisfy it in markup a model wrote a second ago, and you certainly cannot audit it. An agent is an accessibility feature only if the thing it draws was built to the same bar as the rest of the app.

What you give up, honestly#

Three things, and they are real.

You give up novelty. A catalogue cannot produce an interface nobody anticipated. If a user asks something that genuinely wants a seat map and you have no seat map, they get a list and a spoken answer. Free-form generation would attempt the seat map, and would sometimes succeed.

You give up some ceiling on quality. Google’s own generative UI paper is the honest source here. In Generative UI: LLMs are Effective UI Generators (24 February 2026), the authors report that “when ignoring generation speed, results generated by our implementation are overwhelmingly preferred by humans over the standard LLM markdown output”, and then concede that “while the results generated by our implementation are worse than those crafted by human experts, they are at least comparable in 50% of cases”. Generated interfaces beat text. Designed interfaces beat generated ones. A catalogue takes the designed side, which means the ceiling is whatever your design team built and no higher.

And you give up speed of expansion. Adding a widget kind is a release, on two or three platforms, with review. Teams used to shipping a prompt change in an afternoon find this slow, and it is. The upside is that everything already in the catalogue keeps working on a client shipped two years ago.

Common questions#

Is generative UI safe?#

Free-form generative UI, where a model authors markup, inherits every indirect prompt injection risk that has been demonstrated against LLM-integrated applications since 2023. A closed catalogue removes the authoring step entirely: the model names a view and supplies data, so it cannot produce markup at all. That holds only while the schema stays narrow.

What’s wrong with generative UI?#

The standard complaints are that a per-user interface cannot be supported or reproduced, that users cannot build habits around it, that it cannot be documented, and that generated markup is an attack surface. Each is fatal to free-form generation and each is addressed by restricting the model to a fixed set of views.

How do you keep a generated interface consistent enough to support?#

Make the set of possible renders finite and log the spec that produced each one. The same question then produces the same view for every user, and a support engineer reproduces a session by replaying a payload of a few hundred bytes rather than by recreating device state.

Does a widget catalogue limit what the agent can answer?#

It limits how the agent can present an answer, not what it can find out. Tool calls are unrestricted by the catalogue. When no widget fits, the agent still speaks or writes the answer, and the unmatched request is logged, which is how you learn which widget to build next.

Can a fixed catalogue still feel adaptive?#

Yes, because the adaptation is in the selection rather than the construction. Twelve widget kinds filled with live data, chosen per question, produce a very large number of distinct screens. What they do not produce is a screen your designers never approved.

Sources#

Filed underServer-driven UIRender specSecurityWidgets

Next

The catalogue of every widget kind the agent can ask your app to draw, and the payload each one takes.

See every widget kind the agent can render

The rest of Render spec

Open the cluster

Server-driven native UI: the agent names the widgets, your app draws them, and shipping a new answer shape stops requiring an app release.

Elsewhere on the map