platform-widget-generate について
コンポーネント名とデータ形状から Salesforce WidgetBundle を作成するスキルです。UEM レイアウト、JSON Schema、登録メタデータを生成し、組織のアクションで UI ブロックとスキーマを調べます。
主な機能
- 01UEM ウィジェットツリーの作成
- 02ウィジェット JSON Schema の生成
- 03.uiwidget-meta.xml 登録ファイルの作成
- 04利用可能な UI コンポーネントの検索
- 05選択したブロックのスキーマ取得
- 06データバインドとアクション設定
活用シーン
- 01カード形式のリッチ UI ウィジェット作成
- 02オブジェクトやリストの項目表示
- 03条件付き・計算コンテンツの追加
MCP 対応
H360 MCP の dispatch ツールで Salesforce の呼び出し可能なアクションを実行し、UI コンポーネントの検索とスキーマ取得を行います。代替手段として sf API リクエストも記載されています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill platform-widget-generateインストール後、Claude Code で/platform-widget-generateを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/conditional.jsonformulas.jsonlist-with-foreach.jsonlocalized-labels.jsonsingle-object.jsonreferences/schema-from-lightning-type.mdwidget-actions.mdwidget-bundle-layout.mdwidget-bundle-validation.mdwidget-formulas.mdwidget-gotchas.mdwidget-labels.mdwidget-meta-directives.mdwidget-styling.md詳細
WidgetBundle の生成
完全な WidgetBundle を作成します。UEM ツリー(tile/widget)、ウィジェットの入力契約を記述する JSON Schema、およびバンドルを登録する .uiwidget-meta.xml が必要です。
このスキルを使用する場合
ユーザーがウィジェット、モザイク、フラグメント、またはカード形式のリッチ UI サーフェスを求めた場合に使用します。カスタム LWC レンダラーや、Custom Lightning Type バンドル内の renderer.json ファイルには使用しないでください。これらには platform-custom-lightning-type-generate を使用します。
入力
widgetName(必須)—camelCaseの識別子です。uiWidgets/配下のディレクトリ名になります。- シェイプ — ウィジェットがレンダリングするデータです。シェイプがない場合、ウィジェットは生成できません。シェイプは優先順位に従って、次のいずれかの方法で指定されます。
lightningTypeSchema— 既存の Apex ベースの Lightning Type を表す{ path, apexClassFqn }です。FQN には次のいずれかの形式を使用します。外部クラス(<namespace>__<ClassName>)では外部クラスがペイロードになり、内部クラス(<namespace>__<ClassName>$<InnerClass>)では指定された内部クラスがペイロードになります。platform-lightning-type-widget-coordinateオーケストレーターから渡されます。指定されている場合は、references/schema-from-lightning-type.mdに従って導出します。- ユーザーのプロンプトから抽出 —
lightningTypeSchemaが渡されていない場合は、ユーザーが記述した内容(貼り付けられた JSON ペイロード、列挙されたフィールド一覧(「文字列の id、数値の total」など)、または説明文)からシェイプを直接推測します。どちらの場合も、出力は順序付けられた{ name, type, required }のリストです。
どちらの方法でもシェイプを特定できない場合は、作業を中断して、先にユーザーに確認してください。
出力
<pkgDir>/uiWidgets/<widgetName>/ に次の 3 つのファイルを作成します。
| ファイル | 内容 |
|---|---|
<widgetName>.json | ウィジェットのエンベロープ — { "type": "lightning__agentforceWidget", "contentBody": { "widgetBody": { UEM tree rooted at tile/widget } } } |
schema.json | JSON Schema — ルートに type: "object" と、lightning:type: "lightning__objectType" およびフィールドの properties を持つ properties.attributes ラッパーを含みます |
<widgetName>.uiwidget-meta.xml | <masterLabel>、<description>、および <widgetType>JSON</widgetType> を含む <UiWidgetBundle> 要素 |
<pkgDir> の解決手順と、<widgetName>.uiwidget-meta.xml の正確な形式については、references/widget-bundle-layout.md を参照してください。
構成
ウィジェット本体は、contentBody.widgetBody の下にネストされたブロックで構成される UEM ツリーです。ルートノードは tile/widget です。ルートとそれ以外のすべてのノードは同じ形状で、type キーはありません。definition、任意の attributes、任意の meta、および任意の children のみで構成されます。ブロックの形状:
interface Block {
definition: string // {namespace}/{blockName} — root is "tile/widget"
attributes?: Record<string, any>
meta?: { // see references/widget-meta-directives.md
forEach?: string
forItem?: string
if?: string
}
children?: Block[]
}
tile/widget.children の最初の子には、単一の tile/column を指定することを推奨します(SHOULD)。すべてのウィジェットコンテンツは通常、この最初の子の中に配置し、各サーフェスで予測可能な縦方向の構造にします。
使用可能な Invocable Action
どちらも対象組織で使用できる標準の Invocable Action です。
呼び出し規約
利用可能な方法で各アクションを実行します。H360 MCP の dispatch ツール(リクエストボディを指定してエンドポイントパスに POST)または sf api request rest を使用します。v{version} には、このスキルの minApiVersion を使用します。curl は使用せず、組織のアクセストークンを取り出さないでください。
sf api request rest '/services/data/v{version}/actions/standard/<actionName>' --method POST --body '<request body>' --target-org <org>
レスポンスの処理
各レスポンスは 1 つのエンベロープを含む配列です(dispatch では body の下にネストされます)。次の 3 つの失敗レイヤーを順に確認します。
| レイヤー | シグナル | 対応 |
|---|---|---|
| トランスポート/認証 | dispatch の status_code が 200 以外、または CLI がゼロ以外で終了 | エラーを提示します |
| アクション | [0].isSuccess が false、または [0].errors が空でない | errors[].message を提示します |
エントリー単位(getUiComponentSchemas のみ) | [0].isSuccess が true でも、いずれかの componentSchemas[].success が false | そのブロックを利用不可として扱います |
成功した場合は、[0].outputValues を読み取ります。
discoverUiComponents
目的: 作成に使用できるブロックの一覧を確認します。
エンドポイント: POST /services/data/v{version}/actions/standard/discoverUiComponents
リクエスト本文: {"inputs":[{"pageType":"FRAGMENT"}]}
戻り値: outputValues.componentDefinitions[] — { definition, description, label } のリストです。
getUiComponentSchemas
目的: 選択したブロックのスキーマ(プロパティの型、必須か任意か、検証ルール)を取得します。
エンドポイント: POST /services/data/v{version}/actions/standard/getUiComponentSchemas
リクエスト本文: {"inputs":[{"pageType":"FRAGMENT","componentDefinitions":["namespace/definition", ...]}]}
戻り値: outputValues.componentSchemas[] — { definition, success, schema } のリストです(schema は YAML 文字列です)。一部の取得に失敗しても処理できます。
getUiComponentSchemasにtile/widgetを渡さないでください。これは固定ラッパーであり、クエリ可能なコンポーネントではありません。
属性バインディング
{!$attrs.<attrName>}を使用して、ブロックのプロパティを実行時データにバインドします。<attrName>はschema.jsonのプロパティ名と一致している必要があります。forEach内では、代わりにループ変数を参照します。例:"text": "{!$item.name}"。references/widget-meta-directives.mdを参照してください。- バインディングには、フィールド参照だけでなく数式式も使用できます。サポートされる関数の一覧、構文、注意点については
references/widget-formulas.mdを参照してください。 - ローカライズ: ユーザーがローカライズまたは翻訳されたテキストを求めた場合(または Custom Labels /
$Labelを指定した場合)に限り、静的なユーザー向け文字列を Custom Label 参照({!$Label.c.<LabelName>})として記述します。references/widget-labels.mdを参照してください。
アクション
tile/button は、イベント発生時にアクションノードをディスパッチする actions 属性をサポートしています。次の 2 種類のアクション定義を使用できます。
| アクション | タイミング | 必須属性 | 効果 |
|---|---|---|---|
action/openLink | 同期 | url(文字列)。target は任意(_blank|_self、デフォルトは _blank) | URL を開きます |
action/sendMessage | 非同期 | content(文字列) | 新しいユーザーメッセージをエージェントに送信し、新たなターンを開始します |
sendMessage ボタンと openLink ボタンの完全な JSON については、references/widget-actions.md を参照してください。
**actions 属性のない tile/button は無効状態で表示されます。**ボタンはアクションを実行するためのものなので、操作可能なボタンには必ず click アクションを設定してください。
レイアウトのベストプラクティス
次の規則は、ウィジェットの構造、つまりブロックのグループ化や積み重ね方に関するものです。
| プリミティブ | 目的 | 使用する場面 |
|---|---|---|
tile/column | 子要素を縦に積み重ねます | ルートラッパー、およびブロックを積み重ねるグループ |
tile/row | 子要素を横に並べます | 同じ行に配置する 2 つ以上のブロック |
tile/spacer | ブロック間の余白 | コンテンツグループ間に余分なスペースが必要な場合 |
- ネスト: フラットなレイアウトを優先します。サブグループで実際に視覚的な向きが変わる場合に限り、
tile/rowの中にtile/columnを(またはその逆を)ネストします。 - 正確なパレット: 上の表には、一般的なレイアウト用プリミティブが記載されています。
discoverUiComponentsの出力を確認してブロックの存在を必ず確かめてください。検出結果に表示されていないブロック名を、この表だけを根拠に使用しないでください。
スタイリングのベストプラクティス
セマンティックなスタイル(具体的な色やピクセル値ではなくバリエーション)を使用し、グループごとに主要ボタンを 1 つ、ウィジェットごとに h1 を 1 つだけ配置し、アイコンは Lucide のみを使用します。バリエーション、サイズ、アイコンを割り当てる前に references/widget-styling.md を読んでください。
ワークフロー
-
ウィジェット仕様を解決する —
{ name, type, required }の順序付きリストです。入力に応じて参照元が異なります(Inputs を参照)。- オーケストレーターから
lightningTypeSchemaが渡された場合 →references/schema-from-lightning-type.mdに従って導出します。 - それ以外の場合 → ユーザープロンプト(貼り付けられた JSON ペイロード、列挙されたフィールド一覧、または説明文)からリストを直接推定します。
- オーケストレーターから
-
ブロックを検出します(必須 — 省略しないでください)。
discoverUiComponents呼び出し可能アクション(利用可能な呼び出し可能アクションを参照)を呼び出し、ウィジェット仕様のプロパティ型を、返されたlabel/descriptionの値と照合します。isSuccessがfalse、errorsが空でない、またはcomponentDefinitionsが空の場合は、処理を停止し、エラーをそのまま提示してください。記憶、過去の実行、トレーニングデータからブロック名を推測してはいけません。 -
ブロックを選択します。 ウィジェット仕様のプロパティごとにブロックを1つ選択し、レイアウトのベストプラクティスに記載されている構造プリミティブも選択します。
-
ブロックのスキーマを取得します(必須 — 省略しないでください)。 選択したブロックについて、
getUiComponentSchemas呼び出し可能アクションを呼び出します。各プロパティのdefaultを含め、プロパティのメタデータを確認します。値がデフォルトと同じになる属性は省略してください(references/widget-styling.mdを参照)。isSuccessがfalse、componentSchemasが空、またはいずれかのエントリのsuccess: falseの場合は、そのブロックを使用せず、手順2の結果から別のブロックを選び直してください。使用できるブロックがない場合は、処理を停止してエラーを提示してください。プロジェクト内の既存のウィジェットから推測してはいけません。 -
UEM ツリーを構築します(例の読み込みは必須 — 省略しないでください)。 まず、ウィジェット仕様に該当するパターンを特定し、このスキルの
examples/ディレクトリ(<skill-root>/examples/)から該当する例のファイルをそれぞれ読み込みます。仕様内のパターン 読み込む例 単一オブジェクト(反復なし) <skill-root>/examples/single-object.jsonリストの反復(ルートレベルの配列、ネストされたリスト、または単一オブジェクトのウィジェット内に埋め込まれたリスト) <skill-root>/examples/list-with-foreach.json条件付きレンダリング(ブール値または数式にバインドされた if)<skill-root>/examples/conditional.json計算値、テキスト/数値の変換、ロケール形式の数値/通貨/日付、または数式によって制御される if(単純なブール値フィールドではない)<skill-root>/examples/formulas.jsonユーザーがローカライズ/翻訳されたテキスト(カスタムラベル)を求めている <skill-root>/examples/localized-labels.json仕様が複数のパターンに該当する場合もあります(たとえば、一部の項目を条件付きでレンダリングするリストでは、
list-with-foreach.jsonとconditional.jsonの両方を読み込みます)。該当する例をすべて読み込み、該当するものだけを読み込んでください。パターンに見覚えがあるという理由で読み込みを省略してはいけません。**数式を記述する前に、
references/widget-formulas.mdを最後まで読んでください。**ここにはサポートされている演算子と関数がすべて記載されています。ここに記載されていない関数名や演算子を推測してはいけません。$Label参照を記述する前に、references/widget-labels.mdを最後まで読んでください。次に、以下を行います。
- ウィジェット仕様の各プロパティをブロックのプロパティに対応付けます。仕様の順序を維持してください。
- ルートの反復方法を決定します。 単一オブジェクトの場合は、プロパティをルートの
tile/columnの直下に配置します。コレクションの場合は、反復するブロックをforEach/forItemで囲みます。references/widget-meta-directives.mdを参照してください。 - 値を
{!$attrs.X}(forEach内では{!$item.X})でバインドします。 - 条件付きブロックでは、
metaに"if"を追加します。バインド先は、lightning__booleanTypeプロパティ、またはブール値を返す数式のいずれかです。references/widget-formulas.mdを参照してください。 - ウィジェット仕様で生のフィールドではなく計算値(合計値、派生ラベル、書式設定された文字列など)が求められる場合は、
references/widget-formulas.mdに従って{!...}内の数式として表現します。既存のプロパティから計算できる値を保持するために、新しいスキーマプロパティを作ってはいけません。
-
schema.jsonを作成します。 ウィジェット仕様から JSON Schema を構築します。フィールドはattributesラッパーの直下、1階層に配置します。{ "title": "<Widget Display Name>", "description": "<one line about what the widget shows>", "type": "object", "properties": { "attributes": { "lightning:type": "lightning__objectType", "properties": { "<propertyName>": { "title": "<label>", "description": "<short description>", "lightning:type": "<lightning__textType | lightning__numberType | ...>" } } } } }ルートで必須のキー:
title、type: "object"、properties.attributes(lightning:type: "lightning__objectType"と、その中にネストされたpropertiesマップを含む)。プリミティブ型の詳しいガイダンスは、references/schema-from-lightning-type.mdを参照してください。 -
<widgetName>.uiwidget-meta.xmlを作成します。 正確な形式は、references/widget-bundle-layout.mdを参照してください。 -
<pkgDir>を解決し、バンドルを書き込みます。references/widget-bundle-layout.md(## Resolving <pkgDir>)の手順に従ってください。ウィジェットバンドルは3つのファイルで構成されます。3つすべてを同じ手順内で書き込む必要があります。3つ未満のファイルで構成されたバンドルは不完全なため、デプロイされません。<pkgDir>/uiWidgets/<widgetName>/<widgetName>.json # widget envelope — UEM tree (primary artifact) <pkgDir>/uiWidgets/<widgetName>/schema.json # attribute contract for the envelope <pkgDir>/uiWidgets/<widgetName>/<widgetName>.uiwidget-meta.xml # UiWidgetBundle registration各ファイルにはそれぞれ異なる役割があります。
<widgetName>.json—tile/widgetUEM ツリーを含むウィジェットエンベロープです。これが主要な成果物です。schema.jsonはその付随するコントラクトであり、代替にはなりません。schema.json— エンベロープ内の{!$attrs.X}バインディングが参照する属性のJSON Schemaです。<widgetName>.uiwidget-meta.xml— ソース追跡とデプロイ用にバンドルを登録するUiWidgetBundle要素です。
自己検証に進む前に、3つすべてを書き込んでください。
-
自己検証します。 結果を報告する前にチェックを実行し、それぞれの結果を個別に(
passまたはfail (<reason>))報告してください。「すべて合格」のような1行の要約にはしないでください。レビュー担当者が見落とされたチェックを確認できるよう、すべてのチェックを列挙してください。references/widget-bundle-validation.mdに記載されたすべてのチェックを実行してください。 -
ラベルを報告します。 ウィジェットで
$Labelを使用している場合は、references/widget-labels.mdに記載されたラベルレポートで応答を締めくくってください。
ルール/制約
| 制約 | 理由 |
|---|---|
ブロック定義は{namespace}/{blockName}の形式に従い、discoverUiComponentsの出力と一致する必要があります | ランタイムは正確に一致する定義文字列でブロックを解決します |
tile/widgetをgetUiComponentSchemasに渡してはいけません | これは固定のラッパーであり、クエリ可能なコンポーネントではありません |
references/とexamples/のファイルは、それらを指定する手順でのみ読み込んでください | 先に読み込むとコンテキストを浪費し、必要なファイルを決めるディスカバリー結果が得られる前に読み込むことになります |
本文中のすべての{!$attrs.X}は、ウィジェットのschema.json内のプロパティに解決される必要があります | 存在しないフィールドを作らないでください |
すべてのtile/buttonには、action/openLinkまたはaction/sendMessageのみを使ったactions.clickエントリが必要です | サポートされているタイルアクション定義はこの2つだけです。アクションのないボタンは無効状態で表示されます |
Bash ツールの呼び出しでは、$(…)、バッククォート、<(…)、ブレース展開{a,b,c}、eval/execを使用してはいけません | これらのパターンは、Bypass モードでも Vibes のセーフシェルフィルターによって手動承認が必要になります。コマンドを個別に出力する(mkdir -p a && mkdir -p b)か、それぞれの値を個別のコマンドで出力して、その結果を確認してください。シェル変数に格納してはいけません |
注意点
既知の失敗例と修正方法(不完全なスキーマ、未解決のバインディング、誤った出力パス、ifの真偽値、機能しないボタン、アクションの選択)については、references/widget-gotchas.mdを参照してください。
リファレンスファイル一覧
| ファイル | 読むタイミング |
|---|---|
references/widget-meta-directives.md | forEach / forItem(反復処理)と if(条件付きレンダリング)について。ネストしたループも含みます |
references/schema-from-lightning-type.md | lightningTypeSchema が指定されている場合。Apex に基づく Lightning Type からウィジェットの schema.json を導出する方法 |
references/widget-bundle-layout.md | フォルダー構成、-meta.xml の形式、<pkgDir> の解決規則 |
references/widget-bundle-validation.md | ステップ 9 — 報告前に実行するチェック |
references/widget-formulas.md | サポート対象の数式関数と演算子。ロケール形式関数(FORMATNUMBER、FORMATCURRENCY、FORMATDATE など)も含みます |
references/widget-labels.md | ローカライズ — $Label の構文、命名と再利用、使用可能な属性、データとの組み合わせ、ラベルの作成、ラベルレポート |
references/widget-actions.md | action/sendMessage と action/openLink の完全な tile/button JSON |
references/widget-styling.md | バリアント、サイズ、見出し、アイコンの規則 |
references/widget-gotchas.md | 既知の失敗パターンとその修正方法 |
examples/single-object.json | 単一オブジェクトのパターン({!$attrs.X} によるルートバインディング、反復処理なし) |
examples/list-with-foreach.json | リストの反復処理を行うすべてのケース — ルートレベルのコレクション、ネストしたリスト、単一オブジェクトのウィジェット内に埋め込まれたリスト(例:外側の Apex ペイロード内にある List<InnerClass> の反復処理) |
examples/conditional.json | 条件付きパターン(meta の if。if と forEach の併用も含みます) |
examples/formulas.json | 数式の使用方法 — テキスト/算術/日付の変換、ロケール形式関数、tile/text と meta.if の両方を制御する IF/AND/NOT |
examples/localized-labels.json | ローカライズ — 見出し、キャプション、バッジ(ラベルを選択する IF)、ボタンラベル、データと結合したラベルでの $Label の使用 |