Blank white background with no objects or features visible.

TrueFoundryはSeldon AIの買収を発表し、エンタープライズAI向けコントロールプレーンを拡張します。プレスリリース全文はこちら→

Reactにおけるスキーマ駆動型フォーム:TrueFoundry FormBuilderによる構築

TrueFoundryを使ってサービスをデプロイしたり、クラスターを作成したり、LLMモデルを設定したり、シークレットを管理したことがあるなら、通常のUIのように見えるフォームを操作したことがあるでしょう。しかし、それらは一般的なウェブフォームとは全く異なる方法で構築されています。

⚡ TL;DR

TrueFoundry’s FormBuilder is a schema-driven form system that uses structured JSON to automatically render dynamic React inputs, groups, and validation logic. This architecture ensures consistent behavior across complex resource configurations, simplifies nested state management using react-hook-form, and allows for rapid development of domain-specific UIs. TrueFoundry does not hand-code every field on every screen. Instead, it uses a schema-driven form system called FormBuilder. A form is defined as structured JSON (the schema). The UI reads that schema and renders the right inputs, groups, validations, and conditional fields automatically.

This post explains how that works, in four parts:
  • What a form schema looks like
  • How fields are mapped to UI components and rendered
  • How form state is managed
  • How validation works

TrueFoundryがスキーマ駆動型フォームを使用する理由

TrueFoundryのフォームは、多くの場合マニフェスト(CLI(tfy apply -f ...)でも適用できるYAML/JSONオブジェクト)を表します。同じオブジェクトがUIで編集されたり、YAMLとしてダウンロードされたり、APIに送信されたりする可能性があります。

スキーマ駆動型のアプローチは、TrueFoundryに以下のものをもたらします。

  • フォーム構造の唯一の信頼できる情報源(リソースタイプごとにバックエンドからロードされます)。
  • デプロイ、クラスター、ポリシー、モデル、シークレット、設定フォーム、またはプラットフォーム内のその他のあらゆるフォームにおいて一貫した動作。
  • 画面ごとにフォームロジックを書き直すことなく、ネストされた条件付きフィールド。
  • 共有ランタイムにプラグインされるドメイン固有のウィジェット(クラスターピッカー、シークレットセレクター、リソース制限など)。

メンタルモデル:スキーマはデータの形状と編集方法を記述し、FormBuilderはその記述を機能するフォームに変換します。

1. フォームスキーマ:

フォームスキーマはフィールド定義の配列です。各フィールドは、いくつかの重要なプロパティを持つオブジェクトです。

Property Purpose
jsonKey Where this field lives in the submitted object (supports nesting, e.g. image.build_source.type).
label What the user sees.
uiType Which UI component to render (text input, select, group, custom widget, etc.).
sort Display order.
validate Required, min/max, pattern, defaults, custom validators.
conditions Show/hide or enable/disable based on other fields.
subParameters Child fields for groups and repeated sections.
uiProps Extra options passed to the component (search, table view, etc.).

ここに簡略化された一般的な例を示します(実際のTrueFoundryスキーマではありませんが、製品が設定についてどのように考えているかに近いものです):

[
  {
    "sort": 1,
    "jsonKey": "name",
    "label": "Service Name",
    "uiType": "Input",
    "validate": { "required": true, "pattern": "^[a-z0-9-]+$" }
  },
  {
    "sort": 2,
    "jsonKey": "image",
    "label": "Image",
    "uiType": "Group",
    "subParameters": [
      {
        "jsonKey": "type",
        "label": "Source",
        "uiType": "Radio",
        "validate": {
          "required": true,
          "defaultValue": "build",
          "options": [
            { "label": "Build", "value": "build" },
            { "label": "Existing image", "value": "existing" }
          ]
        }
      },
      {
        "jsonKey": "uri",
        "label": "Image URI",
        "uiType": "Input",
        "conditions": [
 		{ "jsonKey": "image.type", "op": "==", "value": "existing"  }
  ],
        "validate": { "required": true }
      }
    ]
  }
]

送信時のマニフェスト/設定:

{
  "name": "my-service",
  "image": { "type": "existing", "uri": "registry.io/app:v1" }
}

2. コンポーネントのマッピングとフィールドのレンダリング方法

レンダリングは小さなパイプラインで行われます。その流れは次のとおりです。

FormBuilderはスキーマツリーを走査し、uiTypeに基づいてノードごとにReactコンポーネントを選択します。

コンポーネントの種類:

  • 基本:入力、選択、ラジオ、スイッチ、数値
  • 構造的:グループ(セクション)、構造体(繰り返し可能なリスト)、KV / ENV(キーバリュー)
  • ドメイン固有:ClusterSelect、SecretSelect、Resources、ModelSelect、PermissionsMatrix、MCPフィールドなど

条件: image.type が "existing" でない場合、URIフィールドはマウントされません。shouldUnregister: true の場合、フォームの状態からも削除されるため、隠された値がペイロードに漏れることはありません。

コード内のマッピングロジック:

// FormComponentMap
const ComponentType = FormComponents[schema.uiType]
const CustomComp = CustomComponentsMap?.[schema.uiType]

if (!enabledByCondition) return null

return CustomComp
  ? <CustomComp schema={schema} />
  : <ComponentType schema={schema} />

3. フォームの状態の処理方法

FormBuilder は状態管理エンジンとして react-hook-form を使用しています。この選択は、製品の動作に影響を与えます。

初期化/コンポーネントの使用 - 作成と編集:

<FormBuilder
  schema={schema}
  defaultValues={existingManifest}   // edit: pre-fill; create: empty/template
  onSubmit={(manifest) => createOrUpdate({ manifest })}
/>

フォームの設定:

const methods = useForm({
  mode: 'onChange',          // validate as user types
  defaultValues,
  shouldUnregister: true,    // hidden fields drop out of state
})

フィールドの登録 - 各入力はそれぞれのパスにバインドされます:

// Inside a text field component
const { register } = useFormContext()

<input
  {...register(schema.jsonKey, registerProps)}
  defaultValue={defaultValue}
/>

追加のコンテキスト - 特定のフォームは、フィールド値とは別にランタイムデータを渡します:

<FormBuilder
  schema={schema}
  extraContext={{
    workspace,
    cluster,
    serviceAccountOptions,  // dynamic dropdown options
    dataTestPrefix: 'create-cluster',
  }}
/>

単一のオブジェクト、ネストされたパス:

すべてのフィールド値は単一のフォームオブジェクト内に存在します。各フィールドは、その完全な jsonKey パスで登録されます:

  • name → トップレベルの文字列
  • image.type → ネストされた値
  • ports.0.container_port → 配列の最初の項目

フィールドを編集すると、この共有オブジェクトが変更されます。送信時、FormBuilder はオブジェクト全体を読み取り、フォームのハンドラーに渡します(通常、TrueFoundry API を呼び出すか、YAML を生成します)。

デフォルトと編集モード:

何かを作成するためにフォームを開く際、defaultValues は空であるか、テンプレートから取得される場合があります。

編集時には、defaultValuesは通常、既存のマニフェストとなります。フォームの各フィールドにはそのオブジェクトから値が事前入力されます。一部のフィールドは編集モードで変更不可(例:リソース名)とマークされており、読み取り専用として表示されます。

非表示フィールドはステートから削除されます。

TrueFoundryのフォームではshouldUnregister: trueが使用されます。これは次のことを意味します。

  • フィールドが条件によって非表示になった場合、フォームステートから登録解除されます。
  • その値は送信されるペイロードに含まれません。

これは条件付きフォームにとって重要です。ユーザーが実際に見て編集できたものだけが送信されます。

4. バリデーションの仕組み

TrueFoundryフォームでのバリデーションは、2つのレイヤーで行われます。

レイヤー1:スキーマバリデーション(宣言的)

各フィールドのvalidateブロックでは、以下を指定できます。

  • 必須
  • min / max(整数値の許容範囲)
  • minLength / maxLength(文字列または配列の長さ)
  • pattern(正規表現、カスタムメッセージ付き)
  • defaultValue
  • immutable(編集モードで読み取り専用)

これらのルールはreact-hook-formのバリデーションルールに変換されます。エラーはフィールドの横にインラインで表示されます。バリデーションは変更時(mode: 'onChange')に実行されるため、ユーザーは送信時だけでなく、入力中にもフィードバックを得られます。

レイヤー2:カスタムおよび非同期バリデーション

スキーマにはカスタムのvalidate関数をアタッチすることもでき、これは一般的に以下のような用途で使用されます。

  • 名前のユニーク性(「この名前のエンティティは既に存在します」など)
  • 送信前のAPI連携チェック
  • カスタムコンポーネント内の複数フィールド間ルール
  • 画面は、「フィールド名にバリデーションをアタッチ」のようなヘルパーを使って、これらをランタイムで適用します。非同期バリデーション(例:デバウンスされた名前チェック)が実行されている間、UIにはスピナーが表示されます。
useAttachValidation(schema, {
  name: async (name) => {
    const taken = await checkNameExists(name)
    return taken ? 'Name already exists' : true
  },
})

まとめ:ユーザー体験

「クラスターの作成」、「サービスのデプロイ」、「モデルの追加」、または「シークレットの管理」を開くと:

  • TrueFoundryは、そのリソースのスキーマをロード(または構築)します
  • FormBuilderは、各スキーマノードを目的の入力コンポーネントとしてレンダリングします
  • あなたの編集は、単一のネストされたフォームオブジェクトを更新します
  • バリデーションは継続的に実行され、送信時にも再度実行されます
  • 最終的なオブジェクトはマニフェストであり、YAMLやCLIで使用するのと同じ形式です

このため、TrueFoundryは、すべての画面が使い捨てのフォームになることなく、非常に複雑な設定UIをサポートできます。複雑さはスキーマとフィールドコンポーネントのライブラリにあり、これらは1つの共有ランタイムによって統合的に管理されます。

The fastest way to build, govern and scale your AI

Sign Up
Table of Contents

One Gateway for Every LLM, Agent and MCP Server

Book a 30-min with our AI expert

Book a Demo

The fastest way to build, govern and scale your AI

Book Demo
Summarize with
ChatGPT logo by OpenAI
Perplexity AI logo
Blurry red snowflake on white background, symmetrical frosty design with soft edges and abstract shape.

Discover More

No items found.
OpenRouter vs AI Gateway
July 4, 2026
|
5 min read

OpenRouter 対 AIゲートウェイ:どちらがあなたに最適ですか?

comparison
July 4, 2026
|
5 min read

プロンプトエンジニアリング:LLMとの対話方法を学ぶ

Thought Leadership
LLMs & GenAI
July 4, 2026
|
5 min read

True ML Talks #12 - Llama-Index共同創設者

True ML Talks
July 4, 2026
|
5 min read

AIワークロードがクラウド料金を膨らませていませんか?

Thought Leadership
No items found.

Recent Blogs

Black left pointing arrow symbol on white background, directional indicator.
Black left pointing arrow symbol on white background, directional indicator.

Frequently asked questions

Why choose a schema-driven approach over hand-coding forms?

Schema-driven forms provide a single source of truth for your configuration manifests. They ensure consistent UI behavior, support nested/conditional logic without repeated code, and allow the backend to drive the form structure dynamically.

How does validation work in FormBuilder?

Validation happens in two layers: Declarative schema validation (using rules like required, pattern, or min/max) and Custom/Async validation for API-backed checks, such as verifying unique resource names.

Can I integrate this with existing React libraries?

Yes. TrueFoundry's FormBuilder uses react-hook-form as its core state engine, making it compatible with standard React patterns and easy to extend with custom components.

Take a quick product tour
Start Product Tour
Product Tour