Help us improve
Share bugs, ideas, or general feedback.
From shopify-pack
Configures Shopify apps for development, staging, and production with separate stores, API credentials, CLI toml files, and secret management.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin shopify-packHow this skill is triggered — by the user, by Claude, or both
Slash command
/shopify-pack:shopify-multi-env-setupThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Configure Shopify apps with isolated development, staging, and production environments. Each environment uses a separate Shopify app instance, development store, and credentials.
Sets up local Shopify app development with Shopify CLI scaffolding, ngrok tunneling for webhooks, hot reload, and Vitest testing.
Sets up Shopify dev environment: CLI install/auth, Partner account, dev stores, env vars, structures for Remix apps, Liquid themes, Hydrogen storefronts.
Guides Shopify CLI usage for validating app/extension configs (shopify.app.toml), running store workflows (auth/execute), inventory/product changes by handle/SKU, and troubleshooting setup/auth/upgrade.
Share bugs, ideas, or general feedback.
Configure Shopify apps with isolated development, staging, and production environments. Each environment uses a separate Shopify app instance, development store, and credentials.
Create one app per environment in your Partner Dashboard:
| Environment | App Name | Store | Purpose |
|---|---|---|---|
| Development | My App (Dev) | dev-store.myshopify.com | Local development |
| Staging | My App (Staging) | staging-store.myshopify.com | Pre-prod testing |
| Production | My App | live-store.myshopify.com | Live traffic |
Each app gets its own API_KEY, API_SECRET, and ACCESS_TOKEN.
# .env.development (git-ignored)
SHOPIFY_API_KEY=dev_api_key
SHOPIFY_API_SECRET=dev_api_secret
SHOPIFY_STORE=dev-store.myshopify.com
SHOPIFY_ACCESS_TOKEN=shpat_dev_token
SHOPIFY_APP_URL=https://localhost:3000
SHOPIFY_API_VERSION=2024-10
NODE_ENV=development
# .env.staging (git-ignored)
SHOPIFY_API_KEY=staging_api_key
SHOPIFY_API_SECRET=staging_api_secret
SHOPIFY_STORE=staging-store.myshopify.com
SHOPIFY_ACCESS_TOKEN=shpat_staging_token
SHOPIFY_APP_URL=https://staging.your-app.com
SHOPIFY_API_VERSION=2024-10
NODE_ENV=staging
# .env.production (never on disk — use secret manager)
# All values stored in Vault / AWS Secrets Manager / GCP Secret Manager
# shopify.app.dev.toml — development config
name = "My App (Dev)"
client_id = "dev_api_key"
[access_scopes]
scopes = "read_products,write_products,read_orders,write_orders"
[auth]
redirect_urls = ["https://localhost/auth/callback"]
[webhooks]
api_version = "2024-10"
# Switch between app configs
shopify app config use shopify.app.dev.toml
shopify app dev
shopify app config use shopify.app.toml # production
shopify app deploy
// src/config.ts
interface ShopifyEnvConfig {
apiKey: string;
apiSecret: string;
appUrl: string;
apiVersion: string;
scopes: string[];
environment: "development" | "staging" | "production";
debug: boolean;
sessionStorageType: "memory" | "sqlite" | "postgresql";
}
function getConfig(): ShopifyEnvConfig {
const env = (process.env.NODE_ENV || "development") as ShopifyEnvConfig["environment"];
const base = {
apiKey: process.env.SHOPIFY_API_KEY!,
apiSecret: process.env.SHOPIFY_API_SECRET!,
appUrl: process.env.SHOPIFY_APP_URL!,
apiVersion: process.env.SHOPIFY_API_VERSION || "2024-10",
scopes: (process.env.SHOPIFY_SCOPES || "read_products").split(","),
environment: env,
};
const envOverrides: Record<string, Partial<ShopifyEnvConfig>> = {
development: {
debug: true,
sessionStorageType: "sqlite",
},
staging: {
debug: false,
sessionStorageType: "postgresql",
},
production: {
debug: false,
sessionStorageType: "postgresql",
},
};
return { ...base, ...envOverrides[env] } as ShopifyEnvConfig;
}
// Prevent dangerous operations outside production
function requireProduction(operation: string): void {
if (process.env.NODE_ENV !== "production") {
console.log(`[DEV] ${operation} — would execute in production`);
return;
}
}
function blockInProduction(operation: string): void {
if (process.env.NODE_ENV === "production") {
throw new Error(
`Operation "${operation}" is blocked in production. ` +
`Use staging or development environment.`
);
}
}
// Example: prevent test data seeding in production
async function seedTestProducts() {
blockInProduction("seedTestProducts");
// ... seeding logic
}
// Example: ensure billing only runs in production
async function activateBilling(session: Session) {
requireProduction("activateBilling");
// ... billing logic
}
| Issue | Cause | Solution |
|---|---|---|
| Wrong store in dev | Using prod .env | Verify SHOPIFY_STORE in your .env file |
| OAuth fails on staging | Wrong redirect URL | Update redirect_urls in staging app config |
| Webhooks not received | URL mismatch | Each environment needs its own webhook URLs |
| Production guard triggered | Wrong NODE_ENV | Set NODE_ENV correctly in deployment platform |
# Create a development store from Partner Dashboard
# Partners > Stores > Add store > Development store
# Install your dev app on the dev store
shopify app dev --store=dev-store.myshopify.com
# Populate test data
shopify populate products --count=25
shopify populate orders --count=10
shopify populate customers --count=20
For observability setup, see shopify-observability.