Generative UI
How to let an AI model build screens with dsui components. OpenUI and json-render are supported.
Generative UI is when an AI model answers with a screen instead of text. The model writes a screen using only a list of components you set in advance, and your app draws that answer with the real components. With dsui, a screen a model made has the same tokens, motion and sound as one a person made.
You define a component once and use it in both frameworks.
| Framework | What the model writes | What dsui produces |
|---|---|---|
| OpenUI | OpenUI Lang (a short function-call syntax) | A library built with defineComponent and createLibrary, and the system prompt |
| json-render | A JSON spec | A catalog and registry built with defineCatalog and defineRegistry, and the system prompt |
The neutral spec holds the name, when a model should pick it (description), the props (zod), whether it takes children (slot) and the events it can fire (events). Props are serializable only: strings, numbers, booleans and enums. A model cannot write a callback or a node, so behaviour reaches your app through emit (events) and setValue (input values).
OpenUI Lang passes arguments by position, so list required props first and optional props after them. A component that takes children puts the child list first (Card([...], "Title")).
Turn the spec into a library and you get both the system prompt for the model and the Renderer that draws the result. An event becomes an action prop (on<Event> when there are several), and input values collect in OpenUI's form state. A component that takes children receives a children array.
The same spec yields a catalog and a registry. An optional prop is accepted as null from the model and reaches the dsui component as an omitted prop. Children go in the default slot, and input values collect in state at /form/<name>.
gen-ui installs with one line like any other component. The components it uses (Button, Input, Textarea, Select, Switch, Checkbox, Alert, Badge, MetricCard, Progress, Stack and Card) and the npm packages it needs (@openuidev/react-lang, @json-render/react and zod) come along.
This is a preview, so it has twelve components. The input fields (Input, Textarea, Select, Switch and Checkbox) report their value to your app under their name.
- A component that takes children holds only the components listed before it in the spec. So a Card can hold a Stack (a horizontal row), but there is no Stack inside a Stack and no Card inside a Card.
- The dsui rules, such as the polite Korean tone and button wording, go into both prompts as the same sentences through
GENUI_RULES. - More components follow the same way. A new component needs only its spec, and both adapters pick it up.