with one click
openui-forge-vercel
// OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support.
// OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support.
| name | openui-forge-vercel |
| description | OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support. |
| version | 1.0.0 |
| author | OthmanAdi |
Build generative UI apps with OpenUI + Vercel AI SDK. Native streaming with streamText and toUIMessageStreamResponse().
OPENAI_API_KEY environment variable setnpm install @openuidev/react-ui @openuidev/react-headless @openuidev/react-lang lucide-react zod ai @ai-sdk/openai
app/layout.tsx:import "@openuidev/react-ui/components.css";
npm run dev and testapp/api/chat/route.tsimport { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
export async function POST(req: Request) {
const { messages } = await req.json();
const systemPrompt = openuiChatLibrary.prompt({
preamble: "You are a helpful assistant that generates interactive UIs.",
additionalRules: ["Always use Stack as root when combining multiple components."],
});
const result = streamText({
model: openai(process.env.OPENAI_MODEL ?? "gpt-5.5"),
system: systemPrompt,
messages,
});
return result.toUIMessageStreamResponse();
}
app/api/chat/route.tsimport { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import { streamText, tool, stepCountIs } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
export async function POST(req: Request) {
const { messages } = await req.json();
const systemPrompt = openuiChatLibrary.prompt({
preamble: "You are a helpful assistant that generates interactive UIs. Use tools to fetch data before rendering.",
});
const result = streamText({
model: openai(process.env.OPENAI_MODEL ?? "gpt-5.5"),
system: systemPrompt,
messages,
tools: {
getWeather: tool({
description: "Get current weather for a city",
inputSchema: z.object({
city: z.string().describe("City name"),
}),
execute: async ({ city }) => {
return { city, temp: 22, condition: "sunny" };
},
}),
},
// AI SDK v5+: stopWhen replaces the removed `maxSteps` option.
stopWhen: stepCountIs(3),
});
return result.toUIMessageStreamResponse();
}
app/chat/page.tsx"use client";
import { FullScreen } from "@openuidev/react-ui";
import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
async function processMessage(messages: { role: string; content: string }[]) {
const res = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ messages }),
});
if (!res.body) throw new Error("No response body");
return res.body;
}
export default function ChatPage() {
return (
<FullScreen
componentLibrary={openuiChatLibrary}
processMessage={processMessage}
/>
);
}
import { defineComponent } from "@openuidev/react-lang";
import { z } from "zod";
export const WeatherCard = defineComponent({
name: "WeatherCard",
description: "Displays weather information for a location",
props: z.object({
city: z.string().describe("City name"),
temp: z.number().describe("Temperature in Celsius"),
condition: z.enum(["sunny", "cloudy", "rainy", "snowy"]).describe("Weather condition"),
}),
component: ({ props }) => (
<div style={{ padding: 16, borderRadius: 12, background: "#f0f9ff" }}>
<h3>{props.city}</h3>
<div style={{ fontSize: 32 }}>{props.temp}C</div>
<div>{props.condition}</div>
</div>
),
});
npx @openuidev/cli generate ./src/lib/library.ts --out src/generated/system-prompt.txt
Or at runtime via openuiChatLibrary.prompt() as shown in the route.
OPENAI_API_KEY is set in .env.localai and @ai-sdk/openai packages installedstreamText and returns result.toUIMessageStreamResponse()processMessage returning response.body (the Vercel AI SDK stream is consumed natively, no streamProtocol needed)componentLibrary={openuiChatLibrary} prop passed to FullScreenstopWhen: stepCountIs(n) is set (AI SDK v5+ replacement for the removed maxSteps), tool results feed back to modelinputSchema: (v5+ rename of parameters:)| Error | Cause | Fix |
|---|---|---|
ai module not found | Missing Vercel AI SDK | npm install ai @ai-sdk/openai |
| Stream format mismatch | Trying to use openAIReadableStreamAdapter with Vercel AI's UI message stream | Drop streamProtocol. Use processMessage returning response.body — the AI SDK stream is consumed natively |
Type error on maxSteps | maxSteps removed in AI SDK v5+ | Import stepCountIs from ai and use stopWhen: stepCountIs(3) |
Type error on tool parameters | Renamed to inputSchema in AI SDK v5+ | Rename parameters: to inputSchema: in every tool({...}) definition |
| Blank response | Wrong export from @ai-sdk/openai | Use openai("gpt-5.5") not new OpenAI() |
| Props silently ignored | Passing messages/onSend/isLoading props to FullScreen | FullScreen does not accept these — use processMessage instead |
OpenUI generative UI with Anthropic Claude SDK backend. Stream conversion to OpenAI NDJSON format.
OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.
OpenUI generative UI with LangChain/LangGraph backend. Supports ChatOpenAI and ChatAnthropic.
OpenUI generative UI with OpenAI SDK backend. Streaming chat completions with gpt-5.5 (or any current OpenAI-compatible model).
OpenUI generative UI with Python FastAPI backend. OpenAI and Anthropic SDK variants.
OpenUI generative UI with Rust Axum backend. Async SSE streaming with reqwest and async-stream.