app-development
1
总安装量
1
周安装量
#49017
全站排名
安装命令
npx skills add https://github.com/dragnoir/shopify-agent-skills --skill app-development
Agent 安装分布
amp
1
openclaw
1
opencode
1
kimi-cli
1
codex
1
github-copilot
1
Skill 文档
Shopify App Development
When to use this skill
Use this skill when:
- Creating a new Shopify app
- Building app extensions (admin, checkout, etc.)
- Embedding UI in the Shopify admin
- Working with OAuth and app authentication
- Managing webhooks and app events
- Using Shopify Polaris UI components
- Deploying apps to the Shopify App Store
App Types
Public Apps
- Distributed via the Shopify App Store
- Available to all merchants
- Require app review process
Custom Apps
- Built for a single merchant/organization
- Direct installation (no app store)
- Simpler distribution
Sales Channel Apps
- Integrate a sales channel with Shopify
- Appear in the Shopify admin’s sales channels
Getting Started
1. Create a New App
# Initialize a new app
shopify app init
# Choose a template:
# - Remix (recommended)
# - Node
# - Ruby
# - PHP
2. Project Structure (Remix Template)
my-app/
âââ app/
â âââ routes/
â â âââ app._index.jsx # Main app page
â â âââ app.products.jsx # Products page
â â âââ webhooks.jsx # Webhook handlers
â âââ shopify.server.js # Shopify API config
â âââ root.jsx # Root layout
âââ extensions/ # App extensions
âââ prisma/ # Database schema
âââ shopify.app.toml # App configuration
âââ package.json
3. Start Development
# Start dev server with tunnel
shopify app dev
# View app info
shopify app info
App Configuration
shopify.app.toml
name = "My App"
client_id = "your-api-key"
[access_scopes]
scopes = "read_products, write_products, read_orders"
[webhooks]
api_version = "2025-01"
[[webhooks.subscriptions]]
topics = ["products/create", "orders/create"]
uri = "/webhooks"
[app_proxy]
url = "https://myapp.example.com/proxy"
subpath = "app-proxy"
prefix = "apps"
Environment Variables
SHOPIFY_API_KEY=your-api-key
SHOPIFY_API_SECRET=your-api-secret
SCOPES=read_products,write_products
HOST=https://your-tunnel-url.ngrok.io
Authentication
Session Tokens (Recommended)
Apps embedded in the Shopify admin use session tokens:
// app/shopify.server.js
import "@shopify/shopify-app-remix/adapters/node";
import { AppDistribution, shopifyApp } from "@shopify/shopify-app-remix/server";
const shopify = shopifyApp({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET,
scopes: process.env.SCOPES?.split(","),
appUrl: process.env.SHOPIFY_APP_URL,
distribution: AppDistribution.AppStore,
});
export default shopify;
Admin API Access
import { authenticate } from "../shopify.server";
export async function loader({ request }) {
const { admin } = await authenticate.admin(request);
const response = await admin.graphql(`
query {
products(first: 10) {
nodes {
id
title
handle
}
}
}
`);
const data = await response.json();
return json({ products: data.data.products.nodes });
}
App Extensions
Extension Types
| Type | Description |
|---|---|
| Admin UI | Embedded UI in Shopify admin |
| Admin Action | Action buttons in admin |
| Admin Block | Content blocks in admin |
| Checkout UI | Custom checkout experience |
| Theme App | Integrate with merchant themes |
| POS UI | Point of Sale extensions |
| Flow | Workflow automation |
| Functions | Backend logic (discounts, shipping) |
Create an Extension
# Generate an extension
shopify app generate extension
# Choose extension type from the list
Admin UI Extension Example
// extensions/admin-block/src/BlockExtension.jsx
import {
reactExtension,
useApi,
AdminBlock,
Text,
BlockStack,
InlineStack,
Button,
} from "@shopify/ui-extensions-react/admin";
export default reactExtension("admin.product-details.block.render", () => (
<ProductBlock />
));
function ProductBlock() {
const { data } = useApi();
return (
<AdminBlock title="Custom Block">
<BlockStack>
<Text>Product ID: {data.selected[0]?.id}</Text>
<InlineStack>
<Button onPress={() => console.log("clicked")}>Action</Button>
</InlineStack>
</BlockStack>
</AdminBlock>
);
}
Theme App Extension
// extensions/theme-block/blocks/product-rating.liquid
{% schema %}
{
"name": "Product Rating",
"target": "section",
"settings": [
{
"type": "product",
"id": "product",
"label": "Product"
}
]
}
{% endschema %}
<div class="product-rating">
<app-block-rating product-id="{{ block.settings.product.id }}">
</app-block-rating>
</div>
{% javascript %}
// Your JavaScript here
{% endjavascript %}
{% stylesheet %}
.product-rating {
padding: 16px;
}
{% endstylesheet %}
Polaris UI Components
Basic Layout
import {
Page,
Layout,
Card,
Text,
BlockStack,
InlineStack,
Button,
TextField,
Select,
Banner,
List,
} from "@shopify/polaris";
export default function ProductPage() {
return (
<Page title="Products" primaryAction={{ content: "Create product" }}>
<Layout>
<Layout.Section>
<Card>
<BlockStack gap="300">
<Text as="h2" variant="headingMd">
Product Details
</Text>
<TextField label="Title" value={title} onChange={setTitle} />
<Select
label="Status"
options={[
{ label: "Active", value: "active" },
{ label: "Draft", value: "draft" },
]}
value={status}
onChange={setStatus}
/>
</BlockStack>
</Card>
</Layout.Section>
<Layout.Section variant="oneThird">
<Card>
<Text as="h2" variant="headingMd">
Summary
</Text>
</Card>
</Layout.Section>
</Layout>
</Page>
);
}
Data Table
import { IndexTable, Card, Text } from "@shopify/polaris";
function ProductTable({ products }) {
const rowMarkup = products.map((product, index) => (
<IndexTable.Row id={product.id} key={product.id} position={index}>
<IndexTable.Cell>
<Text variant="bodyMd" fontWeight="bold">
{product.title}
</Text>
</IndexTable.Cell>
<IndexTable.Cell>{product.status}</IndexTable.Cell>
<IndexTable.Cell>{product.inventory}</IndexTable.Cell>
</IndexTable.Row>
));
return (
<Card>
<IndexTable
itemCount={products.length}
headings={[
{ title: "Product" },
{ title: "Status" },
{ title: "Inventory" },
]}
selectable={false}
>
{rowMarkup}
</IndexTable>
</Card>
);
}
Webhooks
Register Webhooks
# shopify.app.toml
[[webhooks.subscriptions]]
topics = ["products/create", "products/update", "products/delete"]
uri = "/webhooks"
Handle Webhooks
// app/routes/webhooks.jsx
import { authenticate } from "../shopify.server";
export async function action({ request }) {
const { topic, shop, payload } = await authenticate.webhook(request);
switch (topic) {
case "PRODUCTS_CREATE":
console.log("Product created:", payload.id);
// Handle product creation
break;
case "PRODUCTS_UPDATE":
console.log("Product updated:", payload.id);
// Handle product update
break;
case "ORDERS_CREATE":
console.log("Order created:", payload.id);
// Handle new order
break;
}
return new Response("OK", { status: 200 });
}
Metafields
Reading Metafields
const response = await admin.graphql(`
query {
product(id: "gid://shopify/Product/123456") {
metafield(namespace: "custom", key: "care_instructions") {
value
type
}
metafields(first: 10) {
nodes {
namespace
key
value
type
}
}
}
}
`);
Writing Metafields
const response = await admin.graphql(
`
mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields {
key
value
}
userErrors {
field
message
}
}
}
`,
{
variables: {
metafields: [
{
ownerId: "gid://shopify/Product/123456",
namespace: "custom",
key: "care_instructions",
value: "Machine wash cold",
type: "single_line_text_field",
},
],
},
},
);
Deployment
Deploy to Shopify
# Deploy app and extensions
shopify app deploy
# Deploy specific version
shopify app versions list
shopify app release --version VERSION_ID
App Store Submission
- Complete Partner Dashboard app listing
- Add required app store assets
- Submit for review
- Address review feedback
- Publish approved app
CLI Commands Reference
| Command | Description |
|---|---|
shopify app init |
Create new app |
shopify app dev |
Start dev server |
shopify app deploy |
Deploy app |
shopify app generate extension |
Create extension |
shopify app info |
View app info |
shopify app env show |
Show environment |
shopify app versions list |
List versions |
Best Practices
- Use session tokens – More secure than API keys
- Handle rate limits – Implement retry logic
- Validate webhooks – Verify HMAC signatures
- Test on dev stores – Use development stores
- Follow Polaris guidelines – Consistent UX
- Monitor app health – Track errors and performance
Resources
For backend functions, see the shopify-functions skill. For checkout customization, see the checkout-customization skill.