mcpField
J
json-render-catalog

json-render-catalog

github.com/yonatangrossデザイン・UI29994 回インストール今日更新
リポジトリ

json-render-catalog について

json-render Component Catalogs は、json-render 用の制約付きコンポーネントカタログを構築するスキルです。Storybookからのインポートと、安全なディレクティブの利用に重点を置いています。

主な機能

  1. 01Storybookのストーリーからカタログをインポート
  2. 02Zodでコンポーネントとプロパティを制約
  3. 03組み込み・カスタムディレクティブの利用
  4. 04名前付きコンテンツスロットの対応
  5. 05複数の表示先への仕様のレンダリング

活用シーン

  1. 01既存のStorybook設定からカタログを生成
  2. 02AI生成UIを許可されたコンポーネントに限定
  3. 03書式設定や翻訳値を安全に計算

MCP 対応

READMEでは、@json-render/mcpがMCPツールのJSONを会話内のインタラクティブなiframeに変換すると説明されています。同じ仕様を複数の表示先にレンダリングするMCP連携にも触れています。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yonatangross/orchestkit --skill json-render-catalog

インストール後、Claude Code で/json-render-catalogを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

test-cases.json
references/
ork-delta.md
package-ecosystem.md
storybook-fixture.json
storybook-import.md
rules/
_sections.md
_template.md
catalog-definition.md
prop-constraints.md
token-optimization.md
scripts/
storybook-to-catalog.mjs

詳細

アップストリームのバージョン参照:@json-render/core 0.21.0(2026-09-30)。

json-render コンポーネントカタログ

json-render(Vercel Labs、12.9K stars、Apache-2.0)は、AI セーフなジェネレーティブ UI のためのフレームワークです。AI は、開発者が定義したカタログに制約されたフラットツリー形式の JSON(または YAML)仕様を生成します。カタログは、デザインシステムと AI の出力をつなぐ契約です。カタログにないコンポーネントやプロパティを AI が生成することはできません。

Storybook からカタログへのインポート(#1529、2026-04)

プロジェクトに Storybook の設定がある場合は、カタログを手書きするのではなく、Storybook のストーリーからインポートしてください。付属のインポーター scripts/storybook-to-catalog.mjs は、@storybook/addon-mcp の list-all-documentation マニフェストを読み込み、Zod 型付きの catalog.ts と components.tsx レジストリを生成します。

node "${CLAUDE_SKILL_DIR}/scripts/storybook-to-catalog.mjs" storybook-manifest.json \
  --out src/genui/catalog.ts \
  --components src/genui/components.tsx \
  --project-root .

Storybook が唯一の信頼できる情報源になります。ストーリーを追加すると AI が使用できる範囲が自動的に広がり、削除すると狭まります。インポート時に、コールバック、生のオブジェクトプロパティ、z.any() が除外されるため、AI の安全性が確保されます。マッピングの詳細:references/storybook-import.md。テスト用の関連フィクスチャ:references/storybook-fixture.json。

2026-04 → 2026-08 の新機能(json-render 0.14 → 0.20)

  • 名前付きスロット(0.20) — UIElement に slots?: Record<string, string[]> が追加され、カタログでは slots: ["default", "header", "footer"] のように受け入れるスロットを宣言できます。また、React のレジストリコンポーネントは slots?.header として名前付きコンテンツを受け取り、children はデフォルトスロットのままです。レイアウト領域を別々の兄弟要素として表現するよりも、こちらを優先してください。
  • ネストされた繰り返しと項目スコープの表示制御(0.20) — repeat.statePath では、項目相対の {"$item": "employees"} 形式を使用できるようになりました(新しい RepeatStatePath 型と resolveRepeatStatePath/resolveRepeatItemStatePath を追加)。また、同じ要素で repeat と visible: {"$item": "status", "eq": "todo"} を組み合わせると、エラーではなく項目のフィルタリングが行われます。validateSpec に invalid_visible、repeat_without_children、repeat_item_outside_scope、repeat_state_mismatch の問題コードが追加されました。
  • カスタムディレクティブ API(0.19) — @json-render/core に defineDirective が追加され、レンダリング時に計算値へ解決される新しい JSON 形式(例:$format、$math)を宣言できるようになりました。ディレクティブはネストして組み合わせられ、内側から外側に向かって解決されます。React、Vue、Svelte、Solid の 4 つのレンダラーすべてに、ディレクティブ解決機能が組み込まれています。カタログを z.any() に広げることなく計算値を扱える、安全な拡張方法です。
  • @json-render/directives パッケージ(0.19) — すぐに使える 7 つのディレクティブを提供します。$format(Intl による日付/通貨/数値/パーセント)、$math(加算、減算、乗算、除算、剰余、最小値、最大値、四捨五入、切り捨て、切り上げ、絶対値)、$concat、$count、$truncate、$pluralize、$join です。さらに、{{param}} 補間に対応した $t 翻訳キー用の createI18nDirective と、1 行で登録できる standardDirectives も用意されています。一度登録すれば、どの spec でも使用できます。AI が文字列の加工やリテラルの重複を行う必要はありません。
  • Devtools エコシステム(0.18) — 新たに 5 つのパッケージが追加されました。@json-render/devtools コアと、React、Vue、Svelte、Solid 用のフレームワークアダプターです。インスペクターパネルには 6 つのタブ(Spec、State、Actions、Stream、Catalog、Pick)があり、DOM 要素を選択して対応する spec キーを確認できます。本番環境ではツリーシェイクにより null になります。AI チャットとカタログを連携した Next.js デモアプリも同梱されています。アダプターがイベントをパネルに反映できるよう、アクションオブザーバーの基盤も公開されています。
  • Zod 4 の修正(0.18) — formatZodType が z.record()、z.default()、z.literal() を正しく処理するようになりました(以前はプロンプト出力が空、または不正になっていました)。
  • 3 つの編集モード(0.14) — AI による段階的な改善のための patch(RFC 6902)、merge(RFC 7396)、diff(統合形式)です。@json-render/core に buildEditUserPrompt()、diffToPatches()、deepMergeSpec() が追加されました。
  • @json-render/yaml(0.14) — YAML の公式ワイヤーフォーマットとストリーミングパーサーを提供します。buildUserPrompt({ format: 'yaml' }) を使用してください。
  • @json-render/ink(0.15) — 同じ spec を使って、カタログをターミナル UI(Ink ベース、20 以上のコンポーネント)にレンダリングできます。
  • @json-render/next(0.16) — 1 つの spec から、完全な Next.js アプリ(ルート、レイアウト、SSR、メタデータ)を生成します。
  • @json-render/shadcn-svelte(0.16) — React の shadcn カタログに対応する、Svelte 5 + Tailwind 製の 36 コンポーネントのミラーです。
  • shadcn カタログは 36 コンポーネントに対応(29 と記載されていましたが、0.13 の時点でも数が誤っていました)。@json-render/shadcn をそのまま使うか、shadcnComponentDefinitions を独自の定義とともに展開してください。
  • @json-render/react-three-fiber には 19 個のコンポーネントがあります(2026-07-31 にアップストリームのスキルと照合して確認済みです。ここでは一覧を再掲せず、「アップストリームの対応状況」を参照してください)。
  • @json-render/mcp — 通常の MCP ツール JSON を、Claude/Cursor/ChatGPT の会話内で操作可能な iframe に変換します。ork:mcp-visual-output スキルを参照してください。
  • MCP のマルチサーフェス対応:同じ spec を React、PDF(@json-render/react-pdf)、メール(@json-render/react-email)、ターミナル(Ink)、Next.js アプリ、Remotion 動画にレンダリングできます。

ディレクティブ — @json-render/directives (0.19)

ディレクティブは、計算値を扱うための安全な拡張手段です。AI が $ で始まるオブジェクトを出力すると、レンダラーはコンポーネントに props が渡される前に内側から順に解決します。これによりカタログは厳密なまま(z.any() による型の拡張は不要)、仕様も宣言的に保たれます。@json-render/directives パッケージには、組み込みディレクティブ 7 種と i18n ファクトリーが含まれています。standardDirectives では、それらをひとつの配列としてエクスポートしているため、1 行で登録できます。ディレクティブは自由にネストできます(例:$math を $format でラップ)。また、4 つすべてのレンダラー統合(React、Vue、Svelte、Solid)で解決されます。

登録
import { defineRegistry, JSONUIProvider, Renderer } from '@json-render/react'
import { standardDirectives, createI18nDirective } from '@json-render/directives'

const directives = [
  ...standardDirectives,
  createI18nDirective({
    locale: 'en',
    fallbackLocale: 'en',
    messages: { en: { greeting: 'Hello, {{name}}!' } },
  }),
]

const { registry } = defineRegistry(catalog, { components })

// directives register on the provider (RendererProps has no directives prop)
<JSONUIProvider registry={registry} directives={directives}>
  <Renderer spec={spec} registry={registry} />
</JSONUIProvider>
組み込みディレクティブ 7 種
ディレクティブ目的最小限の使用例
$formatdate、currency、number、percent の Intl ベースのフォーマットです。locale、currency、notation、および人間が読みやすい日付の差分を表示する style: "relative" に対応しています。{ "$format": "currency", "value": 1299, "currency": "USD" } → $1,299.00
$math算術演算です。add、subtract、multiply、divide、mod、min、max、round、floor、ceil、abs に対応しています。ゼロ除算の結果は 0 です。数値以外の入力は 0 に変換されます。{ "$math": "multiply", "a": { "$state": "/qty" }, "b": 9.99 }
$concat動的な値の配列を文字列に結合します。各要素は、まずディレクティブのパイプラインを通して解決されます。{ "$concat": ["Hello, ", { "$state": "/user/name" }, "!"] }
$count配列または文字列の長さを返します。それ以外の場合は 0 を返します。{ "$count": { "$state": "/items" } }
$truncatelength(既定値は 100)で切り詰めます。任意で suffix(既定値は ...)を指定できます。すでに指定の長さ以下の場合は何もしません。{ "$truncate": { "$state": "/bio" }, "length": 80 }
$pluralize単数形/複数形/ゼロの場合の表記を選択します。件数を自動的に前置します("3 items"、"1 item"、または zero の文字列)。{ "$pluralize": { "$state": "/cart/count" }, "zero": "no items", "one": "item", "other": "items" }
$join配列を separator(既定値は ", ")で結合します。{ "$join": { "$state": "/tags" }, "separator": " · " }

createI18nDirective({ locale, messages, fallbackLocale? }) は、{{param}} 補間に対応した $t ディレクティブを登録します。使用例:{ "$t": "greeting", "params": { "name": "Ada" } }。

defineDirective によるカスタムディレクティブ

defineDirective は @json-render/core (0.19+) にあります。ディレクティブでは、JSON の形式を定義する Zod スキーマと resolve(raw, ctx) 関数を宣言します。計算する前に、ネストされたディレクティブや状態参照を再帰的に解決するには、resolvePropValue(raw.field, ctx) を使用します。

import { defineDirective, resolvePropValue } from '@json-render/core'
import { z } from 'zod'

export const initialsDirective = defineDirective({
  name: '$initials',
  description: 'First letter of each word, uppercased.',
  schema: z.object({ $initials: z.unknown() }),
  resolve(raw, ctx) {
    const text = String(resolvePropValue(raw.$initials, ctx) ?? '')
    return text.split(/\s+/).map((w) => w[0]?.toUpperCase() ?? '').join('')
  },
})

standardDirectives とともにレンダラーへ展開します:directives={[...standardDirectives, initialsDirective]}。スキーマは厳密に保ってください。ディレクティブは、AI がカタログ外の JSON を出力できる唯一の場所です。そのため、コンポーネントの prop と同じように、Zod で形式を検証してください。

Upstream のカバレッジ(再掲しないでください)

json-render には、パッケージごとの独自のスキルが用意されています。このスキルはそれらをラップし、差分のみを残します。差分とは、独自の Storybook インポートパス、独自のカタログ制約、そして references/ork-delta.md に記載された過去の失敗から得た知見です。ベンダーの一覧や API テーブルを再掲しないでください。

トピックファーストパーティのソース
コア API(defineSchema、defineCatalog、プロンプト、仕様のストリーミング、検証、StateStore)https://github.com/vercel-labs/json-render skills/core/SKILL.md
仕様の形式、動的なプロパティ式($state / $bindState / $cond / $template / $computed)、watch、表示制御https://github.com/vercel-labs/json-render skills/core/SKILL.md および skills/react/SKILL.md
組み込みアクション(setState、pushState、removeState、validateForm)とイベントシステムhttps://github.com/vercel-labs/json-render skills/react/SKILL.md
shadcn のコンポーネント一覧とプロパティスキーマ(36 コンポーネント、React および Svelte)vercel:shadcn スキル、および https://github.com/vercel-labs/json-render skills/shadcn/SKILL.md と skills/shadcn-svelte/SKILL.md
レンダラーごとのコンポーネントと API(Vue、Svelte、Solid、React Native、Ink、Next.js、PDF、email、image、Remotion、react-three-fiber)https://github.com/vercel-labs/json-render skills/<package>/SKILL.md
YAML のワイヤ形式、フェンス、ストリーミングコンパイラー、編集モードhttps://github.com/vercel-labs/json-render skills/yaml/SKILL.md
状態アダプター(zustandStateStore、reduxStateStore、jotaiStateStore、xstateStoreStateStore)https://github.com/vercel-labs/json-render skills/zustand/SKILL.md、skills/redux/SKILL.md、skills/jotai/SKILL.md、skills/xstate/SKILL.md
MCP Apps の統合(createMcpApp、iframe クライアント)ork:mcp-visual-output、および https://github.com/vercel-labs/json-render skills/mcp/SKILL.md
手書きの JSON からコンポーネントへのマッパーの移行https://github.com/vercel-labs/json-render skills/core/SKILL.md(カタログと仕様の契約が目標の形です)

独自の差分、つまり upstream のドキュメントにない内容は、references/ork-delta.md に記載されています。

クイックリファレンス

カテゴリルール影響度使用する場面
カタログの定義1高Zod を使ったコンポーネントカタログの定義
プロパティの制約1高安全性のために AI 生成プロパティを制約する
トークンの最適化1中YAML モードでトークン使用量を削減する

合計:3 カテゴリにわたる 3 つのルール

json-render の仕組み

  1. 開発者がカタログを定義する — プロパティを制約した、Zod 型付きのコンポーネント定義
  2. AI が仕様を生成する — カタログ内のコンポーネントのみを参照する、フラットツリー形式の JSON/YAML
  3. ランタイムが仕様をレンダリングする — <Renderer> コンポーネントが各要素を検証してレンダリングします

カタログが安全性の境界になります。AI が参照できるのはカタログに存在する型のみで、プロパティはランタイムで Zod スキーマに照らして検証されます。これにより、幻覚によるコンポーネントや無効なプロパティが UI に到達するのを防ぎます。

クイックスタート — 3 ステップ

ステップ 1:カタログを定義する
import { defineCatalog } from '@json-render/core'
import { schema } from '@json-render/react/schema'
import { z } from 'zod'

export const catalog = defineCatalog(schema, {
  components: {
    Card: {
      props: z.object({
        title: z.string(),
        description: z.string().optional(),
      }),
      children: true,
    },
    Button: {
      props: z.object({
        label: z.string(),
        variant: z.enum(['default', 'destructive', 'outline', 'ghost']),
      }),
      children: false,
    },
    StatGrid: {
      props: z.object({
        items: z.array(z.object({
          label: z.string(),
          value: z.string(),
          trend: z.enum(['up', 'down', 'flat']).optional(),
        })).max(20),
      }),
      children: false,
    },
  },
})
LLM の構造化出力との互換性

jsonSchema({ strict: true }) を使用して、LLM の構造化出力 API(OpenAI、Anthropic、Gemini)と互換性のあるカタログスキーマをエクスポートします。

// jsonSchema is a METHOD on the Catalog instance, not a top-level export.
const schema = catalog.jsonSchema({ strict: true })
// Pass to OpenAI response_format, Anthropic tool_use, or Gemini structured output
ステップ 2:コンポーネントを実装する
import type { InferCatalogComponents } from '@json-render/core'
import type { catalog } from './catalog'

export const components: InferCatalogComponents<typeof catalog> = {
  Card: ({ title, description, children }) => (
    <div className="rounded-lg border p-4">
      <h3 className="font-semibold">{title}</h3>
      {description && <p className="text-muted-foreground">{description}</p>}
      {children}
    </div>
  ),
  Button: ({ label, variant }) => (
    <button className={cn('btn', `btn-${variant}`)}>{label}</button>
  ),
  StatGrid: ({ items }) => (
    <div className="grid grid-cols-3 gap-4">
      {items.map((item) => (
        <div key={item.label}>
          <span>{item.label}</span>
          <strong>{item.value}</strong>
        </div>
      ))}
    </div>
  ),
}
ステップ 3:仕様をレンダリングする
import { defineRegistry, Renderer } from '@json-render/react'
import { catalog } from './catalog'
import { components } from './components'

// defineRegistry returns DefineRegistryResult — destructure `registry`
const { registry } = defineRegistry(catalog, { components })

function App({ spec }: { spec: JsonRenderSpec }) {
  return <Renderer spec={spec} registry={registry} />
}

仕様の形式

JSON 仕様はフラットツリー形式です。ネストはなく、ID と参照のみで構成されます。フィールドごとのドキュメント(root、elements、props、children、on、watch、state、および $state / $bindState / $cond / $template / $computed 式)は、upstream の https://github.com/vercel-labs/json-render skills/core/SKILL.md にあります。

{
  "root": "card-1",
  "elements": {
    "card-1": {
      "type": "Card",
      "props": { "title": "Dashboard" },
      "children": ["chart-1", "btn-1"]
    },
    "btn-1": {
      "type": "Button",
      "props": { "label": "View Details", "variant": "default" }
    }
  }
}
インタラクティブ機能あり(on / watch / state)
{
  "root": "card-1",
  "elements": {
    "card-1": {
      "type": "Card",
      "props": { "title": "Dashboard" },
      "children": ["chart-1", "btn-1"],
      "on": { "press": { "action": "setState", "path": "/view", "value": "detail" } },
      "watch": { "/data": { "action": "load_data", "url": "/api/stats" } }
    }
  },
  "state": { "/activeTab": "overview" }
}

イベントハンドラー、watch バインディング、組み込みアクション(setState、pushState、 removeState、validateForm)、および state アダプターは、上流の https://github.com/vercel-labs/json-render skills/react/SKILL.md と各アダプターの スキルに記載されています。ここで一覧を繰り返さないでください。その理由については references/ork-delta.md を参照してください。

YAML モード — トークンを30%削減

スタンドアロン(非ストリーミング)で生成する場合、YAML 仕様は JSON よりトークンを約30%削減できます。

root: card-1
elements:
  card-1:
    type: Card
    props:
      title: Dashboard
    children: [chart-1, btn-1]
  btn-1:
    type: Button
    props:
      label: View Details
      variant: default

インラインモード/ストリーミングでは JSON を使用してください(JSONL 上の JSON Patch RFC 6902 には JSON が必要です)。トークンコストが重要なスタンドアロンモードでは YAML を使用してください。選択基準については rules/token-optimization.md を読み込んでください。

プログレッシブストリーミング

json-render はストリーミング中のプログレッシブレンダリングに対応しています。AI が仕様の要素を生成すると、すぐにレンダリングされ、ユーザーは UI がリアルタイムで構築される様子を確認できます。これは、JSONL 上でストリーミングされる JSON Patch(RFC 6902)操作を使用します。

{"op":"add","path":"/elements/card-1","value":{"type":"Card","props":{"title":"Dashboard"},"children":[]}}
{"op":"add","path":"/elements/btn-1","value":{"type":"Button","props":{"label":"Save","variant":"default"}}}
{"op":"add","path":"/elements/card-1/children/-","value":"btn-1"}

要素は、props が完成するとすぐにレンダリングされます。仕様全体を待つ必要はありません。

@json-render/shadcn — 36個の組み込みコンポーネント

@json-render/shadcn パッケージには、Zod スキーマがあらかじめ定義された、本番環境対応の36個のコンポーネントカタログが用意されています。 コンポーネント一覧と props スキーマは、上流の https://github.com/vercel-labs/json-render skills/shadcn/SKILL.md に記載されています。shadcn/ui 自体の構成については、vercel:shadcn スキルを参照してください。

Svelte: @json-render/shadcn-svelte(0.16で追加)は、Svelte 5 + Tailwind プロジェクト向けに同じ36個のコンポーネントを提供します。

import { shadcnComponentDefinitions, shadcnComponents } from '@json-render/shadcn'
import { defineRegistry, Renderer } from '@json-render/react'

// Use as-is
const { registry } = defineRegistry(shadcnComponentDefinitions, { components: shadcnComponents })
<Renderer spec={spec} registry={registry} />

// Or merge with custom components
const catalog = { ...shadcnComponentDefinitions, ...customCatalog }
スタイル対応カタログ

shadcn カタログのコンポーネントでは、デフォルトの Tailwind クラスが使用されます。プロジェクトで特定の shadcn v4 スタイル(Luma、Nova など)を使用している場合は、コンポーネントの実装を上書きして一致させてください。

import { shadcnComponentDefinitions, shadcnComponents } from '@json-render/shadcn'
import type { InferCatalogComponents } from '@json-render/core'

// Override shadcn component implementations for Luma style
const lumaComponents: Partial<InferCatalogComponents<typeof shadcnComponentDefinitions>> = {
  Card: ({ title, description, children }) => (
    <div className="rounded-4xl border shadow-md ring-1 ring-foreground/5 p-6">
      <h3 className="font-semibold">{title}</h3>
      {description && <p className="text-muted-foreground">{description}</p>}
      <div className="mt-6">{children}</div>
    </div>
  ),
  Button: ({ label, variant }) => (
    <button className={cn('rounded-4xl', buttonVariants({ variant }))}>{label}</button>
  ),
}

// Merge: catalog schema unchanged, only rendering adapts to style
const components = { ...shadcnComponents, ...lumaComponents }

検出パターン: components.json の "style" フィールドを読み取り、適用する上書きを判断してください。スタイル固有のクラス名:Luma(rounded-4xl、shadow-md、gap-6)、Nova(コンパクトな px-2 py-1)、Lyra(rounded-none)。

編集モード — patch / merge / diff(0.14+)

初回レンダリング後に仕様を更新する場合(AI による調整、ユーザー編集、一部の再生成)、コアには3つの汎用編集モードが用意されています。

モード仕様使用する場面
patchRFC 6902 JSON Patch差分を正確にストリーミングする場合(プログレッシブストリーミングですでに使用)
mergeRFC 7396 JSON Merge Patchよりシンプルな更新や、フィールド全体の置き換え
diffシリアライズされた仕様の Unified diffモデルがプレーンテキストの差分を優先する場合の、AI ネイティブな出力
import { deepMergeSpec, diffToPatches, buildEditUserPrompt } from '@json-render/core'

// Ask the model for an edit in whichever format it finds easiest
const prompt = buildEditUserPrompt(currentSpec, instruction, { format: 'yaml', mode: 'merge' })

// Normalize any edit mode to RFC 6902 patches for application
const patches = diffToPatches(aiResponse)
const next = deepMergeSpec(currentSpec, patches)

0.14では buildUserPrompt() に format と serializer オプションも追加されました。スタンドアロン仕様には YAML、ストリーミングには JSON を選択してください。

パッケージエコシステム

ウェブ、モバイル、ターミナル、3D、コード生成、状態管理に対応する、コアと23個のレンダラー/統合パッケージがあります。カテゴリ別に整理された全一覧については、references/package-ecosystem.md を読み込んでください。

0.13以降に追加:

  • @json-render/yaml(0.14)— YAML ワイヤーフォーマット + ストリーミングパーサー
  • @json-render/ink(0.15)— ターミナル UI レンダラー(Ink ベース、20個以上のコンポーネント)
  • @json-render/next(0.16)— Next.js アプリ全体を生成(ルート、レイアウト、SSR、メタデータ)
  • @json-render/shadcn-svelte(0.16)— React shadcn カタログを再現した、36コンポーネントの Svelte 5 向けパッケージ
  • @json-render/react-three-fiber には19個のコンポーネントが含まれます(2026-07-31確認済み。一覧は上流にあります)
  • @json-render/devtools + フレームワークアダプター(0.18)— 6タブのインスペクターパネル、DOM ピッカー、本番環境では null にツリーシェイク
  • @json-render/directives(0.19)— 7つの Intl/数学/文字列ディレクティブ + createI18nDirective + standardDirectives 登録ヘルパー

使用する場合と使用しない場合

json-render を使用する場合:

  • AI に UI を生成させる際、生成可能な内容を制限する必要がある
  • ハルシネーションによるコンポーネントの生成を防ぐ、実行時に検証される仕様が必要である
  • クロスプラットフォームのレンダリング(React、Vue、Svelte、React Native、PDF、メール)が必要である
  • 生成 UI の機能(自然言語からのダッシュボード、レポート、フォームの生成)を構築している

json-render を使用しない場合:

  • 静的な、開発者が作成する UI を構築している — コンポーネントを直接使用してください
  • AI が仕様ではなくコード(JSX/TSX)を生成する — 標準的なコード生成を使用してください
  • カタログの制約を受けずに完全な創造の自由が必要である — json-render は意図的に制約を設けています
  • 数千の要素を扱うパフォーマンス重視のレンダリングが必要である — フラットツリーの抽象化によってオーバーヘッドが発生します

カスタム GenUI からの移行

既存のカスタム生成 UI(手作業で作成した JSON からコンポーネントへのマッピング)がある場合、 移行先は、上流の https://github.com/vercel-labs/json-render skills/core/SKILL.md に記載された カタログとフラットツリー仕様の契約です。次の手順が効果的です。 既存の型を一覧にし、それぞれに defineCatalog で Zod スキーマを定義し、ネストされた仕様を root と elements にフラット化し、ハンドラープロパティを on フィールドに移してから、 既存のコンポーネントをカタログ実装としてラップします。

ルールの詳細

カタログ定義

defineCatalog() と Zod スキーマを使用してカタログを定義する方法です。

ルールファイル主要パターン
カタログ定義rules/catalog-definition.mdZod スキーマ、子要素の型を使用した defineCatalog
プロパティの制約

AI によるハルシネーションを防ぐためのプロパティの制約です。

ルールファイル主要パターン
プロパティの制約rules/prop-constraints.mdz.enum、z.string().max()、z.array().max()
トークンの最適化

トークン効率を高めるために JSON と YAML のどちらを選ぶかです。

ルールファイル主要パターン
トークンの最適化rules/token-optimization.mdスタンドアロンモードでは YAML、インライン/ストリーミングでは JSON

主な判断基準

判断項目推奨事項
カスタムカタログと shadcn カタログshadcn から始め、ドメイン固有のコンポーネントにはカスタム型を追加します
JSON と YAML の仕様形式スタンドアロンモードでは YAML(トークンを 30%削減)、インライン/ストリーミングでは JSON
Zod 制約の厳しさ厳しいほど適切です。z.string より z.enum を、上限のない z.array より z.array().max() を使用します
状態管理アダプターアプリで既に使用している状態管理ライブラリ(Zustand、Redux、Jotai、XState)に合わせます

よくある間違い

  1. カタログのプロパティで z.any() または z.unknown() を使用する — カタログ制約の目的が失われ、AI が何でも生成できるようになります
  2. 常に JSON 仕様を使用する — インライン/ストリーミングが不要な場合、トークンを 30%無駄にします(スタンドアロンモードでは YAML を使用してください)
  3. コンポーネント定義をネストする — json-render はフラットツリーを使用します。すべての要素は、ID で参照される兄弟要素です
  4. shadcnComponentDefinitions を展開せずに shadcn コンポーネントを再定義する — 上流の Zod 境界が失われます
  5. 配列に .max() を設定しない — AI がレイアウトを壊すような、上限のないリストを生成する可能性があります

関連スキル

  • ork:ai-ui-generation — v0、Bolt、Cursor 向けの AI 支援 UI 生成パターン
  • ork:ui-components — shadcn/ui コンポーネントのパターンと CVA バリアント
  • ork:component-search — React/Vue コンポーネントの検索と評価
  • ork:design-to-code — デザインを本番用コードに変換

コメント