Skip to content
· 5 min readAIRN
AI-Generated Mobile UI: How an LLM Builds the Screen

AI-Generated Mobile UI: How an LLM Builds the Screen

AI-generated mobile UI explained: how an LLM picks and fills a native component, why mobile needs a different approach than the web, and how to ship it in React Native without a JSON parser.

AI-generated mobile UI is the pattern where an LLM decides what interface to show next and returns it as structured data, and the app renders that data as native components at runtime instead of running a fixed screen. The model does not write code or HTML. It picks a component from a registry you control and fills its props. On React Native, Wire RN validates that pick against a Zod schema and mounts the matching native view, one component per turn. The screen is built by the model, but the building blocks are yours.

People hear "AI generates the UI" and picture a model emitting raw layout code that you then trust. That version is a security and reliability nightmare. The version that ships is narrower and much safer, and it is worth being precise about the difference.

What does AI-generated mobile UI actually mean?

It means the interface is data the model produces, not screens you hard-code. You give the model a set of components it is allowed to use, each described in plain language. The model reads the conversation so far, decides what comes next, and returns a small JSON object: a component name and its props. Your app looks that name up and renders the real native component. The model never ships layout code into your app.

That constraint is the whole point. The model is choosing from a menu you wrote, not inventing arbitrary UI. So the worst a bad model output can do is name a component that does not exist or pass a wrong prop, both of which you catch before anything renders. The plain-English version of the category is in what generative UI is.

How does the model build a screen?

In two moves. First the model picks: given the context and the list of available components, it returns one component name. Then it fills: it generates the props that component needs, matching the schema you defined. Here is what a single turn looks like coming back from the model.

// What the LLM returns for one turn
{
  "component": "ChipSelectCard",
  "props": {
    "title": "What are you here to work on?",
    "options": ["Focus", "Sleep", "Stress", "Energy"]
  }
}

No prose, no markdown, no parsing a chat bubble for a hidden command. The model is constrained to return this shape because the system prompt and the schemas tell it to. Wire RN generates that system prompt from your registered components, so you describe a component once and the prompt-engineering falls out of it. The mechanics are in how generative UI actually works on React Native.

Why mobile needs a different approach than the web

The web solved AI-generated UI in 2024 with tools like the Vercel AI SDK and Tambo. None of that runs on React Native unchanged. Three things break.

  • No DOM. React Native renders native views, not HTML. Any renderer that emits or diffs DOM nodes is dead on arrival.
  • No browser streaming. Hermes does not implement ReadableStream on fetch, so the streaming layer every web tool relies on silently fails. The fix is in the Hermes ReadableStream post.
  • Different bundler. Metro, not a web bundler. The build assumptions do not carry over.

So a mobile-first SDK is not a nice-to-have, it is the only way the pattern works on a phone. Why a web tool cannot be retrofitted is laid out in why Tambo does not work on mobile.

Why validate the model's UI before rendering?

Because a model is a probabilistic system sitting directly upstream of your screen. Even a good model occasionally returns a missing prop, a wrong type, or a component name that is not in your registry. If you render that blindly, a single bad turn blanks or crashes a production screen. The fix is a schema gate: validate the model's output with Zod, and on a mismatch fall back to a text message instead of rendering garbage.

import { z } from 'zod';

const ChipSelectSchema = z.object({
  title: z.string(),
  options: z.array(z.string()).min(2).max(6),
});

const result = ChipSelectSchema.safeParse(modelOutput.props);
if (!result.success) {
  // skip render, fall back to a plain message, log the bad prop in dev
}

Wire RN runs this gate on every turn so you do not write it by hand. The model is creative; the schema keeps it honest. That separation, free-form picking inside a typed boundary, is what makes AI-generated UI safe enough to put in front of real users.

How is this different from a chatbot?

A chatbot returns text and asks the user to read and type. AI-generated UI returns interface: a card to tap, a stepper to nudge, a chip set to pick from. The difference is interaction cost. On a phone, typing free text is slow and error-prone, and a wall of model prose is the worst mobile experience there is. A single decisive card the user taps through is the best one.

There is a reliability difference too. A chatbot's output is unconstrained, so you parse it and hope. AI-generated UI's output is a component name and typed props you validate before render. The model is still doing the thinking, but the surface it produces is bounded by your schemas. That boundary is what moves generative UI from a demo to something you put in front of paying users.

How do you add AI-generated UI to an app?

Four steps, and most of the work is in the second one. Here is the path from an empty Expo app to a model-driven screen.

  • Install the SDK. Run npm install wireai-rn zod and wrap your screen in a WireAIProvider with an adapter (OpenAI, Anthropic, Gemini, Ollama, or A2A).
  • Register your components. Give each a name, a one-line description, and a Zod schema. This is your menu; the model can only pick from it.
  • Render the thread. Use the thread hook and the message renderer. Each turn the model returns one component, validated, and it mounts natively.
  • Handle the action. When the user taps, send their answer back. The model reads it and returns the next component.

You do not write a system prompt, a JSON parser, or a fallback handler by hand. The SDK builds the prompt from your component descriptions and runs the validation gate on every turn. The walkthrough with full code is in build an AI chat app with React Native.

Where this earns its keep first

Onboarding. A static onboarding flow asks everyone the same questions and converts poorly. With AI-generated UI the model reads early answers and builds the next two to four screens around them, so a sleep-focused user and a stress-focused user see different cards. The model picks the components; your registry guarantees they are real. The use-case page is at getwireai.com/onboarding, and the components you can wire are in the components docs.

One honest caveat from shipping this: AI-generated UI is worst exactly where a user expects a fixed, predictable layout (a settings screen, a checkout). Save it for the screens where adapting to the person is the point. Forcing it everywhere is how you make an app feel unpredictable, which is the opposite of what you want.

FAQ

Does the LLM write the actual UI code?

No. The model picks a component from a registry you defined and fills its props as JSON. It never emits layout code, HTML, or JSX into your app. That is what keeps AI-generated UI safe: the building blocks are components you wrote and reviewed.

What happens if the model returns invalid UI?

The output is validated against a Zod schema before anything renders. On a mismatch (missing prop, wrong type, unknown component) the turn falls back to a plain message instead of crashing the screen, and in development the bad prop is logged.

Can I use my own components, not just built-ins?

Yes. You register a custom component with a name, a description, and a Zod schema, and the model can pick it like any built-in. Wire RN folds the description into the system prompt automatically. See the custom-components guide for the full pattern.

Which LLMs can generate the UI?

Any of the adapters Wire RN ships: OpenAI, Anthropic, Gemini, Ollama for local models, or A2A to drive the UI from a remote agent. Frontier models pick components most reliably, but a small local model handles flat schemas well, which keeps cost and latency down for high-frequency turns.

Is AI-generated UI safe for production?

It is safer than rendering raw model output, because the model only picks from components you wrote and every pick is validated against a Zod schema before render. The failure mode is a fallback message, not a crash. Reserve it for screens where adapting to the user is the point, and keep fixed layouts (settings, checkout) hard-coded.


Let the model build the screen, but keep the building blocks yours. Run npm install wireai-rn zod and read the quick-start. The repo is on GitHub.