webflow-mcp:interactions について
Webflow MCPを通じてIX3(GSAP)インタラクションを作成・管理するためのスキルです。ライブガイドの確認、書き込み前の計画と承認、結果の検証を重視します。
主な機能
- 01IX3インタラクションの作成・更新・削除
- 02クリック、ホバー、スクロールのトリガー
- 03コンポーネントとバリアントのスコープ
- 04書き込み前のページとスタイル対象の解決
- 05インタラクションの検証と拒否理由の調査
活用シーン
- 01ページ要素にクリック時のフェードを追加
- 02スクロール表示や視差効果を作成
- 03コンポーネントのバリアントにインタラクションを設定
- 04既存インタラクションの確認と更新
MCP 対応
Webflow MCPの`data_interactions_tool`でインタラクションを読み書きし、サイト、ページ、スタイルの各ツールで対象を特定します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ webflow/ webflow-skills --skill webflow-mcp:interactionsインストール後、Claude Code で/webflow-mcp:interactionsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/actions-and-properties.mdcapabilities.generated.mdconditional-playback.mdenvelope-and-targets.mdgated-capabilities.mdindex.mdlimits-and-budgets.mdpanel-traps.mdrejects-index.mdtimelines-and-groups.mdtrigger-click.mdtrigger-custom.mdtrigger-hover.mdtrigger-load.mdtrigger-mouse-move.mdtrigger-scroll.mdupdating-interactions.md詳細
インタラクション
Webflow MCP を通じて、IX3 インタラクション(GSAP アニメーション)を作成および編集します。
重要な注意事項
すべての操作で、必ず Webflow MCP ツールを使用してください。
- 他のツールを呼び出す前に、Webflow MCP の
webflow_guide_toolを使用してベストプラクティスを確認してください。短い Interactions セクションにはdata_interactions_toolの名前が記載されており、書き込みの前にアクションguideを呼び出すよう指示されています。ペイロードの形式は短いセクションではなく、そのguideアクションから取得してください。 - Webflow MCP の
data_sites_toolをアクションlist_sitesで使用して、対象サイトを特定してください。 - Webflow MCP の
data_pages_toolをアクションlist_pagesで使用して、名前またはスラッグから対象ページを探してください。 - Webflow MCP の
data_interactions_toolを、guide/list/get/create/update/delete に使用してください。 - Webflow MCP の
data_style_toolを使用して、wf:classを対象にする前にクラスの style-block id を解決してください。 - Webflow のインタラクションの CRUD には、他のツールや方法を使用しないでください。
- すべてのツール呼び出しに、必須の
contextパラメーター(第三者の視点で15~25語)を含めてください。 - Designer も MCP Bridge も不要です。
data_interactions_toolはdata_element_toolと同様にヘッドレスです。Designer は後から Interactions パネルの確認やプレビューを行う場合にのみ役立ちます。インタラクションの一覧表示や書き込みのために、ユーザーに Bridge アプリを開くよう求めないでください。 - ツール一覧に
data_interactions_toolがなく、セッションにsite/interactions/interactions.ix3.jsonが含まれている場合は、そのファイルを編集してください。それ以外の場合はdata_interactions_toolを使用してください。このスキルでは MCP を使用します。
ツールの構成
- スコープ:
pages:read/pages:write - 複合ツール:
data_interactions_tool - アクション:
guide、list_interactions、get_interaction、create_interaction、update_interaction、delete_interaction siteIdとpageIdは、ツール引数のトップレベルに指定します(ページのコンテキスト/作成時の管理用)。create_interactionの引数内には含めません。guideは最新情報を返します。data_interactions_toolをアクションguideで呼び出すか、webflow://guides/interactionsを読み取ってください。どちらも同じ Markdown を返します。ペイロードの正しい形式を確認するには、こちらを優先してください。このスキルでは、その形式に沿ったワークフローを説明しています。references/には、guide に含まれていない個別の説明があります。create_interactionの引数:name(必須)、scope(任意、既定値は site)、triggers(必須の配列)、timelines(必須の配列)、timelineDefaults(任意)、conditionalPlayback(任意)- コンポーネントおよびバリアントのスコープに対応しています。
{type:"component", componentId, variants?}は create と update で使用できます。variantsにはdata_component_variants_toolのバリアント オプション ID を指定します。省略する場合も[]を渡す場合も、すべてのバリアントが対象になります。libraryProfileIdは設定しないでください。インタラクションがライブラリ所有としてマークされます。存在しないコンポーネント ID またはバリアント ID は拒否されます。references/envelope-and-targets.md を参照してください。
手順
フェーズ 1:調査
- 最初に
webflow_guide_toolを呼び出します — 常に最初の MCP ツール呼び出しにします。一般的な MCP の規約と、短いインタラクションのセクション(data_interactions_tool、そのアクション、トップレベルのsiteIdとpageId)が記載されています。このセクションはペイロードの契約ではありません。有効な形式はdata_interactions_tool→guideから取得してください。 - サイトを取得します:
list_sitesを指定してdata_sites_toolを呼び出します。サイトが 1 つだけなら、そのサイトを使用します。 - ページを取得します:
list_pagesを指定してdata_pages_toolを呼び出します。data_interactions_toolの各呼び出しでトップレベルのpageIdとして使用する、そのページの ID が必要です。 - ツールが登録されていることを確認します:
data_interactions_toolが登録されていない場合は、回避策を試さずに作業を中止し、その旨をユーザーに伝えます。ツールがないことを Bridge セッションがないことと見なさず、Designer や MCP Bridge を開くようユーザーに求めないでください。セッションにsite/interactions/interactions.ix3.jsonが含まれている場合は、代わりにそのファイルを編集してください。 - 空のリストは、サイトにインタラクションがない証拠にはなりません。
data_interactions_toolが読み取るのは IX3 のみです。インタラクションが IX2 のサイトでは、エラーなしで{items: [], total: 0}が返り、インタラクションがないサイトと区別できません。読み取り結果が空でも、サイトにモーションがないと結論づけてはいけません。取得した内容をユーザーに伝え、Interactions パネルの下部にあるバージョンセレクターを確認してもらってください。IX2 のサイトでも作成は成功し、その後、サイトは両方のランタイムを持つことになります。
フェーズ 2:作成する内容の契約を確認する
- 有効なペイロードの形式を確認するには、
data_interactions_tool→guideを呼び出します。 ガイドに記載されていないセットピースが必要な場合は、トリガーに対応するreferences/ファイルも読んでください。下記のリファレンスマップを参照してください。このファイル内の 5 つのインライン例を超える内容を初めて書き込む前に、必ずこれを行ってください。 +=/</>のtiming.position文字列や{reducedMotion:"skip"}を作り出してはいけません。timing.durationに数値をそのまま指定する場合、単位は秒です(400ではなく0.4)。
リファレンスマップ
| ユーザーの質問 | 参照先 |
|---|---|
| クリック | references/trigger-click.md |
| ホバー、マウスの入退場 | references/trigger-hover.md |
| ページ読み込み | references/trigger-load.md |
| スクロール、スクラブ、パララックス | references/trigger-scroll.md |
| マウス移動、カーソル追従 | references/trigger-mouse-move.md |
| カスタム JS イベント | references/trigger-custom.md |
| ナビゲーションバー、ドロップダウン、条件 | references/gated-capabilities.md |
| 変数、Rive、Animate Rive | data_interactions_tool action guide |
| エンベロープ、ID、スコープ、ターゲット、フィルター | references/envelope-and-targets.md |
プロパティ、値、tt、タイミング、splitText | references/actions-and-properties.md |
| ロール、グループ、パーセントキャンバス | references/timelines-and-groups.md |
| モーション低減、ブレークポイント再生 | references/conditional-playback.md |
| 既存のインタラクションの編集 | references/updating-interactions.md |
| サイズと件数の上限 | references/limits-and-budgets.md |
| 書き込みは成功したが、ユーザーが編集できない | references/panel-traps.md |
| 書き込みは成功したが、何もアニメーションしない | references/rejects-index.md → "nothing to decode" |
| 拒否メッセージの解読 | references/rejects-index.md |
| 利用可能なトリガーとプロパティの一覧 | references/capabilities.generated.md |
不明な場合は、references/index.mdから始めてください。適用タグについても説明しています。特に、[PANEL-TRAP]は書き込みが成功しても、ユーザーがDesignerで編集できない状態になることを意味します。また、[LEGACY-OK-ON-UPDATE]は、保存済みの値を「修正」せず、そのまま渡す必要があることを意味します。
フェーズ 3:計画(書き込み前)
- クラスのターゲットを解決します。
data_style_toolのスタイルブロックID配列を優先してください。クラス名文字列も使用できます。query_stylesで、そのクラスがちょうど1つのスタイルブロックに解決されることを確認してください。複数のコンボチェーンの末端として再利用されている名前は複数の結果を返し、それぞれが別の要素をターゲットにします。要素に専用クラスが必要な場合は、適用するparent_style_namesチェーン全体を指定してcreate_styleで作成し、data_element_toolのset_styleで同じチェーンを適用します。スタイルブロックとしてすでに存在しないチェーンは拒否されます - フェーズ2で参照した資料に基づいてペイロードを計画します。オブジェクト形式、有効なトリガーとターゲット、新しいアクションIDを確認してください
- 作成・更新・削除の前に、明示的な確認を求めてください。
- 「このクリック時のフェードを作成しますか?」
- 「このインタラクションを書き込む前に、次の計画を確認してください:[plan]。実行するには確認してください。」
フェーズ 4:書き込み(確認後のみ)
data_interactions_toolのcreate_interactionまたはupdate_interactionupdate_interactionは部分更新です。省略したフィールドはそのまま維持され、指定した値で置き換えられ、nullを指定するとtimelineDefaults/conditionalPlaybackがクリアされます。timelinesを送信すると全体が置き換えられます。
フェーズ 5:検証
- 返された ID を指定して
get_interaction - 作成または更新した内容を報告します
- 拒否された場合: エラーを読み、references/rejects-index.md で内容を確認してから、ペイロードを修正します。GSAP の位置演算子を推測で作成したり、別の結果を期待して同じ形のペイロードを再試行したりしないでください。ここでの拒否はすべて決定論的です。
- 書き込みに成功しても、アニメーションが動作する証拠にはなりません。 有効なペイロードでも保存され、読み戻すとバイト単位で同一なのに、何も起こらない場合があります。たとえば、To トゥイーンの
[from, to]ペア、1 つのコンボチェーンになっていないクラス配列、ターゲットのないマウス移動トリガー、最初のクリックでのcontrol: "reverse"などです。get_interactionでは、これらを検出できません。成功を報告する前に、以下のガイドラインに照らしてペイロードを確認してください。ユーザーから何も起こらないと言われた場合は、インタラクションを書き換えるのではなく、references/rejects-index.md →「デコードするものが何もない場合」から確認してください。
例
STYLE_BLOCK_ID をスタイルブロック ID に置き換えます。操作ごとに新しい一意の id を生成してください。
例 1:クリックでフェード
ユーザー:「クリックでフェードするインタラクションを追加してください」
webflow_guide_toolを呼び出しますlist_sites→list_pages→data_style_toolでSTYLE_BLOCK_IDを特定しますdata_interactions_toolのguideを呼び出してペイロードの形式を確認します。ガイドに必要な一式が載っていない場合に限り、references/trigger-click.md を読みます。- 計画を提示し、確認を待ちます
- 確認後、
create_interactionを実行します。
{
"name": "Click fade",
"triggers": [
{
"extensionKey": "wf:click",
"config": { "control": "play" },
"target": { "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
}
],
"timelines": [
{
"actions": [
{
"id": "act-click-fade",
"name": "Fade",
"tt": 2,
"timing": { "duration": 0.4 },
"properties": { "wf:transform": { "opacity": ["0%", "100%"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
}
]
}
get_interactionで検証します
FromTo は静止時に開始状態を維持するため、この要素は最初のクリックまで opacity: 0 で描画されます。公開ページで確認されています。これがフェードインの動作ですが、要素が見えない状態は動作しているインタラクションではなく、書き込み失敗のように見えるため、ユーザーに伝えてください。クリック前から表示しておく必要がある場合は、静止値がすでに可視状態になっているプロパティ(x オフセットや色など)をアニメーションするか、To を使用してください。
例 2:ページ読み込み時のフェード
ユーザー:「ページの読み込み時にこのセクションをフェードインしてください」
同じ手順で検出し、参照情報を読み、確認を求めます。Load ではトリガーターゲットを省略します。アクションターゲットに wf:trigger-only を指定してはいけません。
{
"name": "Load fade",
"triggers": [{ "extensionKey": "wf:load", "config": { "control": "play" } }],
"timelines": [
{
"actions": [
{
"id": "act-load-fade",
"name": "Fade",
"tt": 2,
"timing": { "duration": 0.4 },
"properties": { "wf:transform": { "opacity": ["0%", "100%"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
}
]
}
例 3:スクロールスクラブ
ユーザー:「ユーザーのスクロールに合わせてフェードをスクラブしてください」
Scroll は単独で使用します。スクラブには数値の scrub(true ではありません)、canvasDuration: 1 を持つロールなしのタイムライン、そしてこのキャンバス全体でトゥイーンが実行されるよう、キャンバスの長さと等しいアクションの timing.duration が必要です。再生時の control / delay / jump / speed は省略します。scrub を省略すると、範囲に達したときに一度だけ再生されます。スクラブにはなりません。
{
"name": "Scroll scrub fade",
"triggers": [
{
"extensionKey": "wf:scroll",
"config": {
"scrollTriggerConfig": {
"start": "top bottom",
"end": "top 10%",
"scrub": 0.3
}
},
"target": { "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
}
],
"timelines": [
{
"canvasDuration": 1,
"actions": [
{
"id": "act-scroll-scrub",
"name": "Fade",
"tt": 2,
"timing": { "duration": 1 },
"properties": {
"wf:transform": { "opacity": ["0%", "100%"], "xPercent": [-40, 0] }
},
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
}
]
}
一度だけ再生するバリエーション(スクラブではなくリビール)。 scrub と canvasDuration を削除し、timing.duration を秒単位に戻し、さらに enter: "play" を送信します。ホストは作成時およびトリガーの置き換え時に、未指定のトグルキーを設定します(enter: "play"、残りの 3 つは "none")。明示的に指定された "none" はそのまま維持されるため、省略したキーは無効なまま残るのではなく補完されます。それでも enter を送信してください。パネルが書き込む値であり、このロールアウトの前後どちらでも正しい値です。
{
"extensionKey": "wf:scroll",
"config": {
"scrollTriggerConfig": {
"start": "top 90%",
"end": "bottom 15%",
"enter": "play",
"leaveBack": "reset"
}
},
"target": { "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
}
leaveBack: "reset" は省略可能で、ユーザーが上にスクロールしたときにリビールを再生します。リビール自体には From(tt: 1)を使い、要素が非表示の状態から始まるようにしてください。
例 4:ホバーの開始/終了
ユーザー:「ホバー開始時にフェードインし、終了時にフェードアウトする」
ロール形式を使用します。multiTimeline: true を指定した wf:hover トリガーを 1 つ使い、triggerMetadata を介して mouseEnter と mouseLeave のタグを付けたタイムラインを 2 つ用意します。ロールはそれぞれこの文字列と完全に一致させ、タイムラインごとに重複しないようにします。これを従来のホバーの type / hover / custom と混在させないでください。
{
"name": "Hover fade",
"triggers": [
{
"extensionKey": "wf:hover",
"config": { "pluginConfig": { "multiTimeline": true } },
"target": { "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
}
],
"timelines": [
{
"triggerMetadata": { "role": "mouseEnter" },
"actions": [
{
"id": "act-hover-in",
"name": "Fade in",
"tt": 2,
"timing": { "duration": 0.3 },
"properties": { "wf:transform": { "opacity": ["0%", "100%"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
},
{
"triggerMetadata": { "role": "mouseLeave" },
"actions": [
{
"id": "act-hover-out",
"name": "Fade out",
"tt": 2,
"timing": { "duration": 0.3 },
"properties": { "wf:transform": { "opacity": ["100%", "0%"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
}
]
}
もう注意書きは必要ありません。 このスキルの以前のバージョンでは、どちらのアクショングループにもパネルに削除ボタンが表示されないと警告していました。記述時点ではそのとおりでしたが、webflow#117817 により 2026-08-19 に修正されました。Hover のオーナーが存在する場合、この形式でも「削除」が表示されるようになりました。その後 Designer で確認したところ、MCP 経由で作成したロール形式のホバーは正しくアニメーションし、分割形式と同様に、両方のアクショングループに削除コントロールが表示されます。
パネルが推奨する 2 トリガーの分割形式も作成できますが、判別に使うのは config.pluginConfig.eventMode で、値は 'enter' / 'leave' です。mouseEnter/mouseLeave ではなく、また config レベルでもありません。config レベルに指定すると、何も通知されずに破棄されます(最初の「ガイドライン」セクションを参照してください)。eventMode には、隣にブール値の multiTimeline も必要です。また、アクショングループが 2 つ以上あるインタラクションには control: "play" が必要です。
分割形式では multiTimeline: false を使用し、true にはしないでください。 ランタイムはこのフラグに基づいて処理を分岐します。true は 2 グループのロールモードで、mouseEnter / mouseLeave のロールコールバックを発行します。上記のロール形式がこれにあたります。false は単一グループモードで、各トリガーがそれぞれのグループを動かし、eventMode によってバインドするイベントを決めます(bindEnter = eventMode !== 'leave')。分割形式では groupId で振り分けるため、false を指定します。
"triggers": [
{
"extensionKey": "wf:hover",
"config": {
"control": "play",
"assignedGroupId": "grp-in",
"pluginConfig": { "multiTimeline": false, "eventMode": "enter" }
},
"target": { "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
},
{
"extensionKey": "wf:hover",
"config": {
"control": "play",
"assignedGroupId": "grp-out",
"pluginConfig": { "multiTimeline": false, "eventMode": "leave" }
},
"target": { "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
}
]
2 つのタイムラインにそれぞれ groupId: "grp-in" / groupId: "grp-out" を指定します。groupId はホストまで保持されます。また、どのタイムラインのグループとも一致しない assignedGroupId は、機能しない値として保存されるのではなく、拒否されます。マルチタイムラインのホバーでは、グループより先にタイムラインのロールで振り分けられる点に注意してください。
どちらの形式も機能し、ユーザーに測定できるような負担はありません。 同じ要素に対して MCP 経由で作成した両形式を Designer で並べて検証したところ、再生結果(開始時に y が 0 → -24、終了時に -24 → 0)は同一で、どちらの形式でも両方のアクショングループに削除コントロールが表示されました。
したがって、これは強い制約ではなく、弱い推奨です。上記の分割形式を推奨します。 パネル自体が書き込む形式なので、ユーザーは手動で作成した場合と同じ内容を確認できます。ロール形式(例 4)も同様に有効です。パネルはこれを新規作成しませんが、編集はできます。
このスキルの以前のバージョンでは、エージェントに対し、再生の忠実性と削除ボタンがないことのどちらかを選ぶよう伝えていました。そのようなトレードオフはありません。詳しくはreferences/trigger-hover.mdを参照してください。
開始時のみの場合は、pluginConfig: { "multiTimeline": false } を指定したトリガーを 1 つと、タイムラインを 1 つ送信します。
ユーザーが開始時のアニメーションだけを希望する場合は、pluginConfig: { "multiTimeline": false } を指定したトリガーを 1 つ送信します。このキーを省略すると、従来のエディターに切り替わります。いずれの場合も、単一タイムラインのホバーでは、パネルに「ホバー終了を別に追加」が表示されないことがあります。ユーザーが両方向のアニメーションを希望する場合は、上記の分割形式をすべて作成してください。
例 5:マウス移動
ユーザー:「カーソルに合わせてこの要素を動かす」
マウス移動は単独で動作します。ターゲットがなくても検証には通りますが、ターゲットがなければ動作しないため、必ずターゲットを指定してください。ページ全体を追跡する場合は wf:viewport(value: "")、範囲を限定する場合は wf:inst / wf:class を指定します。各タイムラインには、mouseX / mouseY / interval の中から一意のロールを割り当てる必要があります。再生用の control / delay / jump / speed は省略してください。詳しくはreferences/trigger-mouse-move.mdを参照してください。
{
"name": "Mouse follow",
"triggers": [
{
"extensionKey": "wf:mouse-move",
"config": {},
"target": { "extensionKey": "wf:viewport", "value": "" }
}
],
"timelines": [
{
"triggerMetadata": { "role": "mouseX" },
"actions": [
{
"id": "act-mouse-x",
"name": "Follow X",
"tt": 2,
"timing": { "duration": 0.4 },
"properties": { "wf:transform": { "x": ["0px", "40px"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
},
{
"triggerMetadata": { "role": "mouseY" },
"actions": [
{
"id": "act-mouse-y",
"name": "Follow Y",
"tt": 2,
"timing": { "duration": 0.4 },
"properties": { "wf:transform": { "y": ["0px", "40px"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
}
]
}
例 6:カスタム JS イベント
ユーザー:「スクリプトがイベントを発火したときに、これを再生してください」
直感に反する要件が 3 つあります。すべて必須です。
- トリガーのターゲットは
wf:body(value: "")である必要があります。他のキーはすべて拒否されます。 - イベント名は
config.pluginConfig.eventNameに設定します。configレベルに設定すると、通知なしに破棄され、トリガーは決して発火しません。 - これは DOM の
CustomEventではありません。これをディスパッチしても何も起きません。サイトは IX3 モジュール経由で発火させます。
{
"name": "Custom event flash",
"triggers": [
{
"extensionKey": "wf:custom",
"config": {
"control": "play",
"pluginConfig": { "eventName": "my-event" }
},
"target": { "extensionKey": "wf:body", "value": "" }
}
],
"timelines": [
{
"actions": [
{
"id": "act-custom-flash",
"name": "Flash",
"tt": 2,
"timing": { "duration": 0.4 },
"properties": { "wf:transform": { "opacity": ["100%", "20%"] } },
"targets": [
{ "extensionKey": "wf:class", "value": ["STYLE_BLOCK_ID"] }
]
}
]
}
]
}
発火方法をユーザーに伝えてください。 そうしないと、ここが壊れているように見えます。
const wfIx = Webflow.require('ix3');
wfIx.emit('my-event');
発火方法は emit だけです。モジュールが公開するのは
{getInstance, emit, destroy, ready, instance} です。trigger、dispatch、
fire はありません。文字列以外、または空白のみの eventName は書き込み境界で拒否されます。指定されていない場合は後方互換性のため受け入れられますが、トリガーは発火しません。references/trigger-custom.md を参照してください。
ガイドライン
まずこれを読んでください:未知の config キーは通知なしに破棄されます
triggerConfigSchema は非 strict の Zod オブジェクトなので、宣言済みフィールドではないキーを trigger.config に指定すると、エラーなしに破棄されます。 書き込みは成功し、レスポンスには問題がないように見え、get_interaction はバイト単位で同じ内容を返しますが、指定したフィールドは失われています。
宣言済みの config フィールド:control、delay、jump、speed、controlType、
scrollTriggerConfig、pluginConfig、assignedGroupId、assignedTimelineRole、
conditionalLogic。
プラグイン固有の内容はすべて config.pluginConfig の中に指定してください — eventName、
eventMode、multiTimeline、smoothness、その他プラグインが定義するものが該当します。
これらを config レベルに指定することは、この操作で最も大きな損失につながる間違いです。何も知らせてくれないためです。
// WRONG — silently discarded, trigger never fires
"config": { "eventName": "my-event" }
// RIGHT
"config": { "pluginConfig": { "eventName": "my-event" } }
dogfood テストでは、この方法で 3 つのフィールド(eventName、eventMode、タイプミスした
easing)が失われ、3 つすべてが API に欠けている機能として誤って記録されました。送信したフィールドがレスポンスにない場合、未対応だと結論づける前に、指定場所が間違っていた可能性を考えてください。
イージング:timing.ease は文字列ではなく数値です
ease は組み込みイージングテーブルを参照する0 以上の整数インデックスか、高度なイージングオブジェクトのいずれかです。文字列を指定すると、これについて何も説明しない Invalid input だけが返されます。
| インデックス | 名前 | インデックス | 名前 | インデックス | 名前 | ||
|---|---|---|---|---|---|---|---|
| 0 | none(リニア) | 11 | power4.out | 22 | elastic.in | ||
| 1 | power1.in | 12 | power4.inOut | 23 | elastic.out | ||
| 2 | power1.out | 13 | back.in | 24 | elastic.inOut | ||
| 3 | power1.inOut | 14 | back.out | 25 | expo.in | ||
| 4 | power2.in | 15 | back.inOut | 26 | expo.out | ||
| 5 | power2.out | 16 | bounce.in | 27 | expo.inOut | ||
| 6 | power2.inOut | 17 | bounce.out | 28 | sine.in | ||
| 7 | power3.in | 18 | bounce.inOut | 29 | sine.out | ||
| 8 | power3.out | 19 | circ.in | 30 | sine.inOut | ||
| 9 | power3.inOut | 20 | circ.out | ||||
| 10 | power4.in | 21 | circ.inOut |
パネルの「Power 1 out」は 2、「Linear」は 0 です。
"timing": { "duration": 0.4, "ease": 2 }
高度なイージングは type で判別するオブジェクトです。そのまま指定してください — 書き込み境界では高度なイージングは拒否されません。
back {curve,power}、elastic {curve,amplitude,period}、steps {stepCount}、
rough {templateCurve,points,strength,taper,randomizePoints,clampPoints}、
slowMo {linearRatio,power,yoyoMode}、expoScale {startingScale,endingScale,templateCurve}、
customWiggle {wiggles,wiggleType}、customBounce {strength,squash,endAtStart}、
customEase {bezierCurve}。curve は in/out/inOut です。
"timing": { "duration": 0.4, "ease": { "type": "back", "curve": "out", "power": 1.7 } }
timing.stagger.ease も同じ形式を取ります。4 つの数値からなるベジェ配列は受け付けられません — {type: "customEase", bezierCurve: "..."} を使用してください。
クラスの変更:wf:class
class という名前のプロパティが1つあり、Set のみです(tt: 3)。
"tt": 3,
"properties": {
"wf:class": {
"class": { "operation": "addClass", "selectors": ["STYLE_BLOCK_ID"] }
}
}
operation は addClass/removeClass/toggleClass です。配列のみ、文字列のみ、または {add: [...]} はすべて拒否されます。
stagger はオブジェクトです
{amount?, axis?, each?, ease?, from?, grid?}。数値のみは拒否されます。
each/amount— 秒、または"250ms"形式の文字列axis—'x'/'y'ease—timing.easeと同じインデックスまたはオブジェクト形式from—'start' | 'center' | 'end' | 'edges' | 'random'、数値、またはnullgrid—'auto'、[columns, rows]形式の数値ペア、またはnull。'none'は拒否されます。
"timing": { "duration": 0.5, "stagger": { "each": 0.05, "from": "start", "grid": [2, 2] } }
filterContext.relationship の列挙値
none · within · direct-child-of · contains · direct-parent-of ·
next-to · next-sibling-of · prev-sibling-of。descendants のような
CSS 風の推測値は拒否されます。
ターゲット値の形式
| キー | 値 |
|---|---|
wf:class | スタイルブロック ID の配列、またはクラス名の文字列 |
wf:inst | [componentId, elementId] — ページレベルの要素では、componentId の欄に ページ ID を指定します。使用できる形式は scope によって決まります。コンポーネントスコープではコンポーネント定義 ID を指定し、サイトおよびページスコープではページ ID を指定します |
wf:selector | "body" などの CSS セレクター文字列。アクションから body をターゲットにする方法です。wf:body はトリガーコンテキスト専用です |
wf:body、wf:viewport | "" — トリガーターゲット専用 |
wf:any-element | "*" — "" ではありません。アクションターゲット専用 |
wf:trigger-only、wf:trigger-only-parent | ""。アクションターゲット専用 |
wf:attribute | 属性名 または完全なセレクター。"data-thing" は [data-thing] として保存され、その属性を持つすべての要素に一致します。同じ属性を持つ要素が複数ある場合は、'[data-thing="x"]' を渡してください |
wf:id はターゲットキーではありません。 すべてのコンテキストで
target type "wf:id" is not offered by the Designer (shouldShow: false in all contexts). Use wf:selector, wf:class, or wf:inst instead.
というエラーで拒否されます。DOM ID でターゲットにするには、wf:selector に '#the-id' を指定してください。作成可能なターゲットキーは8つではなく7つです。
wf:any-element は、値がプレースホルダーではなくワイルドカードである唯一のキーです。
アクション専用の3つのキーは似ていますが、互換性はありません。wf:any-element に "" を指定すると、"wf:any-element" value must be "*" というエラーで拒否されます。通常、これらは filterContext の関係ごとに1行ずつ作成するため、値を間違えると1行ではなくバッチ全体が失敗します。
wf:inst と wf:trigger-only では、有効な filterContext は拒否されます。スタンプされた relationship: 'none' のプレースホルダーは問題ありません。
上限
インタラクションあたりのトリガー 20 · インタラクションあたりのタイムライン 5 · タイムラインあたりのアクション 200 · アクションあたりのターゲット 20 · canvasDuration ≤ 12s · groupId 1–64 文字 · ランダム配列セット 2–12 個の値 · IX3 の値の合計 65,536 bytes。
MCP は作成時と更新時の両方で、これらを Zod の .max() として適用します。 Designer ホストでは、保存済みの上限超過インタラクションに対して上限が引き上げられますが、MCP では引き上げられません。そのため、200 個以上のアクションを含むタイムラインを読み込み、1つのアクションを変更して再送信すると、MCP 経由では失敗します。
ツールスキーマの正誤情報
現在の data_interactions_tool JSON Schema では、conditionalPlayback は {"type": "object"} と記述され、例として
{reducedMotion:"skip"} が示されています。どちらも誤りです。 サーバーバリデーターが要求するのは配列です。以下の conditionalPlayback の箇条書きを参照してください。このフィールドについては、ツールの説明ではなく、このスキルを信頼してください。
また、ツール群によって siteId/pageId の配置が異なる点にも注意してください。data_interactions_tool、data_style_tool、data_element_tool ではトップレベル、data_pages_tool、data_assets_tool、data_agent_instructions_tool ではアクション内にネストした site_id です。
その他すべて
- オブジェクト形式のみ:
{ extensionKey, value, filterContext? }。ネストされたfilterByはオブジェクトではなく、2 要素のタプル["wf:class", ["STYLE_BLOCK_ID"]]です。 - ID: 作成時はタイムラインの
idを省略してください(ホストが生成します)。各アクションには新しい一意のidが必要です。トリガーのidは送信しないでください。 - 不透明度は
wf:styleではなく、wf:transformの下にあります(例:["0%","100%"])。 - クラスの対象: スタイルブロックの ID 配列が推奨されます。クラス名の文字列も使用できます。
wf:classの ID 配列は複合セレクター 1 つに AND 条件として適用され、選択肢のリストにはなりません。["a","b"]は.a.bに解決されます。ホストがコンボクラスの親を展開するため、末端の ID を 1 つ渡してください。異なる 2 つのコンボチェーンの ID を渡すと、どの要素も持たないセレクターになり、エラーなしで対象が見つかりません。対象は 1 つのクラスまたは 1 つのコンボチェーンにしてください。異なる要素群を 2 つアニメーションさせるには、アクションを 2 つ使ってください。- 異なるチェーンで再利用されている末端クラス名(
.btn.liftと.btn.cta.liftは、どちらもliftという名前のスタイルブロックです)は、名前の文字列で渡すと拒否され、ID で渡すと誤った要素に一致します。要素ごとに別のクラスを付けてください。 - Interactions パネルで作成できるものだけを送信してください。 Worker の Zod は寛容ですが、不正な形式は Designer への書き込み時に失敗します。
conditionalPlaybackは{ type, behavior }(およびブレークポイント形式)の配列であり、{reducedMotion:"skip"}ではありません。例:[{ "type": "prefers-reduced-motion", "behavior": "dont-animate" }]。- Load ではトリガーの
targetとpluginConfigを省略します。 - Scroll と mouse-move では、再生の
control/delay/jump/speedを省略します。 scrubのない Scroll にはenter: "play"が必要です。 ホストは永続化時に未指定の切り替えキーを補完します(enter: "play"、その他は"none")。明示的な"none"はそのまま保持されますが、enterは自分で送信してください。パネルは常に 4 つすべての切り替えを書き込むため、補完処理がどこまで適用されているかにかかわらず、明示するのが正しい方法です。scrollTriggerConfig自体は自動補完されません。欠落または null の場合は拒否されます。- Scroll の scrub: 数値の
scrub、canvasDuration: 1、およびアクションのtiming.duration: 1を送信してください。短すぎる duration はスクロール範囲の約 1% しか占めず、何も起きなかったように見えます。 control: "reverse"は最初のクリックでは何も起こりません(再生ヘッドは 0 から始まります)。Preview でユーザーが試せる reverse には、togglePlayReverseを使ってください(pluginConfig.clickは省略するか"each"にします)。- To tween が読み取るのは
toスロットだけです。tt: 0で[from, to]を指定すると半分が無視され、GSAP は要素の現在値からアニメーションします。そのため、スケールされていない要素にscale: [0.55, 1.15]を指定すると 1 → 1.15 になり、不透明な要素にopacity: ["20%","100%"]を指定すると何も起こりません。アニメーションに開始値が必要な場合は、必ずtt: 2を使ってください。 - 自身の from-state によって折りたたまれる要素(
scaleX: 0、width: 0)に、クリックまたは hover のトリガーを設定しないでください。クリックできるボックスが残りません。親要素にトリガーを設定し、子要素をアニメーションさせてください。 - グループ化されたタイムラインは作成できます。
groupId(1~64 文字)は MCP タイムライン入力で使用でき、クリックまたは hover トリガーのconfig.assignedGroupIdを使うと、そのグループに割り当てられます。どのタイムラインのgroupIdにも一致しないassignedGroupIdは、何も起こらない状態で保存されるのではなく拒否されるため、不一致は機能しないインタラクションではなくエラーとして検出されます。Load、scroll、continuous の各トリガーはassignedGroupIdを無視します。 wf:navbarとwf:dropdownは作成できません。また、wf:focus、wf:blur、wf:changeも作成できません。 ガードはフラグもセッション引数も受け取らないため、Statsig の状態にかかわらず、すべての呼び出し元に対してこの制限が適用されます。有効化するフラグはありません。Navbar と dropdown は Designer に登録されていますが、デフォルトの機能セットから除外されています。focus、blur、change には Designer のスキーマがありません。書き込みを試みるのではなく、ユーザーにそのトリガーは利用できないと伝えてください。references/gated-capabilities.md を参照してください。wf:variable、wf:rive、wf:animate-riveは作成できます。それらの形式についてはguideを呼び出してください。timing.positionでは GSAP の位置演算子(+=、<、>)を使用しないでください。有限の数値(秒)または'500ms'を使ってください。- Duration の単位は秒です。
timing.duration: 0.4は 400ms です。400は 400 秒です。ミリ秒で考える場合は"400ms"を使ってください。 - From/FromTo(
tt: 1/2)は、トリガーが発火するまで from-state のままです。 要素を通常時に表示しておく場合は、To(tt: 0または省略)を優先してください。 splitTextには、すでにコピーを含んでいる対象が必要です。対象自身または子孫要素にコピーが含まれている必要があります。制約となるのは要素のタイプではありません。テキストが子ノードになっている Block/Div は問題なく分割できます(公開済みページで検証済み:"Card one"を含む.pg-cardBlock からgsap_split_wordスパンが 2 つ生成されました)。サイレントに失敗するのは、内部にテキストがまったくない対象です。その場合は保存もアニメーションもされません。- ロールはトリガーではなく
timelines[].triggerMetadataにあります。 Mouse-move では、タイムラインごとに一意のmouseX/mouseY/intervalが必要です。 - 拒否された場合:エラーを読み、references/rejects-index.md で確認し、フィールドを推測して追加しないでください。
インストール
npx -y skills add webflow/webflow-skills --skill 'webflow-mcp:interactions' --yes
省略可能な --agent claude-code(または cursor)。呼び出し元には pages:read / pages:write のスコープが必要です。