wix-cli-site-component について
Wix EditorでカスタマイズできるReactサイトコンポーネントを作るWix CLI向けスキルです。マニフェスト、React実装、CSS、TypeScript型、必須の拡張登録を案内します。
主な機能
- 01エディター用マニフェスト設計
- 02型付きReactコンポーネントのパターン
- 03レスポンシブCSSとCSS変数
- 04コンテンツとスタイルの設定
- 05要素単位のエディター設定
- 06必須の拡張登録
活用シーン
- 01カスタマイズ可能なプロフィールカードの作成
- 02内容を設定できるヒーローセクションの作成
- 03編集可能な機能リストの作成
- 04コンポーネント要素の編集コントロール定義
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wix/ skills --skill wix-cli-site-componentインストール後、Claude Code で/wix-cli-site-componentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/CSS_GUIDELINES.mdDESIGN_SYSTEM.mdEXAMPLE.mdMANIFEST_ADVANCED.mdMANIFEST_GUIDELINES.mdREACT_PATTERNS.mdTYPESCRIPT_QUALITY.md詳細
Wix サイトコンポーネントビルダー
Wix CLI アプリケーション用に、エディターマニフェストを備えた本番品質の React サイトコンポーネントを作成します。サイトコンポーネントは Wix Editor と連携する React コンポーネントで、サイト所有者はビジュアルインターフェースからコンテンツ、スタイル、動作をカスタマイズできます。
前提条件: ファイルを作成する前に、開発依存関係として @wix/editor-react-types をインストールしてください。
アーキテクチャ
サイトコンポーネントは必須ファイル 4 つで構成されます。
1. コンポーネントマニフェスト(manifest.json)
React コンポーネントと Wix エコシステムの間の契約を定義します。
- editorElement:ルート要素の設定(セレクター、表示名、アーキタイプ、レイアウト)
- cssProperties:スタイルをカスタマイズする CSS API
- data:コンテンツを設定するデータ API
- elements:詳細な編集に使用するネストされた要素の定義
- behaviors:エディターの操作動作
2. React コンポーネント(component.tsx)
本番環境に対応した React 関数コンポーネントです。
- マニフェストのデータ構造に一致する props インターフェースを実装します
- ルート要素に className と id を適用します
wix.elementsRemovalStateを使って要素の削除状態を処理します- ネストされた要素にはサブコンポーネントのパターンを使用します
- 適切な TypeScript の型指定とエラー処理を含めます
3. CSS スタイル(style.css)
レスポンシブデザインを備えたモダンな CSS です。
- マニフェストおよび React の classNames とセレクターを同期します
- 動的なスタイル設定には CSS 変数を使用します
- メディアクエリを使わずにレスポンシブデザインを実現します(flexbox、grid、clamp)
- エディター要素でポインターイベントを有効にします
- 静的な値にはインラインスタイルを使用しません
- 各セレクターは 1 回のみ記述し、すべての要素に
box-sizing: border-boxを設定します transition: allは使用しません。prefers-reduced-motionを除き、メディアクエリも使用しません- ルートの display:
--display: [value]CSS 変数を宣言し、ルートでdisplay: var(--display)を使用します
4. TypeScript 型(types.ts)
厳密な型定義です。
- 型をインポートします:
import type { Wix, Link, Image, Text, NumberType, BooleanValue, WebUrl, Direction } from '@wix/editor-react-types'— これらをローカルで定義してはいけません(前提条件でインストール済みです) - 例外:
RichText— ローカルでtype RichText = stringと定義します(@wix/editor-react-typesのバージョンでは{ text, html, linkList }であり、単なる文字列ではありません) - すべてのコンポーネントの props インターフェース
- オプショナルチェーンを使用する要素 props の構造
コンポーネントマニフェストの構造
サイトコンポーネントを実装する前に、MANIFEST_GUIDELINES.md を必ず読んでください。 マニフェストの完全な構造、すべてのデータ型、要素設定、必須パターンが記載されています。
マニフェストでは、次の主要なセクションを使ってエディターとの契約を定義します。
installation(初期配置)
{
"installation": {
"staticContainer": "HOMEPAGE",
"initialSize": {
"width": { "sizingType": "pixels", "pixels": 400 },
"height": { "sizingType": "pixels", "pixels": 300 }
}
}
}
- staticContainer:Harmony エディターに自動インストールするには
"HOMEPAGE"を使用します - initialSize:
sizingTypeオプションを使って初期サイズを定義します。"content"— コンテンツに基づいて自動的にサイズを調整します"stretched"— 使用可能な領域いっぱいに広げます"pixels"— ピクセル単位で固定サイズを指定します(pixelsプロパティが必要です)
editorElement(ルート設定)
{
"selector": ".component-name",
"displayName": "Component Name",
"archetype": "Container",
"layout": {
"resizeDirection": "horizontalAndVertical",
"contentResizeDirection": "horizontal"
},
"cssProperties": {
"backgroundColor": {
"displayName": "Background Color",
"defaultValue": "#ffffff"
}
},
"data": {
"columns": {
"dataType": "number",
"displayName": "Number of Columns",
"number": { "minimum": 1, "maximum": 4 }
}
},
"elements": {
"title": {
"elementType": "inlineElement",
"inlineElement": {
"selector": ".component-name__title",
"displayName": "Title",
"data": {
"titleText": {
"dataType": "text",
"displayName": "Title Text"
}
},
"behaviors": {
"selectable": true,
"removable": true
}
}
}
}
}
データ型のリファレンス
すべてのランタイム型は @wix/editor-react-types のものです。
マニフェストの dataType | TypeScript 型 | 使用例 |
|---|---|---|
text | Text | 名前、タイトル、説明 |
textEnum | TextEnum | 定義済みの選択肢 |
number | NumberType | 数量、寸法 |
booleanValue | BooleanValue | 切り替え、フラグ |
a11y | A11y | アクセシビリティ属性 |
link | Link | ナビゲーションリンク |
image | Image | 画像 |
video | Video | メディアコンテンツ |
audio | Audio | 音声コンテンツ |
vectorArt | VectorArt | アイコン、グラフィック |
localDate | LocalDate (string, YYYY-MM-DD) | 日付の値 |
localTime | LocalTime (string, hh:mm[:ss][.sss]) | 時刻の値 |
localDateTime | LocalDateTime (string, YYYY-MM-DDThh:mm[:ss][.sss]) | 日付と時刻の値 |
webUrl | WebUrl (string) | 外部 URL |
richText | RichText (define locally as string) | 書式付きコンテンツ |
arrayItems | ArrayItems | コレクション、リスト |
direction | Direction | HTML の dir 属性 |
menuItems | MenuItems | ナビゲーションメニュー |
CSS プロパティのリファレンス
スタイルのカスタマイズでよく使われる CSS プロパティ:
- レイアウト:
display、gap、padding、margin、width、height - タイポグラフィ:
font、fontSize、fontWeight、textAlign、color - 背景:
backgroundColor、backgroundImage - 境界線:
border、borderRadius、boxShadow - 配置:
alignItems、justifyContent、flexDirection
CSS プロパティの完全なリファレンス: すべての CSS プロパティ、変数のパターン、スタイル設定のベストプラクティスについては、CSS_GUIDELINES.md を参照してください。
React コンポーネントのパターン
フック、エフェクト、コールバックを使うコンポーネントについて: REACT_PATTERNS.md を参照してください。コンポーネントで useEffect、useCallback、複雑な状態、または非同期処理を使う場合に確認してください。フック、配列、ref、SSR に安全なデータ取得の完全なパターンが記載されています。
Props の構造
import type { Wix, Link, Image } from '@wix/editor-react-types'; // also: Text, NumberType, BooleanValue, WebUrl, Direction
interface ComponentProps {
// Standard props (always present)
className: string;
id: string;
wix?: Wix;
// Component-level data (from editorElement.data)
columns?: number;
layout?: string;
// Element props (from elements definitions)
elementProps?: {
title?: {
titleText?: string;
wix?: Wix;
};
button?: {
buttonText?: string;
buttonLink?: Link;
wix?: Wix;
};
};
}
サブコンポーネントのパターン
個別の UI 要素はすべて、名前付きサブコンポーネントに切り出します。各サブコンポーネントには、マニフェストのセレクターと一致する className prop と、それぞれのデータ prop を渡します。
const Title: FC<{ titleText?: string; className: string }> = ({
titleText = "Default Title", className
}) => <h2 className={className}>{titleText}</h2>;
const MyComponent: FC<MyComponentProps> = ({ className, id, elementProps, wix }) => {
const removalState = wix?.elementsRemovalState || {};
return (
<div className={`my-component ${className}`} id={id}>
{!removalState['title'] && <Title className="my-component__title" {...elementProps?.title} />}
</div>
);
};
サブコンポーネントのアーキテクチャ、配列の処理、TypeScript のパターンの詳細については、REACT_PATTERNS.md を参照してください。
条件付きレンダリング
wix.elementsRemovalState に従って、すべての要素を条件付きでレンダリングします:{!removalState['elementKey'] && <Element />}。ここで removalState = wix?.elementsRemovalState || {} です。
CSS ガイドライン
レスポンシブデザインの方針
コンポーネントは、さまざまなビューポート内にある、ユーザーがサイズ変更できるコンテナ(300~1200px)に配置されます。
- ルート要素:
width: 100%; height: 100% - レイアウト構造:流動的なレスポンシブ対応には CSS Grid と Flexbox を使います
- タイポグラフィ:流動的な拡大縮小には
clamp()を使います - 間隔:固定値、または変動幅が小さい
clamp(変動幅 ≤50%)を使います
動的なスタイル設定のための CSS 変数
.component {
--display: block;
--background-color: #ffffff;
--text-color: #333333;
display: var(--display);
background-color: var(--background-color);
color: var(--text-color);
pointer-events: auto;
}
セレクターの同期
重要:CSS セレクターは、マニフェストのセレクターおよび React の className と正確に一致させる必要があります。
- React:
className="profile-card__name" - CSS:
.profile-card__name { ... } - マニフェスト:
"selector": ".profile-card__name"
デザインガイドライン
完全なリファレンス: ビジュアルデザインの原則、クリエイティブガイドライン、美的なベストプラクティスについては、DESIGN_SYSTEM.md を参照してください。
間隔による情報伝達
| 関係性 | 値 | 使用例 |
|---|---|---|
| 狭い(アイコン+ラベル) | 0.25-0.5rem (4-8px) | 関連する項目をまとめる |
| 同じカテゴリ | 1-1.5rem (16-24px) | カードのセクション、フォームフィールド |
| 異なるセクション | 2-3rem (32-48px) | 主要なコンテンツブロック |
| 強調・演出 | 4rem+ (64px+) | ヒーローコンテンツ、高級感の演出 |
ビジュアルの一貫性
- 角丸:類似するすべての要素で同じ角丸を使用します(0〜4pxは角張った形状、6〜12pxは角丸)
- 影のレベル:最大3段階にします(通常時、ホバー時、浮き上がった状態)
- 要素の高さ:類似する要素の高さを統一します
- カラー戦略:階層とゾーンを明確にするため、パレット全体を意図的に使用します
創造的な探索
分かりやすい解決策の先を目指します。
- カード:非対称のグリッド、要素の重ね合わせ、太いアクセント枠線
- リスト:交互に異なるスタイル、スポットライトのパターン、色のリズム
- インタラクティブな要素:分割ボタン、色付きのアイコン円、滑らかなトランジション
- コンテンツの階層:統計情報を大きな数字で表示、引用文のコールアウト、余白による区切り
コンポーネント要素のガイドライン
1つの要素につき1つのマニフェストエントリー
個別のビジュアル要素ごとに、別々のマニフェスト要素が必要です。
- ✅ ボタンが3つ → それぞれ別の要素にする
- ✅ 画像+テキスト → 2つの要素にする
- ❌ 複数の項目を1つの要素としてまとめる
データのスコープに関するルール
editorElement.data - コンポーネント全体の設定のみ:
- ✅ レイアウトの列挙値、数値(columns: 3、speed: 500)
- ❌ テキスト、リンク、画像(要素に属します)
- ❌ 表示/非表示のブール値(代わりにremovable: trueを使用します)
elements[key].data - その特定の要素のコンテンツ:
- ✅ 要素固有のコンテンツ(タイトルのテキスト、ボタンのリンク、画像)
アセット要件
コンポーネントにデフォルト画像が必要な場合は、次の形式を使用します。
// Import in component
import { heroImage } from './assets/defaultImages';
// Usage
<img src={heroImage} alt="Hero" />
アセット仕様の形式:
<imageUrlName>
{ "description": "Modern cityscape at sunset", "width": 1920, "height": 1088 }
</imageUrlName>
ルール:
'./assets/defaultImages'から名前付きエクスポートとしてインポートします- 幅/高さ:64の倍数で、128〜2048pxの範囲
- 外部URLは絶対に使用しないでください
出力構造
src/extensions/site/components/
└── {component-name}/
├── manifest.json # Component manifest
├── component.tsx # React component
├── style.css # CSS styles
├── types.ts # TypeScript types
└── assets/ # Optional assets
└── defaultImages.ts
例
完全な動作例: ネストされた要素、すべてのデータ型、3種類のコンポーネント(Leaf、Container、Root)を含むプロフィールカードについては、EXAMPLE.mdを参照してください。複雑な複数要素のコンポーネントを構築する場合、すべてのパターンが正しいことを確認したい場合、または参照資料が必要な場合は、こちらを読んでください。要素数が5以下のコンポーネントでは、このファイルに記載されたパターンで十分です。EXAMPLE.mdを読む必要はありません。
プロフィールカードコンポーネント
リクエスト:「写真、名前、経験、連絡ボタンを備えたチームメンバーのプロフィールカードを作成してください」
出力:
- 2階層のネスト(写真セクション、情報セクション)を含む8つの要素を持つマニフェスト
- Leaf、Container、Rootのサブコンポーネントを含むReactコンポーネント
- レスポンシブレイアウトとホバー効果を備えたCSS
- すべてのpropsとデータ構造のTypeScript型
ヒーローセクションコンポーネント
リクエスト:「背景画像、見出し、サブタイトル、CTAボタンを備えたヒーローセクションを作成してください」
出力:
- 背景画像のCSSプロパティと3つのテキスト要素を含むマニフェスト
- オーバーレイデザインとタイポグラフィの階層を備えたReactコンポーネント
- レスポンシブなテキストサイズ調整と印象的な余白を備えたCSS
- デフォルトのヒーロー画像のアセット仕様
特徴リストコンポーネント
リクエスト:「項目数を設定できる特徴コンポーネントを作成してください」
出力:
- 特徴のコレクションにarrayItemsデータ型を使用するマニフェスト
- 安全性を確認しながら特徴の配列をループ処理するReactコンポーネント
- 項目数に応じて調整される柔軟なグリッドレイアウトを備えたCSS
- 特徴のアイコン、タイトル、説明用のサブコンポーネント
拡張機能の登録
拡張機能の登録は必須で、2つの手順が必要です。
ステップ 1:コンポーネント固有の拡張ファイルを作成する
各サイトコンポーネントのフォルダーには、extensions.ts ファイルが必要です。
import { extensions } from "@wix/astro/builders";
import manifest from "./manifest.json";
export const sitecomponentMyComponent = extensions.siteComponent({
...manifest,
id: "{{GENERATE_UUID}}",
description: "My Component",
type: "<CODE_IDENTIFIER>.MyComponent",
resources: {
client: {
component: "./extensions/site/components/my-component/component.tsx",
componentUrl: "./extensions/site/components/my-component/component.tsx",
},
},
});
重要:型の命名規則
type フィールドの形式は {CODE_IDENTIFIER}.{PascalCaseFolderName} です。
- フォルダー
my-component→type: "<CODE_IDENTIFIER>.MyComponent" - フォルダー
profile-card→type: "<CODE_IDENTIFIER>.ProfileCard" - フォルダー
hero-section→type: "<CODE_IDENTIFIER>.HeroSection"
フォルダー名はパスカルケースに変換されます(ハイフンを削除し、各単語の先頭を大文字にします)。
CODE_IDENTIFIER の要件: Code Identifier は必須の値で、推測できません。すべての Wix アプリに自動的に割り当てられます。
プロンプトに Code Identifier が指定されている場合:
- それを型のプレフィックスとして使用します:
<actual-code-identifier>.ComponentName
Code Identifier が指定されていない場合:
typeフィールドにプレースホルダー<CODE_IDENTIFIER>を使用します:<CODE_IDENTIFIER>.ComponentName- 手動アクション項目に「
<CODE_IDENTIFIER>を Wix Dev Center の実際の Code Identifier に置き換えてください」を追加します
重要:UUID の生成
id は一意で静的な UUID v4 文字列でなければなりません。拡張ごとに新しい UUID を生成してください。randomUUID() を使用したり、例から UUID をコピーしたりしないでください。
ステップ 2:メインの拡張ファイルに登録する
重要: コンポーネント固有の拡張ファイルを作成した後、必ず wix-cli-extension-registration を読み、「App Registration」セクションに従って src/extensions.ts を更新してください。
ステップ 2 を完了しないと、Wix Editor でサイトコンポーネントを利用できません。
コード品質要件
詳細なリファレンス: 厳格な TypeScript 設定とコード品質基準については、TYPESCRIPT_QUALITY.md を参照してください。
TypeScript の基準
any型を使わない厳格な TypeScript- すべてのデータプロパティは省略可能にする(
?を使用) - すべての関数に明示的な戻り値の型を指定する
- オプショナルチェーンを使用して、null/undefined を適切に処理する
@ts-ignoreまたは@ts-expect-errorコメントを使用しない
React のベストプラクティス
- React 16 と互換性を保つこと — React 18 以降の機能(
useId、useDeferredValue、useTransitionなど)は使用しない - フックを使用した関数コンポーネント
- useEffect で適切な依存配列を指定する
- プロパティの変更にコンポーネントが反応すること
- SSR セーフなコードにすること(モジュールスコープでブラウザー API を使用しない)
ESLint への準拠
- 未使用の変数/パラメーター/インポートを使用しない(
@typescript-eslint/no-unused-vars) - 外部画像を使用しない:
imgのsrcにhttps://...を指定しない(ローカルインポート、wixstatic.com、変数は使用可能) - SSR セーフにする:モジュールスコープ/コンストラクターで
window/documentを使用しない。ブラウザー API はuseEffect/ハンドラー内でガードする dangerouslySetInnerHTMLやインラインの<style>タグを使用しない。動的な値には CSS 変数またはインラインのstyleプロパティを使用するwindow.fetchを使用しない(no-restricted-properties)- フックの
exhaustive-deps:コンポーネントスコープの値で、useEffect/useCallback内で使用するものはすべて依存配列に含める const/letを使用する(varは使用しない)。不明な JSX プロパティは使用しない
よくある間違い
| 間違い | 失敗する理由 | 修正方法 |
|---|---|---|
| CSS セレクターがマニフェストと一致しない | エディターが要素にスタイルを適用できません | マニフェストの selector、React の className、CSS セレクターが完全に一致するようにします |
コンテンツテキストを editorElement.data に設定する | コンテンツはルートではなく、特定の要素に属します | テキスト/画像/リンクのデータを elements[key].data に移動します |
ルートに display: flex を直接設定する | エディターのオーバーライド機能が壊れます | --display: flex CSS 変数を使い、display: var(--display) を設定します |
要素に removable: true がない | サイトのオーナーが要素を非表示にできません | すべての要素に behaviors: { selectable: true, removable: true } を追加します |
arrayItems に data/dataItem/dynamicItems がない | デプロイ時の検証に失敗します | arrayItems オブジェクトには data、dataItem、dynamicItems のいずれかを含める必要があります |
モジュールスコープで window/document を使う | ビルド中に SSR が失敗します | ブラウザー API は useEffect またはイベントハンドラー内で使用します |
@wix/design-system からインポートする | サイトコンポーネントでは利用できません | プレーンな HTML/CSS またはカスタムコンポーネントのみを使います |
import { FC } from 'react' | Astro の tsconfig にある verbatimModuleSyntax では型のみのインポートが必要です | React から import { type FC } または import type { FC } を使います |
厳守事項
- 新しい型、モジュール、関数、props、イベント、インポートを作り出したり、仮定したりしないでください
- 提供されたリファレンスまたはこのプロジェクトですでに使用されている標準ライブラリに明示的に存在するものだけを使ってください
- 依存関係を追加しないでください。
@wix/design-systemまたは@wix/wix-ui-icons-commonは使用しないでください - ユーザー向けのコンテンツはすべて props から取得してください(ハードコードされたテキストは使用しないでください)
- リンク/メディアはマニフェストからのみ取得し、URL をハードコードしないでください
- コード内ではモック、プレースホルダー、TODO を絶対に使用しないでください
- 必ず本番環境で使える完全な機能を実装してください
リファレンスドキュメント
| ファイル | 読むタイミング |
|---|---|
| MANIFEST_GUIDELINES.md | 必ず — マニフェストの構造、要素のルール、CSS プロパティ、同期 |
| MANIFEST_ADVANCED.md | arrayItems、リンクの制約、richText の機能、またはデフォルト以外のインストール時サイズを使う場合 |
| REACT_PATTERNS.md | フック(useEffect、useCallback)、複雑な状態、または配列を使う場合 |
| EXAMPLE.md | 複雑な(要素が 5 つ以上ある)コンポーネントを構築する場合、またはすべてのパターンを照合する場合 |
| CSS_GUIDELINES.md | 高度な CSS パターンやアニメーションが必要な場合 |
| DESIGN_SYSTEM.md | 視覚的に豊かな、ブランドを反映したコンポーネントを構築する場合 |
| TYPESCRIPT_QUALITY.md | 厳格な TypeScript 設定や props インターフェースのパターンが必要な場合 |