webflow-code-component:component-audit について
Webflow コードコンポーネントの Designer 向け設定、Webflow 互換性、構成を確認するスキルです。一般的な React の品質ではなく、Webflow 固有の課題に絞って改善案を提示します。
主な機能
- 01Designer 向けプロパティの確認
- 02状態管理の Webflow 互換性評価
- 03Slot と Shadow DOM のスタイル確認
- 04SSR の問題点を特定
- 05コンポーネント粒度の評価
- 06優先度付き改善案の作成
活用シーン
- 01デザイナーが編集すべき固定コンテンツの発見
- 02Webflow で動作しないコンポーネントの調査
- 03コンポーネント間の状態管理の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ webflow/ webflow-skills --skill webflow-code-component:component-auditインストール後、Claude Code で/webflow-code-component:component-auditを入力して読み込まれたか確認します。
詳細
コンポーネント監査
既存のコードコンポーネントにおけるWebflow固有のアーキテクチャ上の判断を監査します。このスキルでは、一般的なReactのベストプラクティスではなく、コンポーネントがWebflow Designerとどれだけうまく統合できるかに焦点を当てます。
このスキルを使うタイミング
次の場合に使用します:
- Webflow Designerでコンポーネントをより適切に動作させたい場合
- 適切な項目がpropsとして公開されているか、ハードコードされているかを確認する場合
- 状態管理のパターンがWebflowと互換性があるか確認する場合
- コンポーネントをデザイナーにとって使いやすくする方法を探す場合
- Webflowでコンポーネントが期待どおりにレンダリングされない、または動作しない場合
次の場合は使用しないでください:
- デプロイ前の検証(代わりにpre-deploy-checkを使用してください)
- 新しいコンポーネントの作成(代わりにcomponent-scaffoldを使用してください)
- Reactコンポーネントの変換(代わりにconvert-componentを使用してください)
- 一般的なコード品質レビュー(リンターを使用してください)
基本方針
この監査では、次の3つの問いに答えます:
- デザイナーによる制御:デザイナーがカスタマイズできるよう、適切な項目がpropsとして公開されていますか?
- Webflowとの互換性:コンポーネントはWebflowの制約(Shadow DOM、SSR、分離されたReactルート)の範囲内で動作しますか?
- コンポーネントのアーキテクチャ:適切な粒度になっていますか。それとも分割または統合するべきですか?
手順
フェーズ1:調査
-
すべてのコンポーネントを探します:
- webflow.jsonを探す
- すべての.webflow.tsxファイルを探す
- 対応するReactコンポーネントを読む
-
意図を把握します:コンポーネントの用途と、特に気になっている点をユーザーに尋ねます
フェーズ2:分析
各コンポーネントについて、Webflow固有の次の領域を分析します:
A. Propの公開状況の分析
目標:デザイナーが制御できるべきなのに、現在は制御できない項目を特定します。
| 確認項目 | 推奨事項 |
|---|---|
| ハードコードされたテキスト文字列 | props.Text()として公開します |
| キャンバス上でデザイナーが編集するべきテキスト | props.RichText()として公開します |
| 選択肢が固定されたハードコード値 | props.Variant({ options: [...] })として公開します |
| ハードコードされた画像URL | props.Image()として公開します |
| ハードコードされたリンクURL | props.Link()として公開します |
ハードコードされたHTML id属性 | props.Id()として公開します |
| ブール値を使った条件付きレンダリング | props.Boolean()またはprops.Visibility()として公開します |
| 外観に影響する内部状態 | 初期値をpropとして公開することを検討します |
Slotを使っていないchildren | props.Slot()に変換します |
別名:
props.String=props.Text、props.Children=props.Slotです。監査時は同等のものとして扱ってください。
確認する質問:
- 「デザイナーは何を変更したいでしょうか?」
- 「本来コード変更が不要なもののうち、コード変更が必要なものは何でしょうか?」
B. 状態管理のアーキテクチャ
目標:Webflowで動作しないパターンを特定します。
| アンチパターン | 動作しない理由 | 代替案 |
|---|---|---|
| コンポーネント間の状態共有にReact Contextを使う | 各コンポーネントが分離されたReactルートを持つ | nano stores、カスタムイベント、またはURLパラメーターを使う |
| Slotを介したpropsのバケツリレー | Slotの子要素は別々のReactアプリである | nano storesまたはカスタムイベントを使う |
| モジュールレベル変数による状態共有 | SSRの問題を引き起こす可能性がある | ブラウザーのストレージまたはnano storesを使う |
| クリーンアップを行わないグローバルイベントリスナー | メモリーリークやSSRの問題が発生する | クリーンアップを行うuseEffectを使う |
リファクタリングの推奨事項:
- コンポーネント間の通信が必要な場合 → コンポーネント間の状態共有パターンを提案します
- Contextを内部でのみ使用している場合 → 問題ありません。その旨を記載します
- コンポーネントが密結合している場合 → 分解を提案します
C. スロットの活用機会
目標:デザイナーが制御すべきハードコードされたコンテンツを特定します。
| 現在のパターン | より良いパターン |
|---|---|
| カード内にハードコードされたボタン | アクション領域にスロットを使用 |
| ハードコードされたアイコンコンポーネント | スロットまたは Image プロパティを使用 |
| 固定されたヘッダー/フッターの構造 | ヘッダーとフッターにスロットを使用 |
| ハードコードされたリスト項目 | 複数のコンポーネントに分けるべきか検討 |
スロットを使用しない場合:
- コンテンツに特定の動作要件がある場合
- コンテンツがコンポーネントの状態と連携する必要がある場合
- 構造が完全に固定されており、カスタマイズできない場合
D. Shadow DOM との互換性
目標:スタイルが分離された環境でも機能することを確認します。
| 問題 | 検出方法 | 修正方法 |
|---|---|---|
| サイト/グローバル CSS クラスを使用している | .container、.btn などのクラス名 | CSS Modules またはコンポーネントスコープのスタイルを使用 |
| CSS-in-JS が設定されていない | デコレーターなしで styled-components/Emotion を使用 | styledComponentsShadowDomDecorator(styled-components)または emotionShadowDomDecorator(Emotion/MUI)を指定した globals.ts を追加 |
| スタイルのインポートが不足している | スタイルは定義されているが、.webflow.tsx でインポートされていない | import 文を追加 |
| 継承スタイルに依存している | 親のスタイルがカスケードされることを想定している | 明示的なスタイルまたは CSS 変数を使用 |
| タグセレクター(h1、p など)が必要 | Shadow DOM 内でタグにスタイルが適用されない | コンポーネントオプションで applyTagSelectors: true を有効にする |
SSR に関する注意: styled-components または Emotion を使用する場合、SSR が正しく機能するよう、
webflow.jsonでサーバーレンダラーも設定する必要があります。
- styled-components:
"library": { "renderer": { "server": "@webflow/styled-components-utils/server" } }- Emotion:
"library": { "renderer": { "server": "@webflow/emotion-utils/server" } }
E. SSR の安全性
目標:レンダリング中に実行されるブラウザー専用コードを特定します。
| パターン | 問題 | 解決策 |
|---|---|---|
レンダリング中の window.innerWidth | SSR エラー | useEffect を使用するか、ssr: false を設定 |
レンダリング中の document.getElementById | SSR エラー | useEffect または refs を使用 |
useEffect の外での localStorage.getItem | SSR エラー | useState とともに useEffect で囲む |
| window を必要とするサードパーティライブラリ | SSR エラー | 動的インポートまたは ssr: false |
F. コンポーネントの粒度
目標:コンポーネントが適切な抽象化レベルにあるか判断します。
コンポーネントを分割すべき兆候:
- props が多すぎて(10 個超)、デザイナー UI が煩雑になる
- 個別のコンポーネントにできる複数の異なるセクションがある
- デザイナーが各パーツを個別に使いたい
- コンポーネントが互いに無関係な複数の責務を担っている
コンポーネントを統合すべき兆候:
- 常に一緒に使用される
- 状態の結びつきが強く、同期しにくい
- 単独では使われない小さなコンポーネント
フェーズ 3:レポート
次の内容を含む、実行可能なレポートを作成します。
- 概要:調査結果の簡潔なまとめ
- コンポーネント別:各コンポーネントの具体的な問題と推奨事項
- アーキテクチャに関する推奨事項:横断的な懸念事項
- 優先対応事項:最初に修正すべき項目
監査チェックリスト
デザイナーによる制御(Webflow で最も重要)
| 確認項目 | 質問 |
|---|---|
| プロパティの網羅性 | デザイナーが必要なすべての項目をカスタマイズできますか? |
| プロパティの型 | 適切な Webflow プロパティ型が使われていますか? |
| デフォルト値 | プロパティに妥当なデフォルト値が設定されていますか? |
| プロパティの命名 | 開発者以外にも分かりやすい名前ですか? |
| スロットの使用 | ネストされたコンテンツはスロットで処理されていますか? |
| 表示プロパティ | セクションの表示/非表示を切り替えられますか? |
Webflow との互換性
| 確認項目 | 質問 |
|---|---|
| SSR の安全性 | ブラウザー API を使わずにコンポーネントをレンダリングできますか? |
| スタイルの分離 | スタイルは Shadow DOM 内で機能しますか? |
| 状態の独立性 | コンポーネントは親の Context がなくても機能しますか? |
| 関数プロパティがない | 機能しないコールバックプロパティはありませんか? |
アーキテクチャ
| チェック項目 | 質問 |
|---|---|
| 単一責任 | コンポーネントは1つのことを適切に行っていますか? |
| 適切な粒度 | Designer での使用に適したサイズですか? |
| コンポーネント間の状態 | 必要な場合、正しく実装されていますか? |
例
ユーザープロンプト:
Audit my ProductCard component
レスポンス:
## Audit: ProductCard
### Component Overview
```typescript
// Current props
props: {
title: props.Text(),
price: props.Number(),
imageUrl: props.Text() // ⚠️ Should be Image
}
A. プロパティ公開の分析
| 指摘事項 | 重要度 | 推奨事項 |
|---|---|---|
imageUrl が Image ではなく Text になっています | 警告 | アセットを適切に処理するため、props.Image() に変更します |
| 「カートに追加」ボタンのテキストがハードコードされています | 提案 | プロパティとして公開します:addToCartText: props.Text() |
| セールバッジは条件付きで表示されますが、制御できません | 提案 | showSaleBadge: props.Boolean() を追加します |
| バッジの色が赤にハードコードされています | 提案 | badgeVariant: props.Variant({ options: ["sale", "new", "featured"] }) を追加します |
見つかったハードコード済みコンテンツ:
// Line 24 - hardcoded, should be prop
<button>Add to Cart</button>
// Line 18 - hardcoded, should be prop or removed
{onSale && <span className="badge">SALE</span>}
追加を推奨するプロパティ:
props: {
// ...existing
addToCartLabel: props.Text({
name: "Button Label",
defaultValue: "Add to Cart"
}),
showBadge: props.Boolean({
name: "Show Badge",
defaultValue: false
}),
badgeType: props.Variant({
name: "Badge Type",
options: ["sale", "new", "featured"],
defaultValue: "sale"
})
}
B. 状態管理
| 指摘事項 | 重要度 |
|---|---|
カート数に localStorage を使用しています | 警告 |
| React Context への依存はありません | OK |
問題:render 内の localStorage
// Line 8 - will break SSR
const cartCount = localStorage.getItem('cart');
修正:
const [cartCount, setCartCount] = useState(0);
useEffect(() => {
setCartCount(parseInt(localStorage.getItem('cart') || '0'));
}, []);
C. スロットの活用機会
| 現状 | 推奨事項 |
|---|---|
| ボタンがハードコードされています | 検討事項:柔軟な CTA のために actions: props.Slot() を使用します |
デザイナーがアクション領域に異なるコンテンツ(ボタン、リンク、カスタム要素)を配置する必要がある場合:
props: {
actions: props.Slot({
name: "Actions"
})
}
// Component
<div className={styles.actions}>
{actions}
</div>
ただし、ボタンの動作がカートのロジックに紐づいている場合は、ハードコードしたままにします。
D. Shadow DOM との互換性
| チェック項目 | ステータス |
|---|---|
| .webflow.tsx でスタイルをインポート | ✅ OK |
| CSS Modules を使用 | ✅ OK |
| グローバルクラスへの参照なし | ✅ OK |
E. SSR の安全性
| チェック項目 | ステータス |
|---|---|
| window の使用 | ✅ なし |
| document の使用 | ✅ なし |
| localStorage の使用 | ⚠️ ガードが必要(上記の修正を参照) |
F. コンポーネントの粒度
現在のサイズ:4 個のプロパティ(推奨事項の適用後は 7 個) 評価:適切な粒度です。単一の目的で、プロパティも管理しやすいです。
まとめ
| カテゴリー | ステータス |
|---|---|
| Designer による制御 | ⚠️ 要対応:ハードコードされた項目が 4 個見つかりました |
| 状態管理 | ⚠️ localStorage に SSR ガードが必要です |
| Shadow DOM | ✅ 良好 |
| SSR の安全性 | ⚠️ 問題が 1 件あります |
| 粒度 | ✅ 良好 |
優先して対応する項目:
- localStorage の SSR 問題を修正します(デプロイを妨げます)
- imageUrl を Text から Image プロパティに変更します
- バッジの制御項目をプロパティとして公開します
- ボタンのラベルの公開を検討します
## Guidelines
### What This Audit Does NOT Check
This is not a generic code quality audit. Skip:
- Generic React performance patterns (let users use React DevTools)
- Generic accessibility (let users use axe or similar)
- Code formatting (let users use Prettier/ESLint)
- Generic TypeScript best practices
Focus only on Webflow-specific concerns.
### Prop Exposure Heuristics
**Should be a prop:**
- Any text visible in the UI
- Any image or media
- Any color or size that might vary
- Any boolean that controls visibility
- Any value that changes per-use
**Should NOT be a prop:**
- Internal implementation details
- State that changes during interaction
- Values derived from other props
- Animation timing/easing (unless explicitly customizable)
### When to Recommend Slots vs Props
**Use Slot when:**
- Designer wants to put arbitrary Webflow elements inside
- Content structure is flexible
- Nested content doesn't need to interact with component state
**Use Props when:**
- Content is simple (text, image, link)
- Component needs to process/transform the content
- Specific structure is required
### State Pattern Recommendations
If components need to share state, recommend in this order:
1. **URL parameters** - if state should be shareable/bookmarkable
2. **Nano stores** - for real-time sync between components
3. **Custom events** - for fire-and-forget communication
4. **Browser storage** - for persistence across sessions