json-render-core について
@json-render/coreは、AI生成UIの構造を定義する開発者向けに、json-renderのスキーマ、カタログ、仕様ストリーミングを提供します。動的プロパティの解決、検証、外部状態ストア用インターフェースも備えています。
主な機能
- 01スキーマとコンポーネントカタログの定義
- 02AIプロンプトの生成
- 03JSONL仕様パッチのストリーミング
- 04状態駆動の動的プロパティ解決
- 05仕様の検証と自動修正
- 06交換可能な状態ストアインターフェース
活用シーン
- 01AI生成UIの構造定義
- 02ストリーミング仕様出力の逐次処理
- 03生成仕様の検証や修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel-labs/ json-render --skill json-render-coreインストール後、Claude Code で/json-render-coreを入力して読み込まれたか確認します。
詳細
@json-render/core
スキーマ定義、カタログ作成、仕様のストリーミングを行うコアパッケージです。
主な概念
- スキーマ:仕様とカタログの構造を定義します(
defineSchemaを使用) - カタログ:コンポーネント名/アクション名を定義に対応付けます(
defineCatalogを使用) - 仕様:スキーマに準拠した、AI による JSON 出力です
- SpecStream:仕様を段階的に構築するための JSONL ストリーミング形式です
スキーマの定義
import { defineSchema } from "@json-render/core";
export const schema = defineSchema((s) => ({
spec: s.object({
// Define spec structure
}),
catalog: s.object({
components: s.map({
props: s.zod(),
description: s.string(),
}),
}),
}), {
promptTemplate: myPromptTemplate, // Optional custom AI prompt
});
カタログの作成
import { defineCatalog } from "@json-render/core";
import { schema } from "./schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Button: {
props: z.object({
label: z.string(),
variant: z.enum(["primary", "secondary"]).nullable(),
}),
description: "Clickable button component",
},
},
});
AI プロンプトの生成
const systemPrompt = catalog.prompt(); // Uses schema's promptTemplate
const systemPrompt = catalog.prompt({ customRules: ["Rule 1", "Rule 2"] });
SpecStream ユーティリティ
AI の応答をストリーミングする場合(JSONL パッチ):
import { createSpecStreamCompiler } from "@json-render/core";
const compiler = createSpecStreamCompiler<MySpec>();
// Process streaming chunks
const { result, newPatches } = compiler.push(chunk);
// Get final result
const finalSpec = compiler.getResult();
動的なプロパティ式
レンダリング時に解決される動的な式を、任意のプロパティ値として指定できます。
{ "$state": "/state/key" }- 状態モデルから値を読み取ります(単方向の読み取り){ "$bindState": "/path" }- 双方向バインディングです。状態を読み取り、書き戻しを有効にします。フォームコンポーネントの自然な値プロパティ(value、checked、pressed など)に使用します。{ "$bindItem": "field" }- 繰り返し項目のフィールドに対する双方向バインディングです。繰り返しスコープ内で使用します。{ "$cond": <condition>, "$then": <value>, "$else": <value> }- 表示条件を評価して、分岐を選択します{ "$template": "Hello, ${/user/name}!" }-${/path}参照を状態値で補間します{ "$computed": "fnName", "args": { "key": <expression> } }- 解決済みの引数を使って登録済み関数を呼び出します
$cond では、表示条件と同じ構文($state、eq、neq、not、AND を表す配列)を使用します。$then と $else にも式を指定できます(再帰的に評価されます)。
コンポーネントでは、双方向バインディングに statePath プロパティを使用しません。代わりに、自然な値プロパティ(例:value、checked、pressed)に { "$bindState": "/path" } を指定します。
{
"color": {
"$cond": { "$state": "/activeTab", "eq": "home" },
"$then": "#007AFF",
"$else": "#8E8E93"
},
"label": { "$template": "Welcome, ${/user/name}!" },
"fullName": {
"$computed": "fullName",
"args": {
"first": { "$state": "/form/firstName" },
"last": { "$state": "/form/lastName" }
}
}
}
import { resolvePropValue, resolveElementProps } from "@json-render/core";
const resolved = resolveElementProps(element.props, { stateModel: myState });
状態ウォッチャー
要素に watch フィールド(type/props/children と同じ階層のトップレベル)を宣言すると、状態値の変化時にアクションを実行できます。
{
"type": "Select",
"props": { "value": { "$bindState": "/form/country" }, "options": ["US", "Canada"] },
"watch": {
"/form/country": { "action": "loadCities", "params": { "country": { "$state": "/form/country" } } }
},
"children": []
}
ウォッチャーは値が変化した場合にのみ実行され、初回のレンダリング時には実行されません。
バリデーション
組み込みのバリデーション関数:required、email、url、numeric、minLength、maxLength、min、max、pattern、matches、equalTo、lessThan、greaterThan、requiredIf。
フィールド間のバリデーションでは、引数に $state 式を使用します。
import { check } from "@json-render/core";
check.required("Field is required");
check.matches("/form/password", "Passwords must match");
check.lessThan("/form/endDate", "Must be before end date");
check.greaterThan("/form/startDate", "Must be after start date");
check.requiredIf("/form/enableNotifications", "Required when enabled");
ユーザープロンプトビルダー
仕様の任意の調整や状態コンテキストを含む、構造化されたユーザープロンプトを作成します。
import { buildUserPrompt } from "@json-render/core";
// Fresh generation
buildUserPrompt({ prompt: "create a todo app" });
// Refinement (patch-only mode)
buildUserPrompt({ prompt: "add a toggle", currentSpec: spec });
// With runtime state
buildUserPrompt({ prompt: "show data", state: { todos: [] } });
仕様のバリデーション
仕様の構造を検証し、よくある問題を自動修正します。
import { validateSpec, autoFixSpec } from "@json-render/core";
const { valid, issues } = validateSpec(spec);
const fixed = autoFixSpec(spec);
表示条件
状態に基づく条件で要素の表示を制御します。VisibilityContext は { stateModel: StateModel } です。
import { visibility } from "@json-render/core";
// Syntax
{ "$state": "/path" } // truthiness
{ "$state": "/path", "not": true } // falsy
{ "$state": "/path", "eq": value } // equality
[ cond1, cond2 ] // implicit AND
// Helpers
visibility.when("/path") // { $state: "/path" }
visibility.unless("/path") // { $state: "/path", not: true }
visibility.eq("/path", val) // { $state: "/path", eq: val }
visibility.and(cond1, cond2) // { $and: [cond1, cond2] }
visibility.or(cond1, cond2) // { $or: [cond1, cond2] }
visibility.always // true
visibility.never // false
スキーマの組み込みアクション
スキーマでは builtInActions を宣言できます。これは実行時に常に利用可能で、プロンプトに自動挿入されるアクションです。
const schema = defineSchema(builder, {
builtInActions: [
{ name: "setState", description: "Update a value in the state model" },
],
});
これらはプロンプトに [built-in] として表示され、defineRegistry でハンドラーを定義する必要はありません。
StateStore
StateStore インターフェイスを使うと、外部の状態管理ライブラリ(Redux、Zustand、XState など)を json-render レンダラーに接続できます。createStateStore ファクトリーは、シンプルなメモリ内実装を作成します。
import { createStateStore, type StateStore } from "@json-render/core";
const store = createStateStore({ count: 0 });
store.get("/count"); // 0
store.set("/count", 1); // updates and notifies subscribers
store.update({ "/a": 1, "/b": 2 }); // batch update
store.subscribe(() => {
console.log(store.getSnapshot()); // { count: 1 }
});
StateStore インターフェイス:get(path)、set(path, value)、update(updates)、getSnapshot()、subscribe(listener)。
主なエクスポート
| エクスポート | 用途 |
|---|---|
defineSchema | 新しいスキーマを作成します |
defineCatalog | スキーマからカタログを作成します |
createStateStore | フレームワークに依存しない、メモリ内の StateStore を作成します |
resolvePropValue | データに基づいて単一のプロパティ式を解決します |
resolveElementProps | 要素内のすべてのプロパティ式を解決します |
buildUserPrompt | 改良内容と状態コンテキストを含むユーザープロンプトを作成します |
validateSpec | 仕様の構造を検証します |
autoFixSpec | よくある仕様の問題を自動修正します |
createSpecStreamCompiler | JSONL パッチを仕様にストリーミングします |
createJsonRenderTransform | 混在ストリーム内のテキストと JSONL を分離する TransformStream を作成します |
parseSpecStreamLine | 単一の JSONL 行を解析します |
applySpecStreamPatch | オブジェクトにパッチを適用します |
StateStore | 外部の状態管理を組み込むためのインターフェースです |
ComputedFunction | $computed 式の関数シグネチャです |
check | 検証チェックを作成するための TypeScript ヘルパーです |
BuiltInAction | 組み込みアクション定義の型です(name + description) |
ActionBinding | アクションバインディングの型です(preventDefault フィールドを含みます) |