Claude CodeでShopify checkout UI extensionを作る手順 — app devで確認
Claude Codeにcheckout UI extensionを書かせるとき、targetとPlus条件を先に決め、unit testで形を固め、shopify app devの開発ストアで画面を確かめる流れをまとめます。
Claude CodeでShopify checkout UI extensionを作る手順 — app devで確認
Claude Codeにcheckout UI extensionを書かせるときは、コードより先に「どのtargetに出すか」を決めます。checkout UI extensionはチェックアウトの特定の位置に差し込む拡張で、targetが使えるAPIと配置の自由度を決めるからです。決めずに書かせると、動くけれど置き場所が違うコードができます。
この記事では、targetの選び方、使えるUI部品の制約、Claudeが自分で確かめられる範囲、shopify app dev で開発ストアのチェックアウトを見る手順を順に扱います。割引や配送ロジックを書くFunctionsは別の話で、Claude CodeでShopify Functionsを書く手順にまとめています。
先に決めるのはtargetとPlus条件
checkout UI extensionは、チェックアウトの画面に独自のUIとロジックを足す拡張です。たとえばカート確認中のメッセージ表示や、サンクスページのアンケートが例に挙がっています。構成要素は3つです。
拡張を構成する3つの部品
target
画面のどこに出すかを決めます。種類はblock、runnable、staticの3つです。
target API
チェックアウトのデータや機能にアクセスする口です。実行時に渡される
shopifyグローバルオブジェクトのshopify.costやshopify.buyerIdentityなどがそれにあたります。web component
ボタンやスタックなどのUI部品です。Shopifyが提供する要素だけを描画できます。
Claudeへの最初の指示には、この3つのうちtargetを必ず含めます。選ぶ軸は、位置をマーチャントに任せるかどうかです。
staticとblockの違い
static target
配送方法リストの前後など、チェックアウト機能の前後に自動で描画されます。位置は動かせません。紐づく機能が表示されない場面(店舗受け取りを選ぶと配送方法が出ない、など)では、そのtargetも描画されません。
block target
チェックアウトエディタで、マーチャントが対応する配置の中から置き場所を選びます。紐づく機能が隠れていても常に描画されます。
配送の遅延告知のように特定の機能に紐づく内容はstatic、信頼バッジや販促のように置き場所を店舗側で変えたい内容はblockが向きます。サンクスページ用の purchase.thank-you.block.render や、チェックアウト用の purchase.checkout.block.render が代表的なblock targetです。1つのblock target位置に追加できる拡張は最大3つです。
もう1つ、書く前に確かめる条件があります。情報・配送・支払いのステップに描画される拡張は、Shopify Plusプランの店舗だけで使えます。ターゲットの選択がそのまま提供先の店舗プランを左右するので、依頼の最初に「出す店舗はPlusか」を伝えておくと、Claudeが使えない案を出さずに済みます。
雛形を作ってからtargetを指定する
雛形はShopify CLIで作ります。checkout_ui テンプレートを指定すると、設定ファイルの shopify.extension.toml と、コードを書く Checkout.jsx が生成されます。
cd my-app
shopify app generate extension --template checkout_ui雛形づくりは人が実行し、生成されたファイルをClaudeに読ませる流れが安全です。生成直後の設定は shopify.extension.toml で確かめます。形はこうなります。
api_version = "2026-10"
[[extensions]]
type = "ui_extension"
name = "My checkout UI extension"
handle = "my-checkout-extension"
[[extensions.targeting]]
target = "purchase.checkout.block.render"
module = "./src/Checkout.tsx"複数のtargetを1つの設定ファイルに書く場合、各targetは別々のモジュールを指します。同じファイルを2つのtargetで共有できません。Claudeにtargetを足させるときは、ここを先に伝えます。handle は下書きバージョンを作るかデプロイした後は変更できないため、名前を気軽に変えさせない点も指示に入れておくと安心です。
CLAUDE.mdには、こうした固定の前提を書いておきます。
# checkout UI extension の規約
- 出す先は Shopify Plus の店舗。情報・配送・支払いステップの target も使ってよい
- target は shopify.extension.toml の extensions.targeting に書く。target ごとに module を分ける
- UI は <s-stack> <s-text> <s-button> など Shopify 提供の web component だけで組む。独自 CSS と生の HTML は使わない
- 変更後は npm test を実行して結果を読み、失敗を直す
- shopify app dev は人が起動する。shopify app deploy は実行しない使えるのはShopify提供のweb componentだけ
checkout UI extensionは、チェックアウトのDOMにアクセスできません。任意のHTMLも描画できず、描画できるのはShopifyが提供するカスタム要素だけです。コンポーネントのCSSも上書きできず、チェックアウトには常にマーチャント自身のブランディングが適用されます。
通常のWebアプリの感覚で <div> やインラインスタイルを書かせると、描画できません。そこで効くのが上の規約です。web componentの一覧は、アクション、フィードバック表示、フォーム、レイアウト、メディア、オーバーレイ、タイポグラフィの7つの区分に分かれています。さらに、targetによって使えるコンポーネントが変わります。
実装の形は、公式ドキュメントのサンプルに沿うとこうなります。小計を表示する例です。
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
export default function extension() {
render(<Extension />, document.body);
}
function Extension() {
const subtotal = shopify.cost.subtotalAmount.value;
return (
<s-stack>
<s-text>
Subtotal: {subtotal.amount} {subtotal.currencyCode}
</s-text>
</s-stack>
);
}shopify.cost.subtotalAmount.value のように、データは shopify オブジェクトから読みます。ESLintを使うプロジェクトでは、グローバルの shopify を readonly で宣言しないとlintが落ちます。この設定もClaudeに先に伝えます。
落とし穴
カートやメタフィールドの変更を連打すると、変更が止まる
applyAttributeChange や applyMetafieldChange は、変更が多すぎるとレート制限を受けます。制限された拡張は、そのバイヤーのセッション中、それ以上の変更ができません。Claudeにイベントごとに変更を呼ばせず、必要な変更だけを Promise.all でまとめるよう指示します。
Claudeが自分で確かめられる範囲
Claudeが自分で実行できて、結果を読んで直せるのは、ローカルのテストまでです。API version 2026-04 以降のcheckout UI extensionでは、@shopify/ui-extensions-tester を使ってユニットテストを書けます。ShopifyのリポジトリにはサンプルのテストスイートとREADMEがあり、Claudeにはこれを参照させます。
権限は、テストなどの読み取り中心の操作を許可し、本番にかかわる操作を確認に置く形で組みます。Claude Codeの権限ルールは、denyが先、次にask、最後にallowの順で評価されます。
{
"permissions": {
"allow": [
"Bash(npm test *)",
"Bash(npm run lint *)"
],
"ask": [
"Bash(shopify app generate extension *)",
"Bash(shopify app dev *)"
],
"deny": [
"Bash(shopify app deploy *)"
]
}
}shopify app deploy は、拡張のバンドルをビルドしてShopifyへアップロードするコマンドです。denyに置けば、Claudeが勝手に走らせる経路を塞げます。デプロイは人が実行します。
ここで注意するのは、ユニットテストが通ってもチェックアウトの見え方は保証されない点です。レイアウトや配置の確認は、次の手順で人が画面を見て行います。見た目がおかしいときは、スクリーンショットを会話に貼れば、Claudeは画像を分析できます。貼り付けは Ctrl+V で行い、WindowsとWSLでは Alt+V です。
shopify app devで開発ストアのチェックアウトを確かめる
shopify app dev は、アプリを開発ストアでビルドしてプレビューし、変更を監視するコマンドです。開発サーバーはコードを変えると拡張を自動で再読み込みするので、Claudeの編集結果をすぐ画面で確認できます。
開発ストアで拡張を確かめる流れ
- 1
開発サーバーを起動する
アプリのディレクトリで
shopify app devを実行します。ストアを指定するなら-sを使い、既存の開発ストアかShopify Plusのサンドボックスストアを渡します。 - 2
チェックアウトのURLを開く
CLIが出力するチェックアウトのURLを開きます。カートの中身を固定したいときは
--checkout-cart-urlに/cart/{商品バリアントID}:{数量}の形式で渡せます。 - 3
block targetは位置を切り替える
URLの末尾に
?placement-reference=DELIVERY1のように付けると、対応する配置で表示されます。 - 4
チェックアウトエディタで追加する
管理画面でSettings > Checkoutを開き、Customize checkoutからアプリブロック(Add app block)を追加します。一覧に拡張が出ないときは、
shopify app devが動いているか確かめます。
shopify app dev -s my-dev-store.myshopify.com \
--checkout-cart-url "/cart/1234567890:2"1234567890 はバリアントIDの仮の値で、自分のストアの値に置き換えます。
配置を試すときの参照名は、ページごとに決まっています。
| 表示ページ | block target | placement reference |
|---|---|---|
| チェックアウト | block targetpurchase.checkout.block.render | placement referenceWALLETS1、INFORMATION1〜3、DELIVERY1・2、PAYMENT1〜4 |
| サンクスページ | block targetpurchase.thank-you.block.render | placement referenceORDER_SUMMARY1〜4、ORDER_STATUS1〜3 |
マーチャントが最初に見る配置は、TOMLの default_placement で指定できます。値は、そのtargetが対応する配置の参照名でなければなりません。
チェックアウトの形は店舗の設定で変わるため、次の3パターンを必ず切り替えて見ます。
- 3ページのチェックアウト(既定)
- 1ページのチェックアウト
- Shop Pay
エディタのSettingsタブにあるCheckout layoutで、3ページと1ページを切り替えます。Shop Payで見るには、開発ストアでShopify Paymentsのテストモードを有効にします。そのうえでエディタでInclude app in Shop Payを有効にし、Preview Shop Payを開きます。
capabilityとバンドル上限を設計に入れる
外部APIの呼び出しやバリデーションを足すときは、設定ファイルの [extensions.capabilities] への宣言が要ります。
| capability | できること | 注意 |
|---|---|---|
api_access | できることStorefront APIに問い合わせる | 注意— |
network_access | できること外部へのネットワーク呼び出し | 注意公開するには承認の申請が必要 |
block_progress | できることバイヤーの進行を止める | 注意マーチャントが拒否できる |
block_progress は、マーチャントがチェックアウトエディタで許可しない場合があります。その場合、behavior: 'block' の指定は 'allow' として扱われ、チェックアウトは進みます。ローカルの拡張では自動で許可されるので、開発中は通るのに本番で止まらない、という差が出ます。TOMLから block_progress を外せば、拒否された状態を再現できます。拒否された場合の代わりに警告を出す作りにしておくよう、Claudeに伝えます。
デプロイ時の制約にも触れておきます。コンパイル後のUI拡張のバンドルは64 KBを超えられず、超えるとデプロイ時にはじかれます。依存ライブラリを足すときは、バンドルサイズを意識する必要があります。unhandledrejection と error のリスナーを置いてエラーを拾う作りにすると、本番での不具合の切り分けも楽になります。
本番の店舗へ出す前の確認
開発ストアでの確認が済んだら、shopify app deploy で本番へ反映します。デプロイは人が実行し、次を見てから進めます。
- 出す先の店舗がPlusか。情報・配送・支払いステップに描画するtargetなら、Plusが前提になる
network_accessを使うなら、申請が通っているか- 3ページ・1ページ・Shop Payの3パターンで崩れないか
- チェックアウトエディタで、拡張を追加して位置を決めるのは店舗側の作業になる。デプロイしただけでは表示されない
本番での不具合調査には、ソースマップが使えます。Shopify CLIの3.70.0以降では、デプロイのコマンドが拡張のプロジェクトディレクトリ内の dist フォルダにソースマップを出力します。Chromeの開発者ツールで拡張のバンドルに紐づければ、元のソースでブレークポイントを置けます。
つまずきやすい点
- 拡張が管理画面の一覧に出ない:
shopify app devが動いているかを見ます。エディタに出るのは、開発サーバーが起動している間です - block targetの見え方が想定と違う: placement referenceの綴りと、そのtargetが対応する参照名かを確かめます
<div>を書いてしまう: 規約に「Shopify提供のweb componentだけ」と書いてあるか、targetに対応するコンポーネントを使っているかを確認します- Shop Payで見えない: Shopify Paymentsのテストモードと、エディタのInclude app in Shop Payが有効かを見ます
まとめ
checkout UI extensionは、画面の位置、使える部品、店舗プランが先に決まる拡張です。Claudeに任せる範囲は、targetと制約をCLAUDE.mdで固定し、ユニットテストで形を整えるところまでです。置き場所の見え方と、3つのチェックアウトの形は、開発ストアで人が見て判断します。デプロイを権限で止めておけば、Claudeの編集が本番へ届く経路は人の手に残ります。
画面側の拡張を作る前後の関連作業として、テーマの編集はClaude CodeでShopifyテーマ開発を進める手順、Shopify向けのスキル導入はClaude CodeでShopify AI Toolkitを使う方法にあります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- shopify.dev/docs/apps/build/checkout
- shopify.dev/docs/api/checkout-ui-extensions/latest
- shopify.dev/docs/api/checkout-ui-extensions/latest/targets
- shopify.dev/docs/api/checkout-ui-extensions/latest/web-components
- shopify.dev/docs/apps/build/checkout/test-checkout-ui-extensions
- shopify.dev/docs/apps/build/checkout/capabilities
- shopify.dev/docs/api/shopify-cli/app/app-dev
- code.claude.com/docs/en/common-workflows
- code.claude.com/docs/en/permissions