بنقرة واحدة
openui-forge-vercel
OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | openui-forge-vercel |
| description | OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support. |
| version | 1.2.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-lang lucide-react zod ai @ai-sdk/openai @ai-sdk/react
Pin to the AI SDK v6 line: ai@^6, @ai-sdk/openai@^3, @ai-sdk/react@^3.
2. Add the CSS import to 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 { convertToModelMessages, 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."],
});
// AI SDK v6: convert the UI message stream into model messages before passing to the model.
const modelMessages = await convertToModelMessages(messages);
const result = streamText({
model: openai(process.env.OPENAI_MODEL ?? "gpt-5.5"),
system: systemPrompt,
messages: modelMessages,
});
return result.toUIMessageStreamResponse();
}
app/api/chat/route.tsimport { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import { convertToModelMessages, 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.",
});
// AI SDK v6: convert the UI message stream into model messages before passing to the model.
const modelMessages = await convertToModelMessages(messages);
const result = streamText({
model: openai(process.env.OPENAI_MODEL ?? "gpt-5.5"),
system: systemPrompt,
messages: modelMessages,
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 v6: stopWhen replaces the removed `maxSteps` option.
stopWhen: stepCountIs(3),
});
return result.toUIMessageStreamResponse();
}
app/chat/page.tsxDrive the conversation with useChat from @ai-sdk/react, then render each assistant message with a per-message <Renderer> from @openuidev/react-lang. The Renderer takes the assistant text as response, the component library as library (NOT componentLibrary), an isStreaming flag for the in-flight message, and an onAction handler for built-in actions like continuing the conversation.
"use client";
import { useChat } from "@ai-sdk/react";
import { Renderer, BuiltinActionType } from "@openuidev/react-lang";
import type { ActionEvent } from "@openuidev/react-lang";
import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import { useState } from "react";
export default function ChatPage() {
const [input, setInput] = useState("");
const { messages, sendMessage, status } = useChat();
const isLoading = status === "submitted" || status === "streaming";
const handleSend = (text: string) => {
const trimmed = text.trim();
if (!trimmed || isLoading) return;
setInput("");
sendMessage({ text: trimmed });
};
const handleAction = (event: ActionEvent) => {
if (event.type === BuiltinActionType.ContinueConversation && event.humanFriendlyMessage) {
handleSend(event.humanFriendlyMessage);
}
};
return (
<div>
{messages.map((message, i) => {
const isLast = i === messages.length - 1;
if (message.role === "user") {
const text = message.parts
.filter((p): p is { type: "text"; text: string } => p.type === "text")
.map((p) => p.text)
.join("");
return <div key={message.id}>{text}</div>;
}
// assistant: render generative UI from the text parts
const response = message.parts
.filter((p): p is { type: "text"; text: string } => p.type === "text")
.map((p) => p.text)
.join("");
return (
<Renderer
key={message.id}
response={response}
library={openuiChatLibrary}
isStreaming={isLoading && isLast}
onAction={handleAction}
/>
);
})}
<form
onSubmit={(e) => {
e.preventDefault();
handleSend(input);
}}
>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button type="submit" disabled={isLoading}>Send</button>
</form>
</div>
);
}
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, @ai-sdk/openai, and @ai-sdk/react packages installed (v6 line: ai@^6, @ai-sdk/openai@^3, @ai-sdk/react@^3)convertToModelMessages(messages) and passes messages: modelMessages to streamTextstreamText and returns result.toUIMessageStreamResponse()useChat from @ai-sdk/react (messages, sendMessage, status)<Renderer response={...} library={openuiChatLibrary} isStreaming={...} onAction={...} /> from @openuidev/react-langlibrary={openuiChatLibrary} (NOT componentLibrary)stopWhen: stepCountIs(n) is set (AI SDK v6 replacement for the removed maxSteps), tool results feed back to modelinputSchema: (v6 rename of parameters:)| Error | Cause | Fix |
|---|---|---|
ai module not found | Missing Vercel AI SDK | npm install ai @ai-sdk/openai @ai-sdk/react |
useChat is not exported / not found | Importing the hook from ai | Import useChat from @ai-sdk/react and install @ai-sdk/react@^3 |
| Empty / mismatched model messages | Passing raw UI messages straight to streamText | const modelMessages = await convertToModelMessages(messages), then pass messages: modelMessages |
Type error on maxSteps | maxSteps removed in AI SDK v6 | Import stepCountIs from ai and use stopWhen: stepCountIs(3) |
Type error on tool parameters | Renamed to inputSchema in AI SDK v6 | Rename parameters: to inputSchema: in every tool({...}) definition |
| Blank response | Wrong export from @ai-sdk/openai | Use openai("gpt-5.5") not new OpenAI() |
| Generative UI does not render | componentLibrary prop passed to Renderer, or rendering message.content instead of joined text parts | Use library={openuiChatLibrary} and pass the joined text parts as response={...} |
OpenUI generative UI with Anthropic Claude SDK backend. Stream conversion to OpenAI NDJSON format.
OpenUI generative UI with C# ASP.NET Core Minimal API backend. Direct OpenAI API SSE streaming via HttpClient on .NET 10.
OpenUI generative UI with Elixir Phoenix backend. Chunked SSE streaming via Plug.Conn and Req.
OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.
OpenUI generative UI with a Java Spring Boot (WebFlux) backend. Streams the OpenAI API directly via WebClient as SSE.
OpenUI generative UI with LangChain/LangGraph backend. Supports ChatOpenAI and ChatAnthropic.