app-development
Skill48 starsChanged 9 months agoMITView on GitHub
Build Shopify apps with extensions and embedded experiences. Use this skill for creating new Shopify apps, adding app extensions, building admin interfaces, working with OAuth authentication, managing app configuration, and deploying to the Shopify App Store. Covers Shopify CLI for apps, Polaris UI, and app bridge.
- Reads credentials
1 other project uses a version of this.
Adopted by
Most recently taken up by
- lubusIN/frappe-skillstheir own version, first seen Nov 4, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- lubusIN/frappe-skills★ 68same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository7 other files it gives its agents.
- api-graphqlSkill
- checkout-customizationSkill
- cli-toolsSkill
- headless-hydrogenSkill
- liquid-templatingSkill
- shopify-functionsSkill
- theme-developmentSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Use this skill when:
- Distinctive: line 465
Add required app store assets
- Distinctive: line 486
Validate webhooks: - Verify HMAC signatures
- Distinctive: line 487
Test on dev stores: - Use development stores
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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
# - PHP2. 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.json3. Start Development
# Start dev server with tunnel
shopify app dev
# View app info
shopify app infoApp 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.ioAuthentication
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 listAdmin 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_IDApp 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.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

