# Generative UI

> How to let an AI model build screens with dsui components. OpenUI and json-render are supported.

- URL: https://dsui.vercel.app/en/docs/genui

## What generative UI means

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 |

## Define a component once

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).

```tsx
import { z } from "zod";
import { defineGenUi } from "@/components/arc/gen-ui/spec";
import { Button } from "@/components/arc/button/button";

export const GenButton = defineGenUi({
  name: "Button",
  description: "A button that triggers an action. Use a verb phrase as the label.",
  props: z.object({
    label: z.string(),
    variant: z.enum(["primary", "secondary", "ghost"]).optional(),
  }),
  events: ["press"],
  render: ({ props, emit }) => (
    <Button variant={props.variant} onClick={() => emit("press")}>
      {props.label}
    </Button>
  ),
});
```

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")`).

## Use it in OpenUI

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.

```tsx
// Server (a route handler): the system prompt for the model.
import { GENUI_RULES, GENUI_SPEC } from "@/components/arc/gen-ui/components";
import { openUiPrompt } from "@/components/arc/gen-ui/openui";

const system = openUiPrompt(GENUI_SPEC, { rules: GENUI_RULES });

// Client: draw what the model wrote.
import { GenUi } from "@/components/arc/gen-ui/gen-ui";

<GenUi framework="openui" response={text} />;
```

## Use it in json-render

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>`.

```tsx
// Server (a route handler): the system prompt for the model.
import { GENUI_RULES, GENUI_SPEC } from "@/components/arc/gen-ui/components";
import { jsonRenderPrompt } from "@/components/arc/gen-ui/json-render";

const system = jsonRenderPrompt(GENUI_SPEC, { rules: GENUI_RULES });

// Client: draw the spec the model wrote.
import { GenUi } from "@/components/arc/gen-ui/gen-ui";

<GenUi framework="json-render" response={spec} />;
```

## Install it, and what works now and what does not

[`gen-ui`](/en/items/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.

```bash
npx shadcn@latest add https://dsui.vercel.app/r/gen-ui.json
```

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.
