OpenUI

Generative UI のオープン標準フレームワーク — ストリーミングファーストな言語、React ランタイム、すぐ使えるチャットインターフェースをワンパッケージで提供。JSON 比で最大 67% のトークン削減

MIT License React 19+ Streaming-first Zod スキーマ TypeScript
1 — 概要

OpenUI は フルスタック Generative UI フレームワークです。LLM の出力をテキストとしてのみ扱うのではなく、コンポーネントを定義し、モデルがストリームしながら構造化 UI を生成・描画できるようにします。

中心にあるのは OpenUI Lang — コンパクトでストリーミングに最適化された UI 生成言語。JSON-based なフォーマットより大幅にトークン効率が高く、React の <Renderer> がトークンの到着と同時に UI を段階的に描画します。

67% 最大トークン削減(vs JSON)
4 公開パッケージ
30+ 組み込みコンポーネント
3 チャットレイアウト
  • OpenUI Lang — モデル出力向けのコンパクトなストリーミング UI 言語
  • 組み込みコンポーネントライブラリ — チャート・フォーム・テーブル・レイアウト等がすぐ使える
  • コンポーネントライブラリからのプロンプト生成 — 定義したコンポーネントから自動でシステムプロンプトを生成
  • ストリーミングレンダラー — トークン到着と同時に React コンポーネントを逐次描画
  • チャット & アプリサーフェス — アシスタント・コパイロット・インタラクティブ UI まで同じ基盤で対応
2 — アーキテクチャ

コンポーネントライブラリが「モデルが生成できるもの」を定義します。そこからシステムプロンプトを生成し、LLM に渡すと OpenUI Lang のストリームが返り、Renderer がリアルタイムで UI を描画します。

flowchart LR A["🗂️ Component
Library"]:::amber --> B["📝 System
Prompt"]:::step B --> C["🤖 LLM"]:::step C --> D["📡 OpenUI Lang
Stream"]:::amber D --> E["⚙️ Renderer"]:::step E --> F["🖼️ Live UI"]:::step classDef amber fill:#fef3c7,stroke:#d97706,color:#92400e classDef step fill:#f9fafb,stroke:#d1d5db,color:#374151

ステップ解説

ステップ担当説明
1. コンポーネント定義defineComponent名前・Zod スキーマ・React レンダラーでコンポーネントを宣言
2. ライブラリ作成createLibraryコンポーネントをまとめてライブラリ化
3. プロンプト生成library.prompt()許可コンポーネント一覧をモデルへ伝えるシステムプロンプトを自動生成
4. LLM 呼び出しバックエンド APIChatProvider / processMessage でストリーミングリクエストを実行
5. ストリーム受信Streaming AdapterOpenAI SSE / AG-UI などを内部イベント形式に正規化
6. レンダリング<Renderer>OpenUI Lang テキストをリアルタイムで React コンポーネントに変換
graph TB subgraph UI["@openuidev/react-ui"] FS["FullScreen"] CP["Copilot"] BT["BottomTray"] COMP["30+ Components"] end subgraph HEADLESS["@openuidev/react-headless"] PROV["ChatProvider"] HOOKS["useThread / useThreadList"] ADAPT["Streaming Adapters"] end subgraph LANG["@openuidev/react-lang"] DC["defineComponent"] CL["createLibrary"] REN["<Renderer>"] PARSER["Parser / StreamingParser"] end subgraph CLI["@openuidev/cli"] CREATE["openui create"] GEN["openui generate"] end UI --> HEADLESS UI --> LANG HEADLESS --> LANG
各パッケージは独立してインストール可能です。@openuidev/react-ui はフルスタックで導入でき、@openuidev/react-lang だけを使って独自 UI に組み込むことも可能です。
3 — パッケージ構成
@openuidev/react-lang
コアランタイム
コンポーネント定義・プロンプト生成・Renderer・パーサーを提供。OpenUI の心臓部。
peer: react ≥19
@openuidev/react-headless
ヘッドレスチャット状態管理
ChatProvider・useThread・useThreadList・Streaming Adapters を提供。UI は持たないため、任意のデザインに組み合わせ可能。
peer: react ≥19, zustand ^4.5
@openuidev/react-ui
UI コンポーネント & レイアウト
FullScreen / Copilot / BottomTray のチャットレイアウト、30+ の UI コンポーネント、openuiLibrary を同梱。
peer: react-lang, react-headless
@openuidev/cli
CLI ツール
create でアプリのスキャフォールド、generate でシステムプロンプト or JSON Schema を生成。
npx @openuidev/cli@latest
openui/
├── packages/
│   ├── react-lang/      # コアランタイム(パーサー・レンダラー・プロンプト生成)
│   ├── react-headless/  # ヘッドレスチャット状態 & ストリーミングアダプター
│   ├── react-ui/        # 組み込みチャットレイアウト & コンポーネントライブラリ
│   └── openui-cli/      # スキャフォールド & プロンプト生成 CLI
├── skills/
│   └── openui/          # AI コーディングアシスタント向け Agent Skill
├── examples/
│   └── openui-chat/     # 動作サンプル(Next.js)
├── docs/                # openui.com ドキュメントサイト
└── benchmarks/          # トークン効率ベンチマーク
4 — クイックスタート
npx @openuidev/cli@latest create --name genui-chat-app
cd genui-chat-app
echo "OPENAI_API_KEY=sk-your-key-here" > .env
npm run dev
これだけで OpenUI Lang・ライブラリ駆動プロンプト・ストリーミング対応のチャットアプリが起動します。
import { FullScreen } from "@openuidev/react-ui";
import "@openuidev/react-ui/components.css";

function App() {
  return (
    <FullScreen
      apiUrl="/api/chat"
      threadApiUrl="/api/threads"
    />
  );
}

① コンポーネントを定義

import { defineComponent } from "@openuidev/react-lang";
import { z } from "zod";

const Greeting = defineComponent({
  name: "Greeting",
  description: "挨拶メッセージを表示",
  props: z.object({
    name: z.string().describe("対象の名前"),
    mood: z.enum(["happy", "excited"]).optional(),
  }),
  component: ({ name, mood }) => (
    <div className={mood === "excited" ? "text-xl font-bold" : ""}>
      こんにちは、{name}!
    </div>
  ),
});

② ライブラリを作成しプロンプトを生成

import { createLibrary } from "@openuidev/react-lang";

const library = createLibrary({ components: [Greeting, Card, Table] });

// モデルへ渡すシステムプロンプト
const systemPrompt = library.prompt({
  preamble: "あなたは親切なアシスタントです。",
  examples: ["<Greeting name='Alice' mood='happy' />"],
});

③ ストリーミング出力を Renderer で描画

import { Renderer } from "@openuidev/react-lang";

function AssistantMessage({ response, isStreaming }) {
  return (
    <Renderer
      response={response}
      library={library}
      isStreaming={isStreaming}
      onAction={(event) => console.log("Action:", event)}
    />
  );
}
import { ChatProvider } from "@openuidev/react-headless";
import { openAIAdapter } from "@openuidev/react-headless";

function App() {
  return (
    <ChatProvider
      apiUrl="/api/chat"
      streamProtocol={openAIAdapter}  // OpenAI SDK のストリームに対応
    >
      <YourChatUI />
    </ChatProvider>
  );
}

// チャット状態の参照
import { useThread } from "@openuidev/react-headless";

function ChatMessages() {
  const { messages, isRunning, processMessage } = useThread();
  // ...
}
5 — API リファレンス
エクスポート種別説明
defineComponent(config)関数名前・Zod スキーマ・React レンダラーでコンポーネントを宣言
createLibrary(def)関数コンポーネント配列からライブラリを生成
library.prompt(opts)メソッドシステムプロンプトを生成
library.toJSONSchema()メソッドJSON Schema 表現を返す
<Renderer>コンポーネントOpenUI Lang テキストをリアルタイムで React に変換
createParser(library)関数完成テキスト用ワンショットパーサー
createStreamingParser(library)関数ストリーミング入力向けインクリメンタルパーサー

Renderer Props

Prop説明
responsestring | nullモデルからの生 OpenUI Lang テキスト
libraryLibrarycreateLibrary() で作成したライブラリ
isStreamingbooleanストリーミング中かどうか(フォームを無効化)
onAction(event) => voidコンポーネントのアクション発火時コールバック
onStateUpdate(state) => voidフォームフィールド値変更時コールバック
initialStateRecord<string, any>フォームの初期状態(ハイドレーション用)

Context Hooks(コンポーネントレンダラー内で使用)

Hook説明
useIsStreaming()ストリーミング中かどうか
useTriggerAction()アクションイベントを発火
useGetFieldValue()フォームフィールドの現在値を取得
useSetFieldValue()フォームフィールドの値を設定
useFormName()現在のフォーム名を取得
useRenderNode()子要素ノードを描画
Hook / コンポーネント返り値 / 説明
<ChatProvider>スレッド・メッセージ・ストリーミング状態を管理する Context プロバイダー
useThread()messages, isRunning, processMessage, cancelMessage, appendMessages など
useThreadList()threads, selectedThreadId, selectThread, switchToNewThread, deleteThread など
useMessage()メッセージコンポーネント内で現在のメッセージにアクセス

Streaming Adapters

アダプター説明
agUIAdapterデフォルト — AG-UI SSE イベントをパース
openAIAdapterOpenAI Chat Completions ストリーミングをパース
openAIResponsesAdapterOpenAI Responses API ストリームをパース
openAIReadableStreamAdapterOpenAI SDK の Stream.toReadableStream() NDJSON 出力をパース
カスタムアダプターは StreamProtocolAdapter インターフェースを実装し、AsyncIterable<AGUIEvent> を yield するだけで作成できます。
コンポーネント / エクスポート説明
FullScreenスレッドサイドバー付きフルページチャット
Copilotサイドパネル型コパイロットオーバーレイ
BottomTray折りたたみ可能なボトムトレイチャット
openuiLibraryフルコンポーネントライブラリ(チャート・テーブル・フォーム等)
openuiChatLibraryチャット最適化サブセット(フォローアップ・ステップ・コールアウト)
ThemeProviderカラー・タイポグラフィ・スペーシングのテーマ管理
createTheme(overrides)デフォルトテーマのカスタマイズ

コンポーネント一覧(カテゴリ別)

カテゴリコンポーネント
レイアウトCard, CardHeader, SectionBlock, Tabs, Accordion, Carousel, Separator, Steps
データ表示Table, Charts(バー/ライン/エリア/パイ/レーダー/散布図), ListBlock, Tag, CodeBlock, Image, ImageGallery
フォームInput, TextArea, Select, CheckBoxGroup, RadioGroup, SwitchGroup, Slider, DatePicker, FormControl
アクションButton, Buttons, IconButton, FollowUpBlock, FollowUpItem
フィードバックCallout, TextCallout, MessageLoading
コンテンツTextContent, MarkDownRenderer
コマンド説明主なオプション
openui create Next.js + OpenUI Chat のアプリをスキャフォールド --name, --no-interactive
openui generate <entry> createLibrary() エクスポートからシステムプロンプト or JSON Schema を生成 --json-schema, --out, --export
# システムプロンプトを標準出力へ
npx @openuidev/cli generate ./src/library.ts

# JSON Schema をファイルへ書き出し
npx @openuidev/cli generate ./src/library.ts --json-schema --out ./artifacts/schema.json
6 — ベンチマーク

tiktoken(GPT-5 エンコーダー)で計測。7 つの UI シナリオで JSON ベースの 2 フォーマットと比較。

シナリオ Vercel JSON-Render Thesys C1 JSON OpenUI Lang vs Vercel vs C1
simple-table340357148-56.5%-58.5%
chart-with-data520516231-55.6%-55.2%
contact-form893849294-67.1%-65.4%
dashboard224722611226-45.4%-45.8%
pricing-page248723791195-52.0%-49.8%
settings-panel12441205540-56.6%-55.2%
e-commerce-product244923811166-52.4%-51.0%
合計1018099484800-52.8%-51.7%
計測方法: tiktoken GPT-5 エンコーダー使用。各シナリオのトークン数は完全なシステムプロンプト込みで計測。詳細な再現手順は benchmarks/ ディレクトリに記載。
  • コスト削減 — トークン数が半分以下なら API コストも大幅に削減
  • レスポンス速度 — 出力量が少ないほど最初のトークンが届くまでの時間(TTFT)が短縮
  • コンテキスト節約 — 会話履歴と UI 出力を同じコンテキストウィンドウ内に収めやすい
  • 精度向上 — 簡潔な構造はモデルが誤った JSON を生成するリスクを低減