vtex-io-storefront-theme-app について
VTEX IOのストアフロントテーマアプリで、ページブロックの構成、カスタムルートの定義、Site Editorで編集可能なコンテンツの設定を行うスキルです。テーマアプリ、コンポーネントアプリ、マーチャント管理コンテンツの役割も整理します。
主な機能
- 01ページのブロックツリーとテンプレートの構成
- 02ストアフロントのカスタムルート定義
- 03Site Editorで編集可能なプロパティの設定
- 04ブロック参照とアプリのメジャーバージョン確認
- 05テーマ継承とバージョン移行の計画
活用シーン
- 01ストアのホームや商品ページのレイアウト作成
- 02ページコンテキストを伴うカスタムルートの追加
- 03Site Editorでマーチャントがページ内容を編集
- 04ブロック欠落やテーマのメジャーバージョン変更リスクの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vtex/ skills --skill vtex-io-storefront-theme-appインストール後、Claude Code で/vtex-io-storefront-theme-appを入力して読み込まれたか確認します。
詳細
ストアフロントテーマアプリ
このスキルを使用する場合
ストアフロントを構成するアプリ、つまりストアのページツリー、カスタムルート、サイトエディターの表示領域を管理するテーマアプリを扱う際に、このスキルを使用してください。
vendor.store-theme、またはページを提供するstoreビルダーを持つアプリのスキャフォールディングstore/blocks.jsonまたはstore/blocks/以下のテンプレート別ファイルの追加・変更store/routes.jsonへのカスタムルートの追加・変更store.home、store.product、store.search、store.custom、またはネイティブページテンプレートのブロックツリーの構成vtex.store-themeなどのベーステーマの拡張またはオーバーライド- 変更内容がテーマアプリ、コンポーネントアプリ、アプリ設定のどこに属するかの確認
以下の場合は、このスキルを使用しないでください。
- コンポーネントアプリで新しいブロックを登録する場合(
store/interfaces.json) —vtex-io-render-runtime-and-blocksを使用してください - ブロックの背後にある React コンポーネントを実装する場合 —
vtex-io-storefront-reactを使用してください masterでテーマアプリのインストール済みバージョンを変更する場合 —vtex-io-storefront-theme-versioningを使用してください- ローカライズされた文字列の場合 —
vtex-io-messages-and-i18nを使用してください
判断ルール
- テーマアプリは、
manifest.jsonでstoreビルダーを宣言する通常の VTEX IO アプリです。React コードを含むことはほとんどなく、コンポーネントアプリやベーステーマが宣言するブロックを組み合わせます。 - テーマアプリは通常
vtex.store-themeであるベーステーマをmanifest.json#dependenciesで宣言し、ベーステーマが提供するすべてのページテンプレート、ブロック宣言、デフォルトコンテンツを継承します。 store/blocks.json(またはstore/blocks/以下のテンプレート別ファイル)は、ブロック ID を参照して、ページテンプレートごとのブロックツリーを定義します。ブロック ID はコンポーネントアプリのstore/interfaces.jsonに由来し、宣言元アプリの MAJOR バージョンごとにスコープされます。store/routes.jsonはカスタムストアフロントルートを定義し、ページコンテキスト(store.custom、store.product、store.searchなど)に紐付けます。ネイティブルート(/、/{slug}/p、検索)はベーステーマに由来するため、再宣言する必要はほとんどありません。store/contentSchemas.jsonは、サイトエディターで編集可能なブロックのプロパティを宣言します。マーチャントがこれらのプロパティに加えた変更はvtex.pages-graphqlに保存され、テーマアプリの MAJOR バージョンを含むキーで管理されます。- ストアフロントの動作を変更できる場所は3つあります。意識して選択してください。
- テーマアプリの
store/JSON — 構成、ルート、デフォルトコンテンツ、許可される子要素を扱います。プロモート後、すべての買い物客に直ちに反映されます。 - コンポーネントアプリのコード — ブロックの React による動作を扱います。コンポーネントアプリ独自のバージョンリリースサイクルでリリースされます。
- サイトエディター — テーマのデフォルトの上書きとして、マーチャントが管理するコンテンツを扱います。
vtex.pages-graphqlに保存され、宣言元アプリのインストール済みメジャーバージョンごとにスコープされます。
- テーマアプリの
- ベーステーマをフォークするより、拡張することを優先してください。ベーステーマをフォークすると、上流のバグ修正も含め、すべてのブロック、ルート、テンプレートに対する責任を永久に自分のアプリが負うことになります。
- ストアフロントページはブロックのツリーです。末端はコンポーネントブロック、枝はコンテナブロック(
flex-layout.row、flex-layout.colなど)です。デザイン上可能な限りツリーを浅く保ってください。深いツリーはレンダリングとコンテンツの負荷を増大させます。 vtex-io-storefront-theme-versioningの意味では、テーマアプリはコンテンツを保持するアプリです。インストール済みのメジャーバージョンは、このアプリが宣言したブロックに対してマーチャントがこれまでに保存した、サイトエディターのすべての変更について、プラットフォームが使用するキーの一部になります。そのバージョン契約は開発者向けではなく、マーチャント向けとして扱ってください。
厳守事項
制約:テーマアプリでは store ビルダーとベーステーマを宣言する必要があります
ストアフロントのテーマアプリは、manifest.json#builders に "store" を宣言し、すべての標準ページテンプレート、ブロック、ルートを明示的に引き受けるのでない限り、ベーステーマ(通常は vtex.store-theme)に依存する必要があります。
重要な理由
store ビルダーがないと、store/ 配下のファイルは一切処理されず、テーマはストアフロントに何も追加しません。ベーステーマがない場合、アプリはすべての標準ページテンプレート(store.home、store.product、store.search など)を一から宣言する必要があり、その後のメンテナンスも永久に担うことになります。
検出方法
テーマアプリに store/blocks.json または store/routes.json が含まれているのに、マニフェストの builders に "store" が宣言されていない場合は、作業を中断してビルダーを追加してください。マニフェストの dependencies または peerDependencies に vtex.store-theme(または別のベーステーマ)が含まれておらず、明示的な理由もない場合は、作業を中断して、そのアプリがすべての標準テンプレートを引き受ける意図があることを確認してください。
正しい例
{
"vendor": "acme",
"name": "store-theme",
"version": "1.0.0",
"title": "ACME Store Theme",
"builders": {
"store": "0.x",
"messages": "1.x"
},
"dependencies": {
"vtex.store-theme": "2.x",
"acme.product-widgets": "0.x"
}
}
誤った例
{
"vendor": "acme",
"name": "store-theme",
"version": "1.0.0",
"builders": {
"messages": "1.x"
},
"dependencies": {}
}
store/ ファイルはディスク上に存在しますが、プラットフォームはそれらを無視し、テーマは何も継承しません。
制約:store/blocks.json のブロック ID は、インストール済みアプリで登録されたブロックを参照する必要があります
store/blocks.json(またはテンプレートごとのファイル)で参照されるすべてのブロック ID は、プラットフォームがレンダリング時に解決する MAJOR バージョンと一致する、インストール済みアプリの interfaces.json で宣言されている必要があります。解決できないブロック ID があると、GraphQL レイヤーで Missing block エラーが発生し、ページが表示できなくなります。
重要な理由
vtex.pages-graphql は、インストール済みアプリを検索して [email protected]:block-id を照合し、ブロック ID を解決します。宣言元のアプリがインストールされていない場合、またはマーチャントのコンテンツ作成時とは異なるメジャーバージョンでインストールされている場合、リゾルバーからはブロックが存在しないものとみなされ、ページのレンダリングに失敗します。
検出方法
store/blocks.json がブロック ID を参照している場合、manifest.json#dependencies にあるアプリのいずれかが、依存関係に記載されたメジャーバージョンの範囲で store/interfaces.json にそのブロックを宣言していることを確認してください。依存関係が [email protected] の場合、ブロックはそのアプリの 5.x 系ではなく、0.x 系に存在する必要があります。
正しい例
// manifest.json
{
"dependencies": {
"vtex.store-theme": "2.x",
"acme.product-widgets": "0.x"
}
}
// store/blocks.json
{
"store.product": {
"children": [
"flex-layout.row#product-main",
"acme-related-products"
]
},
"acme-related-products": {
"props": { "limit": 8 }
}
}
// [email protected] ships store/interfaces.json with:
{
"acme-related-products": {
"component": "RelatedProducts"
}
}
誤った例
// manifest.json depends on [email protected]
// but store/blocks.json references a block that only exists in @5.x
{
"store.product": {
"children": ["acme-new-related-products"]
}
}
レンダリング時のリゾルバーが Missing block [email protected]:acme-new-related-products を返し、ページの表示に失敗します。
制約:store/routes.json のカスタムルートは、実在するページコンテキストとテンプレートに紐付ける必要があります
store/routes.json の各エントリーでは、有効な path と context(または store.product などの標準ページ ID に組み込まれたコンテキストを利用すること)を設定し、ブロックツリーに存在するテンプレート(ページ ID 自体、または store/blocks.json で宣言された store.custom#<id>)を指定する必要があります。
重要な理由
解決可能なテンプレートがないルートエントリーでは、何もレンダリングされません。コンテキストが誤っているルートエントリー(たとえば、カスタムの法人向けページを store.product として指定した場合)は、誤ったデータリゾルバーを実行し、クラッシュしたり、商品データが空で返されたりします。
検出方法
store/routes.json の各ルートについて、次の点を確認してください。(a)path が標準の VTEX パスと衝突しないこと、(b)紐付けられたページ ID が store/blocks.json のキーとして存在すること、(c)context がページで実際に必要なデータと一致すること。
正しい例
// store/routes.json
{
"store.custom#about": {
"path": "/institucional/sobre",
"context": "vtex.store-resources/InstitutionalPageContext"
}
}
// store/blocks.json
{
"store.custom#about": {
"blocks": ["rich-text#about-body"]
}
}
誤った例
// store/routes.json
{
"store.custom#about": {
"path": "/p/sobre"
}
}
パス /p/sobre が標準の PDP ルート形式と衝突しており、context が宣言されておらず、store/blocks.json に対応する store.custom#about テンプレートもありません。
推奨パターン
推奨されるテーマアプリの構成:
acme.store-theme/
├── manifest.json # store builder, base theme dependency
├── messages/ # localized strings (separate skill)
└── store/
├── blocks.json # global block declarations
├── routes.json # custom routes
├── contentSchemas.json # Site Editor-editable props
└── blocks/ # per-template block trees
├── home.jsonc
├── product.jsonc
├── search.jsonc
├── category.jsonc
└── custom/
├── about.jsonc
└── stores.jsonc
推奨される store.home の構成:
{
"store.home": {
"blocks": [
"flex-layout.row#home-hero",
"shelf#home-best-sellers",
"rich-text#home-newsletter"
]
},
"flex-layout.row#home-hero": {
"children": ["image#hero-banner"]
},
"image#hero-banner": {
"props": {
"src": "/arquivos/home-hero.png",
"alt": "Promotional banner"
}
}
}
推奨されるカスタムの機関向けルート:
// store/routes.json
{
"store.custom#about": {
"path": "/institucional/sobre",
"context": "vtex.store-resources/InstitutionalPageContext"
}
}
// store/blocks/custom/about.jsonc
{
"store.custom#about": {
"blocks": ["flex-layout.row#about-body"]
},
"flex-layout.row#about-body": {
"children": ["rich-text#about-copy"]
},
"rich-text#about-copy": {
"props": {
"text": "About ACME — see Site Editor for the live copy."
}
}
}
推奨される Site Editor で編集可能な領域:
// store/contentSchemas.json
{
"rich-text#about-copy": {
"type": "object",
"properties": {
"text": {
"type": "string",
"title": "Body copy",
"widget": { "ui:widget": "textarea" }
}
}
}
}
text に対するマーチャントの編集内容は、テーマアプリの MAJOR バージョンを含むキーで vtex.pages-graphql に保存されます。メジャーバージョンを上げるとそのコンテンツに何が起こるか、および updateThemeIds ミューテーションを使った移行方法については、vtex-io-storefront-theme-versioning を参照してください。
よくある失敗パターン
vtex.store-themeに依存せずフォークしてしまい、以後、上流のブロック修正やルート追加が一切反映されなくなる。store/blocks.jsonで、依存関係のバージョン範囲が許容するものとは異なるメジャーバージョンの宣言元アプリに存在するブロック ID を参照する。- 2 つの異なるアプリで同じブロック ID を宣言し、レンダリング時の解決が非決定的になる。
contentSchemas.jsonを用意せずに、Site Editor で編集可能な文言をstore/blocks.jsonのpropsに直接置き、マーチャントが変更できないようにする。- 対応する
store.custom#<id>テンプレートをstore/blocks.jsonに追加せず、store/routes.jsonにカスタムルートを追加する。 - テーマアプリのバージョンを開発者向けのものとして扱い、「整理」のためにメジャーバージョンを上げる。その結果、新しいメジャーバージョンにはマーチャントのコンテンツがなくなり、プロモート前に
[email protected]でupdateThemeIdsによる移行が必要になる(vtex-io-storefront-theme-versioningを参照)。 - React コンポーネントのコードを専用のコンポーネントアプリではなくテーマアプリに置くことで、ブロックの宣言と利用が混在し、再利用が複雑になる。
- 運用データや購入者固有のデータをテーマの
store/ファイルに保存する。テーマは全体に適用されるため、購入者単位またはセグメント単位のデータは別の場所に置く必要があります。
レビューチェックリスト
-
manifest.jsonでstoreビルダーが宣言されていますか? - テーマはベーステーマに依存していますか?それとも、ネイティブテンプレートを全面的に所有することが明示され、意図されていますか?
-
store/blocks.jsonのすべてのブロック ID は、インストール済みアプリの適切なメジャーバージョンにある実際のinterfaces.jsonエントリーに解決されますか? -
store/routes.jsonのすべてのエントリーに有効なpathとcontextがあり、store/blocks.jsonに対応するテンプレートがありますか? - マーチャントが編集できる文言や画像フィールドは、
propsにハードコードせず、contentSchemas.jsonを通じて公開されていますか? - React コンポーネントはテーマアプリではなく、専用のコンポーネントアプリに置かれていますか?
- 予定している変更によって、このコンテンツを保持するアプリのメジャーバージョンを上げる必要が生じないか、チームで検討しましたか?
関連スキル
vtex-io-storefront-theme-versioning—masterにインストールされるこのテーマアプリのバージョンを安全に変更する方法が質問の場合に使用します。vtex-io-render-runtime-and-blocks— ブロック ID が React コンポーネントになる仕組みや、コンポーネントアプリがテーマで利用するブロックを宣言する方法が質問の場合に使用します。vtex-io-storefront-react— ページへの組み込みではなく、ブロックの React 実装が質問の場合に使用します。vtex-io-app-contract— テーマアプリのマニフェスト契約で宣言すべき内容や、ベーステーマおよびコンポーネントアプリとの連携が質問の場合に使用します。
参考資料
- Store Framework — テーマアプリがブロックとテンプレートからページを組み立てる方法です。
- Using Components — ベーステーマやコンポーネントアプリのブロックを参照する方法です。
- Themes — テーマアプリの構成と
vtex.store-themeとの関係です。 - Routes — カスタムストアフロントルートを宣言し、ページコンテキストに関連付ける方法です。
- Making a Custom Component Available in Site Editor —
contentSchemas.jsonと Site Editor の画面について説明します。