← 資料一覧

json-render

カタログで制約する Generative UI · Apache-2.0

1 — 概要

json-render は、開発者が定義したコンポーネントとアクションを使い、AI が JSON の画面仕様を生成するフレームワーク。アプリはその仕様を受け取り、登録済みの実装で描画します。ダッシュボード、フォーム、会話中の UI などに利用できます。

見た目や処理の実装は開発者が管理し、AI には組み合わせ方を生成させます。固定の JSON を手で用意して描画することもでき、AI 接続は必須ではありません。

2 — 3つの役割

01 · Catalog

使える部品名、props の Zod スキーマ、説明、アクションを宣言。モデルへの指示の材料になります。

02 · Spec

画面のインスタンス。root と elements を持ち、子要素を ID で参照します。

03 · Registry

部品名を React などの実装に対応付けます。Renderer が spec をたどり、登録した部品を描画します。

カタログは利用できる語彙、spec はその組み合わせ、レジストリは実際の描画処理です。defineCatalog と defineRegistry は別の責務を持ちます。

3 — React で描画

React アプリを用意し、次の依存を追加します。確認した 0.21.1 の peer dependency は React ^19.2.3 と Zod ^4.0.0 です。この例は固定 spec の描画を確認するものです。内部で必要になる状態・表示条件・アクションのコンテキストを、JSONUIProvider でまとめて供給します。Next.js App Router ではクライアントコンポーネントとして配置します。

npm install @json-render/core @json-render/react zod
"use client";

import { defineCatalog } from "@json-render/core";
import { defineRegistry, JSONUIProvider, Renderer } from "@json-render/react";
import { schema } from "@json-render/react/schema";
import { z } from "zod";

const catalog = defineCatalog(schema, {
  components: {
    Metric: {
      props: z.object({ label: z.string(), value: z.string() }),
      description: "ラベル付きの指標を表示する",
    },
  },
  actions: {},
});

const { registry } = defineRegistry(catalog, {
  components: {
    Metric: ({ props }) => (
      <article>
        <h3>{props.label}</h3>
        <output>{props.value}</output>
      </article>
    ),
  },
});

const spec = {
  root: "sales",
  elements: {
    sales: {
      type: "Metric",
      props: { label: "今月の売上", value: "¥128,000" },
      children: [],
    },
  },
};

export default function App() {
  return (
    <JSONUIProvider registry={registry}>
      <Renderer spec={spec} registry={registry} />
    </JSONUIProvider>
  );
}

描画イメージ(静的な HTML による見本):

今月の売上

¥128,000

children に他の要素 ID を並べると、コンテナと子要素の構造を表現できます。上の例では actions: {} のため、レジストリのアクション実装は省略できます。

4 — 状態とイベント

仕組み用途アプリ側の接続
$stateJSON Pointer で状態を参照StateProvider で状態を供給
$bindStateフォーム値の読み書き部品実装で useBoundProp を使用
visible状態に応じた条件付き表示条件式と参照先の状態を定義
emit("press")部品からイベントを通知spec の on でアクションに接続
ActionProviderアクションの実行先を供給ハンドラから API や業務処理を呼ぶ

状態参照やイベントを使うときは、必要な Provider とハンドラを組み込みます。送信内容の検証とサーバー側の認可はアプリで実装します。

5 — 生成とストリーミング

  1. catalog.prompt() で部品・props・アクションを説明するシステムプロンプトを作成します。
  2. 使用するモデルに、ユーザーの要求とシステムプロンプトを渡します。モデル接続と API エンドポイントはアプリで用意します。
  3. SpecStream では JSONL の JSON Patch を順に受信し、コンパイラで部分 spec を組み立てます。
  4. 描画可能な部分を更新し、完了後の spec とエラーを確認します。
import { createSpecStreamCompiler } from "@json-render/core";

// 概念例: chunk の受信と画面への反映はアプリで実装
const compiler = createSpecStreamCompiler();
const { result } = compiler.push(chunk);
const finalSpec = compiler.getResult();

React には useUIStream などのフックもあります。受信途中の不完全な仕様、生成失敗、再試行時の表示を設計してください。プロンプトでの制約だけで、モデルの出力が常に正しいと仮定しないことが必要です。

6 — 対応パッケージ

共通のコアと、用途別のレンダラー・補助パッケージに分かれています。代表例は以下のとおりです。

用途パッケージ
スキーマ・カタログ・プロンプト・ストリーム@json-render/core
Web UI@json-render/react、vue、svelte、solid
既製 UI 部品@json-render/shadcn、shadcn-svelte
モバイル・ターミナル・3D@json-render/react-native、ink、react-three-fiber
動画・PDF・メール・画像@json-render/remotion、react-pdf、react-email、image
アプリのルーティング・SSR@json-render/next、tanstack-start
外部ストア・開発支援@json-render/redux、zustand、jotai、xstate、devtools、mcp

表の省略名には @json-render/ が付きます。描画先によってスキーマや対応機能が異なるため、同じ spec がそのまま全環境で動くとは限りません。各パッケージの README で依存と機能を確認してください。

7 — 導入時の確認

  • 生成結果を検証: catalog.validate() でスキーマへの適合を、validateSpec() で spec の構造・参照整合性を確認します。コアの validateSpec は構造上の問題を返すための API で、業務上の妥当性を保証するものではありません。
  • アクションの権限: 非表示のボタンや許可されたアクション名だけを認可の根拠にせず、処理を実行するサーバー側でユーザー権限と引数を検証します。
  • 登録部品の責任: URL の扱い、HTML の埋め込み、外部通信などは部品実装に依存します。任意コードを実行する部品を公開すれば、カタログの制約だけでは防げません。
  • 実行環境を用意: パッケージの導入だけで AI バックエンドが完成するわけではありません。モデルへの接続、必要な認証情報、ストリームのエラー処理を組み込みます。

確認日: 2026-10-21。取得した main のコミット 72568f9 に基づきます。React パッケージのソース内バージョン表記は 0.21.1。npm の最新公開版を示すものではありません。