.agents/skills/openui-forge-vercel/SKILL.md
OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support.
npx skillsauth add OthmanAdi/openui-forge openui-forge-vercelInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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";
import "@openuidev/react-ui/styles/index.css";
npm run dev and testapp/api/chat/route.tsimport { openuiLibrary } from "@openuidev/react-ui";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
export async function POST(req: Request) {
const { messages } = await req.json();
const systemPrompt = openuiLibrary.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("gpt-4o"),
system: systemPrompt,
messages,
});
return result.toUIMessageStreamResponse();
}
app/api/chat/route.tsimport { openuiLibrary } from "@openuidev/react-ui";
import { streamText, tool } 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 = openuiLibrary.prompt({
preamble: "You are a helpful assistant that generates interactive UIs. Use tools to fetch data before rendering.",
});
const result = streamText({
model: openai("gpt-4o"),
system: systemPrompt,
messages,
tools: {
getWeather: tool({
description: "Get current weather for a city",
parameters: z.object({
city: z.string().describe("City name"),
}),
execute: async ({ city }) => {
return { city, temp: 22, condition: "sunny" };
},
}),
},
maxSteps: 3,
});
return result.toUIMessageStreamResponse();
}
app/chat/page.tsx"use client";
import { FullScreen } from "@openuidev/react-ui";
import { openuiLibrary } from "@openuidev/react-ui";
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={openuiLibrary}
processMessage={processMessage}
/>
);
}
app/chat/page.tsx"use client";
import { useChat } from "@ai-sdk/react";
import { FullScreen } from "@openuidev/react-ui";
import { openuiLibrary } from "@openuidev/react-ui";
export default function ChatPage() {
const chat = useChat({ api: "/api/chat" });
return (
<FullScreen
componentLibrary={openuiLibrary}
messages={chat.messages}
onSend={(text) => chat.append({ role: "user", content: text })}
isLoading={chat.isLoading}
/>
);
}
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 openuiLibrary.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 or useChat (not openAIReadableStreamAdapter)componentLibrary prop passed to FullScreenmaxSteps is set, tool results feed back to model| Error | Cause | Fix |
|-------|-------|-----|
| ai module not found | Missing Vercel AI SDK | npm install ai @ai-sdk/openai |
| Stream format mismatch | Using openAIReadableStreamAdapter with Vercel AI | Use processMessage or useChat instead |
| Tools not executing | Missing maxSteps | Add maxSteps: 3 (or higher) to streamText options |
| Blank response | Wrong export from @ai-sdk/openai | Use openai("gpt-4o") not new OpenAI() |
| Type errors on messages | Vercel AI message format differs | Let useChat manage messages, or map to CoreMessage[] |
development
Build generative UI with OpenUI — any LLM provider, any backend language. Scaffold, integrate, validate.
data-ai
使用 OpenUI 构建生成式 UI 应用 — 支持任意 LLM 提供商、任意后端语言。脚手架、集成、验证。
tools
OpenUI generative UI with Vercel AI SDK. streamText, toUIMessageStreamResponse, and tools support.
development
OpenUI generative UI with Rust Axum backend. Async SSE streaming with reqwest and async-stream.