# jsx2ui

> Let AI models build live, interactive UIs in your app using your own React components.

Latest version **0.0.4** (published 2026-06-30) · 0 weekly downloads

## Install

```sh
npm install jsx2ui
pnpm add jsx2ui
yarn add jsx2ui
bun add jsx2ui
```

## Health

**Score 55/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.0.4 |
| Published | 2026-06-30 |
| First published | 2026-03-23 |
| Weekly downloads | 0 |
| TypeScript types | bundled |
| Module format | ESM |
| Dependencies | 3 |
| Unpacked size | 126.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | vaibhavshn, palashgo |
| Keywords | ai, ai-sdk, cloudflare, generative-ui, llm, react, typescript, workers |

## Links

- npm: https://www.npmjs.com/package/jsx2ui
- npm.io page: https://npm.io/package/jsx2ui

## Dependencies (3)

- [zod](https://npm.io/package/zod.md) ^4.4.3
- [acorn](https://npm.io/package/acorn.md) ^8.16.0
- [sucrase](https://npm.io/package/sucrase.md) ^3.35.1

## Alternatives

- [@expo/fingerprint](https://npm.io/package/@expo/fingerprint.md) — 6.2M weekly downloads
- [@azure/monitor-opentelemetry-exporter](https://npm.io/package/@azure/monitor-opentelemetry-exporter.md) — 850.0K weekly downloads
- [@azure/monitor-opentelemetry](https://npm.io/package/@azure/monitor-opentelemetry.md) — 624.0K weekly downloads
- [@posthog/ai](https://npm.io/package/@posthog/ai.md) — 423.3K weekly downloads
- [fakefilter](https://npm.io/package/fakefilter.md) — 63.9K weekly downloads

## Recent versions

- 0.0.4 (latest) — 2026-06-30
- 0.0.3 — 2026-06-30
- 0.0.2 — 2026-06-30
- 0.0.1 — 2026-03-26
- 0.0.0 — 2026-03-23

## README

# jsx2ui

`jsx2ui` helps you integrate generative, model-authored UI into your app.
It turns JSX returned by your model tool calls into serializable UI JSON and renders it with your own React component catalog.

## Installation

```bash
npm install jsx2ui
```

## Table of Contents

- [Package Entrypoints](#package-entrypoints)
- [Quick Start (AI SDK + Cloudflare Workers)](#quick-start-ai-sdk--cloudflare-workers)
  - [1) Define the components in frontend](#1-define-the-components-in-frontend)
  - [2) Define the components schema for the LLM](#2-define-the-components-schema-for-the-llm)
  - [3) Add the UI tool to your AI chat configuration](#3-add-the-ui-tool-to-your-ai-chat-configuration)
  - [4) Render the UI on the frontend](#4-render-the-ui-on-the-frontend)
  - [5) Styling for the default components (Optional - if using TailwindCSS)](#5-styling-for-the-default-components-optional---if-using-tailwindcss)
- [Server-side APIs](#server-side-apis)
  - [Core framework-agnostic APIs (`jsx2ui`)](#core-framework-agnostic-apis-jsx2ui)
  - [AI SDK server API (`jsx2ui/ai-sdk`)](#ai-sdk-server-api-jsx2uiai-sdk)
- [Frontend APIs (React)](#frontend-apis-react)
  - [Shared React APIs (`jsx2ui/react`)](#shared-react-apis-jsx2uireact)
  - [AI SDK React APIs (`jsx2ui/react/ai-sdk`)](#ai-sdk-react-apis-jsx2uireactai-sdk)

## Package Entrypoints

| Entrypoint                        | Layer    | Use for                                                                                    |
| --------------------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `jsx2ui`              | Core     | Framework-agnostic primitives like schema/prompt generation and JSX-to-JSON transformation |
| `jsx2ui/ai-sdk`       | Server   | AI SDK `createUI` tool and `createGenUI` helper                                            |
| `jsx2ui/react`        | Frontend | Shared React primitives (`createCatalog`, `Renderer`, result guards/types)                 |
| `jsx2ui/react/ai-sdk` | Frontend | AI SDK message-part rendering utilities                                                    |

## Quick Start (AI SDK + Cloudflare Workers)

### 1) Define the components in frontend

```tsx
// src/catalog.tsx

import { createCatalog } from "jsx2ui/react";

function Title({ children, size }: { children: React.ReactNode; size: "sm" | "md" | "lg" }) {
	return <h1 className={`text-${size}`}>{children}</h1>;
}

function Card({ children }: { children: React.ReactNode }) {
	return <div className="card">{children}</div>;
}

const catalog = createCatalog({
	Title,
	Card,
});
```

### 2) Define the components schema for the LLM

```ts
import { defineComponents, z } from "jsx2ui";

export const components = defineComponents([
	{
		name: "Title",
		acceptsChildren: true,
		props: z.object({
			size: z.enum(["sm", "md", "lg"]).default("md"),
		}),
	},
	{
		name: "Card",
		acceptsChildren: true,
	},
]);
```

### 3) Add the UI tool to your AI chat configuration

```ts
import { createWorkersAI } from "workers-ai-provider";
import {
	createUIMessageStream,
	createUIMessageStreamResponse,
	convertToModelMessages,
	streamText,
} from "ai";
import { createGenUI } from "jsx2ui/ai-sdk";
import { components } from "./schema";

export default {
	async fetch(request, env) {
		const url = new URL(request.url);

		if (url.pathname.startsWith("/api/chat")) {
			const { messages } = await request.json();
			const workersAi = createWorkersAI({ binding: env.AI });

			const genUI = createGenUI({ loader: env.LOADER, components });
			const modelMessages = await convertToModelMessages(messages);

			const stream = createUIMessageStream({
				execute: ({ writer }) => {
					const textStream = streamText({
						model: workersAi("@cf/zai-org/glm-4.7-flash"),
						system: genUI.systemPrompt(),
						messages: modelMessages,
						tools: genUI.tools(writer),
						stopWhen: [genUI.stopCondition()],
					});
					writer.merge(textStream.toUIMessageStream());
				},
			});

			return createUIMessageStreamResponse({ stream });
		}

		return new Response(null, { status: 404 });
	},
} satisfies ExportedHandler<Env>;
```

### 4) Render the UI on the frontend

```tsx
// src/chat.tsx
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
import { useGenUI } from "jsx2ui/react/ai-sdk";
import { catalog } from "./catalog";

function Chat() {
	const { parsePart, onData } = useGenUI({ catalog });

	const { messages, sendMessage } = useChat({
		transport: new DefaultChatTransport({ api: "/api/chat" }),
		onData,
	});

	return (
		<>
			{messages.map((message) => (
				<div key={message.id}>
					{message.parts.map((part, partIdx) => {
						const result = parsePart(part);
						if (result.handled) {
							return <div key={partIdx}>{result.element}</div>;
						}
						if (part.type === "text") {
							return <span key={partIdx}>{part.text}</span>;
						}
						return null;
					})}
				</div>
			))}
		</>
	);
}
```

### 5) Styling for the default components (Optional - if using TailwindCSS)

For TailwindCSS v4:

```css
/* src/index.css */
@source "../node_modules/jsx2ui/dist/**/*.*js";
```

For TailwindCSS v3:

```js
// tailwind.config.js
module.exports = {
	content: [
		"./node_modules/jsx2ui/dist/**/*.*js", // add this to content
	],
};
```

## Server-side APIs

### Core framework-agnostic APIs (`jsx2ui`)

```ts
import { defineComponents, z } from "jsx2ui";

const genUI = defineComponents([
	{
		name: "Title",
		acceptsChildren: true,
		props: z.object({
			size: z.enum(["sm", "md", "lg"]).default("md"),
		}),
	},
	{ name: "Card", acceptsChildren: true },
]);

console.log(genUI.getSystemPrompt());
```

### AI SDK server API (`jsx2ui/ai-sdk`)

```ts
import { streamText } from "ai";
import { createGenUI } from "jsx2ui/ai-sdk";

const genUI = createGenUI({ loader: env.LOADER, components });

const result = streamText({
	model,
	system: genUI.systemPrompt(),
	messages,
	tools: genUI.tools(),
	stopWhen: genUI.stopCondition(),
});
```

## Frontend APIs (React)

### Shared React APIs (`jsx2ui/react`)

```tsx
import React from "react";
import { createCatalog, Renderer, type UINode } from "jsx2ui/react";

const catalog = createCatalog({ Title, Card });

export function GeneratedView({ ui }: { ui: UINode }) {
	return <Renderer node={ui} catalog={catalog} />;
}
```

### AI SDK React APIs (`jsx2ui/react/ai-sdk`)

```tsx
import React from "react";
import { isGenUiPart, useGenUI } from "jsx2ui/react/ai-sdk";

const { parsePart, reset } = useGenUI({ catalog });

// Optional guard when filtering AI SDK message parts yourself.
if (isGenUiPart(part)) {
	const result = parsePart(part);
	return <>{result.element}</>;
}

// Call reset() when removing chat messages to release cached generated UI state.
```

---
_Source: https://npm.io/package/jsx2ui · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
