最初のShopifyアプリ
このレッスンでは、ゼロから開発ストアにインストールされた実行中のShopifyアプリまでを構築します。Shopify CLIを使ってプロジェクトをスキャフォールドし、ファイル構造を理解し、開発サーバーを起動し、Claude Codeを使って最初の機能を構築します。
shopify app initでスキャフォールド
Shopify CLIは、認証、データベース、UIがすでに構成された完全なアプリプロジェクトを生成します。以下を実行してください:
# 新しいShopifyアプリを作成
cd ~/shopify-projects
shopify app init
# CLIが以下のプロンプトを表示します:
# ? Your app project name: masterclass-app
# ? Get started building your app:
# > Start with Remix (recommended)
# Start with a blank extension-only app
# Start with a template
Start with Remixを選択してください。これはShopifyが推奨するフレームワークであり、コース全体を通して使用します。
# スキャフォールド完了後
cd masterclass-app
ShopifyがRemixを推奨アプリフレームワークとして選んだのは、そのサーバーサイドレンダリングモデル、ネストされたルーティング、優れたデータ読み込みパターンのためです。RemixのactionとloaderはShopifyのOAuthフローとAPI呼び出しに自然にマッピングされます。Shopify Remixテンプレートには、認証、セッション管理、App Bridgeの統合がすぐに含まれています。
プロジェクト構造の理解
スキャフォールドされたプロジェクトには、理解しておくべき特定の構造があります。各ディレクトリは明確な目的を持っています:
masterclass-app/
├── app/ # Remixアプリケーション
│ ├── routes/ # ページルート(ファイルベースルーティング)
│ │ ├── app._index.jsx # メインアプリページ(認証後)
│ │ ├── app.jsx # ナビゲーション付きアプリレイアウト
│ │ ├── auth.$.jsx # OAuthコールバックハンドラー
│ │ ├── auth.login/ # ログインページ
│ │ │ ├── route.jsx
│ │ │ └── login.css
│ │ └── webhooks.jsx # Webhookハンドラー
│ ├── shopify.server.js # Shopify APIクライアントの設定
│ ├── db.server.js # データベース接続(SQLite)
│ └── entry.server.jsx # Remixサーバーエントリ
├── extensions/ # Shopifyエクステンション(UI、Functionsなど)
├── prisma/
│ └── schema.prisma # データベーススキーマ
├── public/ # 静的アセット
├── shopify.app.toml # アプリ構成
├── shopify.web.toml # Webサーバー構成
├── package.json
├── remix.config.js
└── .env # 環境変数(自動生成)
主要ファイルの説明
shopify.app.toml -- アプリマニフェスト。アプリの名前、スコープ(権限)、エクステンション構成を定義します:
name = "masterclass-app"
client_id = "your-client-id"
application_url = "https://your-tunnel.trycloudflare.com"
embedded = true
[access_scopes]
scopes = "write_products,read_orders"
[webhooks]
api_version = "2026-04"
app/shopify.server.js -- Shopify APIクライアント。このファイルは認証を設定し、API呼び出しのためのメソッドを提供します:
import "@shopify/shopify-app-remix/adapters/node";
import {
ApiVersion,
AppDistribution,
shopifyApp,
} from "@shopify/shopify-app-remix/server";
import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma";
import prisma from "./db.server";
const shopify = shopifyApp({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
apiVersion: ApiVersion.April26,
scopes: process.env.SCOPES?.split(","),
appUrl: process.env.SHOPIFY_APP_URL || "",
authPathPrefix: "/auth",
sessionStorage: new PrismaSessionStorage(prisma),
distribution: AppDistribution.AppStore,
future: {
unstable_newEmbeddedAuthStrategy: true,
},
});
export default shopify;
export const apiVersion = ApiVersion.April26;
export const addDocumentResponseHeaders = shopify.addDocumentResponseHeaders;
export const authenticate = shopify.authenticate;
export const unauthenticated = shopify.unauthenticated;
export const login = shopify.login;
export const registerWebhooks = shopify.registerWebhooks;
export const sessionStorage = shopify.sessionStorage;
app/routes/app._index.jsx -- アプリのメインページ。Shopify Admin内に埋め込みアプリとしてレンダリングされます。
開発サーバーの起動
Shopify CLIのdevコマンドでアプリを起動します:
shopify app dev
この1つのコマンドが驚くほど多くの作業を行います:
CLIは以下を行います:
localhost:3000でRemix開発サーバーを起動- HTTPSアクセスのためのCloudflareトンネルを作成
- パートナーダッシュボードのアプリURLを更新
- 開発ストアにアプリをインストールするためにブラウザを開く
初回実行時、CLIはデータベーステーブルの作成、OAuth認証情報の生成、トンネルのセットアップを行います。以降の実行ははるかに高速です。
開発ストアへのインストール
CLIがブラウザを開くと、Shopifyの認証画面が表示されます。アプリをインストールをクリックして要求された権限を付与します。インストール後、アプリのメインページがShopify Admin内に埋め込まれて表示されます。
「Nice work on building a Shopify app」というメッセージとサンプルコンテンツを含むShopify Polaris UIのページが表示されるはずです。
Claude Codeで最初の機能を構築
ここからがエキサイティングな部分です。Claude Codeを使って実際の機能を構築します。ストア内の商品の総数とステータスの内訳を表示する商品カウントダッシュボードを追加します。
プロジェクトディレクトリでClaude Codeを開きます:
cd ~/shopify-projects/masterclass-app
claude
Claude Codeに以下のプロンプトを入力します:
Update the main app page (app/routes/app._index.jsx) to show a product
dashboard. Use the Shopify Admin GraphQL API to fetch the total number
of products and break them down by status (active, draft, archived).
Display the data using Polaris Cards and Layout components. Include a
loading state.
Claude Codeは以下を行います:
- 既存の
app._index.jsxファイルを読んで現在の構造を理解する - Shopify Admin APIを呼び出すRemixの
loader関数を記述する - ステータス別の商品数を取得するGraphQLクエリを使用する
- Polaris
Card、Layout、TextコンポーネントでレンダリングするJSXを更新する - ローディング状態とエラー状態を追加する
結果のコードは以下のようになります:
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import {
Page,
Layout,
Card,
BlockStack,
Text,
InlineGrid,
} from "@shopify/polaris";
import { authenticate } from "../shopify.server";
export const loader = async ({ request }) => {
const { admin } = await authenticate.admin(request);
const response = await admin.graphql(`
{
activeCount: productsCount(query: "status:active") {
count
}
draftCount: productsCount(query: "status:draft") {
count
}
archivedCount: productsCount(query: "status:archived") {
count
}
totalCount: productsCount {
count
}
}
`);
const data = await response.json();
return json({
products: {
total: data.data.totalCount.count,
active: data.data.activeCount.count,
draft: data.data.draftCount.count,
archived: data.data.archivedCount.count,
},
});
};
export default function Index() {
const { products } = useLoaderData();
return (
<Page title="Product Dashboard">
<Layout>
<Layout.Section>
<InlineGrid columns={4} gap="400">
<Card>
<BlockStack gap="200">
<Text variant="headingSm">Total Products</Text>
<Text variant="heading2xl">{products.total}</Text>
</BlockStack>
</Card>
<Card>
<BlockStack gap="200">
<Text variant="headingSm">Active</Text>
<Text variant="heading2xl" tone="success">
{products.active}
</Text>
</BlockStack>
</Card>
<Card>
<BlockStack gap="200">
<Text variant="headingSm">Draft</Text>
<Text variant="heading2xl" tone="caution">
{products.draft}
</Text>
</BlockStack>
</Card>
<Card>
<BlockStack gap="200">
<Text variant="headingSm">Archived</Text>
<Text variant="heading2xl" tone="subdued">
{products.archived}
</Text>
</BlockStack>
</Card>
</InlineGrid>
</Layout.Section>
</Layout>
</Page>
);
}
ファイルを保存してブラウザを確認してください。Remixは自動的にホットリロードするので、商品ダッシュボードが表示されるはずです。
何が起きたか注目してください。機能を平易な英語で説明しただけで、Claude CodeがGraphQLクエリ、Remix loader、Polaris UIを書きました。既存のshopify.server.jsファイルを読んでauthenticate.admin(request)を使うべきことを知っていました。Shopify Admin APIを理解しているためproductsCountを使うことを知っていました。これがagentic codingの実践です。
チェックポイント
次に進む前に確認してください:
-
shopify app devがエラーなしで起動する - アプリが開発ストアにインストールされている
- 商品ダッシュボードにストアの実データが表示されている
- Claude Codeを使ってアプリの変更に成功した
「App not loaded」エラー:localhostではなく、CloudflareトンネルのURLを使用していることを確認してください。トンネルはshopify app devによって自動的に作成されます。
「Access denied」エラー:shopify.app.tomlのスコープにread_productsが含まれているか確認してください。shopify app dev --resetを実行して再認証してください。
商品カウントが空:開発ストアに商品がない場合は、Shopify Adminで「商品を追加」をクリックしてテスト商品をいくつか作成するか、一括インポート機能を使用してください。
学んだこと
このレッスンでは以下を学びました:
- Shopify CLIを使ってShopify Remixアプリをスキャフォールドした
- プロジェクト構造と主要な構成ファイルを理解した
- トンネリングとホットリロードで開発サーバーを実行した
- 開発ストアにアプリをインストールした
- Claude Codeを使って商品ダッシュボード機能を構築した
次のレッスンでは、Shopifyパートナーエコシステムを探索し、Shopify開発のビジネス面を理解します。