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

Built for Speed: ~10ms Latency, Even Under Load
Blazingly fast way to build, track and deploy your models!
- Handles 350+ RPS on just 1 vCPU — no tuning needed
- Production-ready with full enterprise support
TrueFoundryを使ってサービスをデプロイしたり、クラスターを作成したり、LLMモデルを設定したり、シークレットを管理したことがあるなら、通常のUIのように見えるフォームを操作したことがあるでしょう。しかし、それらは一般的なウェブフォームとは全く異なる方法で構築されています。
TrueFoundryがスキーマ駆動型フォームを使用する理由
TrueFoundryのフォームは、多くの場合マニフェスト(CLI(tfy apply -f ...)でも適用できるYAML/JSONオブジェクト)を表します。同じオブジェクトがUIで編集されたり、YAMLとしてダウンロードされたり、APIに送信されたりする可能性があります。
スキーマ駆動型のアプローチは、TrueFoundryに以下のものをもたらします。
- フォーム構造の唯一の信頼できる情報源(リソースタイプごとにバックエンドからロードされます)。
- デプロイ、クラスター、ポリシー、モデル、シークレット、設定フォーム、またはプラットフォーム内のその他のあらゆるフォームにおいて一貫した動作。
- 画面ごとにフォームロジックを書き直すことなく、ネストされた条件付きフィールド。
- 共有ランタイムにプラグインされるドメイン固有のウィジェット(クラスターピッカー、シークレットセレクター、リソース制限など)。
メンタルモデル:スキーマはデータの形状と編集方法を記述し、FormBuilderはその記述を機能するフォームに変換します。
1. フォームスキーマ:
フォームスキーマはフィールド定義の配列です。各フィールドは、いくつかの重要なプロパティを持つオブジェクトです。
ここに簡略化された一般的な例を示します(実際の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つの共有ランタイムによって統合的に管理されます。
TrueFoundry AI Gateway delivers ~3–4 ms latency, handles 350+ RPS on 1 vCPU, scales horizontally with ease, and is production-ready, while LiteLLM suffers from high latency, struggles beyond moderate RPS, lacks built-in scaling, and is best for light or prototype workloads.
The fastest way to build, govern and scale your AI


Recent Blogs
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.










.webp)



.png)








.webp)
.webp)



.webp)





