Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build Shopify apps, extensions, themes using GraphQL Admin API, Shopify CLI, Polaris UI, and Liquid. TRIGGER: "shopify", "shopify app", "checkout extension", "admin extension", "POS extension", "shopify theme", "liquid template", "polaris", "shopify graphql", "shopify webhook", "shopify billing", "app subscription", "metafields", "shopify functions"
.claude/skills/davila7-shopify-development/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 178% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 53% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 141% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 240% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 217% | 0% |
Use this skill when the user asks about:
IF user wants to integrate external services OR build merchant tools OR charge for features: → Build an App (see references/app-development.md)
IF user wants to customize checkout OR add admin UI OR create POS actions OR implement discount rules: → Build an Extension (see references/extensions.md)
IF user wants to customize storefront design OR modify product/collection pages: → Build a Theme (see references/themes.md)
IF user needs both backend logic AND storefront UI: → Build App + Theme Extension combination
Install CLI:
bashnpm install -g @shopify/cli@latest
Create and run app:
bashshopify app init # Create new app shopify app dev # Start dev server with tunnel shopify app deploy # Build and upload to Shopify
Generate extension:
bashshopify app generate extension --type checkout_ui_extension shopify app generate extension --type admin_action shopify app generate extension --type admin_block shopify app generate extension --type pos_ui_extension shopify app generate extension --type function
Theme development:
bashshopify theme init # Create new theme shopify theme dev # Start local preview at localhost:9292 shopify theme pull --live # Pull live theme shopify theme push --development # Push to dev theme
Configure in shopify.app.toml:
toml[access_scopes] scopes = "read_products,write_products,read_orders,write_orders,read_customers"
Common scopes:
read_products, write_products - Product catalog accessread_orders, write_orders - Order managementread_customers, write_customers - Customer dataread_inventory, write_inventory - Stock levelsread_fulfillments, write_fulfillments - Order fulfillmentgraphqlquery GetProducts($first: Int!, $query: String) { products(first: $first, query: $query) { edges { node { id title handle status variants(first: 5) { edges { node { id price inventoryQuantity } } } } } pageInfo { hasNextPage endCursor } } }
graphqlquery GetOrders($first: Int!) { orders(first: $first) { edges { node { id name createdAt displayFinancialStatus totalPriceSet { shopMoney { amount currencyCode } } } } } }
graphqlmutation SetMetafields($metafields: [MetafieldsSetInput!]!) { metafieldsSet(metafields: $metafields) { metafields { id namespace key value } userErrors { field message } } }
Variables example:
json{ "metafields": [ { "ownerId": "gid://shopify/Product/123", "namespace": "custom", "key": "care_instructions", "value": "Handle with care", "type": "single_line_text_field" } ] }
tsximport { reactExtension, BlockStack, TextField, Checkbox, useApplyAttributeChange, } from "@shopify/ui-extensions-react/checkout"; export default reactExtension("purchase.checkout.block.render", () => ( <GiftMessage /> )); function GiftMessage() { const [isGift, setIsGift] = useState(false); const [message, setMessage] = useState(""); const applyAttributeChange = useApplyAttributeChange(); useEffect(() => { if (isGift && message) { applyAttributeChange({ type: "updateAttribute", key: "gift_message", value: message, }); } }, [isGift, message]); return ( <BlockStack spacing="loose"> <Checkbox checked={isGift} onChange={setIsGift}> This is a gift </Checkbox> {isGift && ( <TextField label="Gift Message" value={message} onChange={setMessage} multiline={3} /> )} </BlockStack> ); }
liquid{% comment %} Product Card Snippet {% endcomment %} <div class="product-card"> <a href="{{ product.url }}"> {% if product.featured_image %} <img src="{{ product.featured_image | img_url: 'medium' }}" alt="{{ product.title | escape }}" loading="lazy" > {% endif %} <h3>{{ product.title }}</h3> <p class="price">{{ product.price | money }}</p> {% if product.compare_at_price > product.price %} <p class="sale-badge">Sale</p> {% endif %} </a> </div>
In shopify.app.toml:
toml[webhooks] api_version = "2026-01" [[webhooks.subscriptions]] topics = ["orders/create", "orders/updated"] uri = "/webhooks/orders" [[webhooks.subscriptions]] topics = ["products/update"] uri = "/webhooks/products" # GDPR mandatory webhooks (required for app approval) [webhooks.privacy_compliance] customer_data_request_url = "/webhooks/gdpr/data-request" customer_deletion_url = "/webhooks/gdpr/customer-deletion" shop_deletion_url = "/webhooks/gdpr/shop-deletion"
pageInfo.endCursorimg_url filterIF you see rate limit errors: → Implement exponential backoff retry logic → Switch to bulk operations for large datasets → Monitor X-Shopify-Shop-Api-Call-Limit header
IF authentication fails: → Verify the access token is still valid → Check that all required scopes were granted → Ensure OAuth flow completed successfully
IF extension is not appearing: → Verify the extension target is correct → Check that extension is published via shopify app deploy → Confirm the app is installed on the test store
IF webhook is not receiving events: → Verify the webhook URL is publicly accessible → Check HMAC signature validation logic → Review webhook logs in Partner Dashboard
IF GraphQL query fails: → Validate query against schema (use GraphiQL explorer) → Check for deprecated fields in error message → Verify you have required access scopes
For detailed implementation guides, read these files:
references/app-development.md - OAuth authentication flow, GraphQL mutations for products/orders/billing, webhook handlers, billing API integrationreferences/extensions.md - Checkout UI components, Admin UI extensions, POS extensions, Shopify Functions for discounts/payment/deliveryreferences/themes.md - Liquid syntax reference, theme directory structure, sections and snippets, common patternsscripts/shopify_init.py - Interactive project scaffolding. Run: python scripts/shopify_init.pyscripts/shopify_graphql.py - GraphQL utilities with query templates, pagination, rate limiting. Import: from shopify_graphql import ShopifyGraphQLAPI Version: 2026-01 (quarterly releases, 12-month deprecation window)
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 8,653 | 10,264 | +19% | 1 | 1 | 0% | 1,398 | 3,880 | +178% | 0 | 0 | — |
case-02 | fail→pass | 11,302 | 5,515 | -51% | 1 | 1 | 0% | 2,118 | 3,248 | +53% | 0 | 0 | — |
case-03 | fail→pass | 8,195 | 5,670 | -31% | 1 | 1 | 0% | 1,283 | 3,096 | +141% | 0 | 0 | — |
case-04 | fail→pass | 5,157 | 2,865 | -44% | 1 | 1 | 0% | 741 | 2,522 | +240% | 0 | 0 | — |
case-05 | pass→pass | 10,730 | 4,619 | -57% | 1 | 1 | 0% | 1,905 | 2,909 | +53% | 0 | 0 | — |
case-06 | fail→pass | 5,571 | 4,520 | -19% | 1 | 1 | 0% | 912 | 2,888 | +217% | 0 | 0 | — |
case-07 | pass→pass | 4,819 | 3,568 | -26% | 1 | 1 | 0% | 744 | 2,622 | +252% | 0 | 0 | — |
case-08 | fail→pass | 6,378 | 3,609 | -43% | 1 | 1 | 0% | 950 | 2,637 | +178% | 0 | 0 | — |
case-09 | pass→pass | 14,188 | 8,589 | -39% | 1 | 1 | 0% | 2,405 | 3,668 | +53% | 0 | 0 | — |
case-10 | pass→pass | 6,428 | 5,761 | -10% | 1 | 1 | 0% | 1,181 | 3,078 | +161% | 0 | 0 | — |
case-11 | fail→pass | 6,175 | 5,863 | -5% | 1 | 1 | 0% | 1,040 | 3,239 | +211% | 0 | 0 | — |
case-12 | pass→pass | 4,592 | 3,441 | -25% | 1 | 1 | 0% | 742 | 2,622 | +253% | 0 | 0 | — |
case-13 | pass→pass | 11,377 | 6,021 | -47% | 1 | 1 | 0% | 2,001 | 3,189 | +59% | 0 | 0 | — |
case-14 | pass→pass | 5,131 | 2,524 | -51% | 1 | 1 | 0% | 895 | 2,494 | +179% | 0 | 0 | — |
case-15 | pass→pass | 4,505 | 2,612 | -42% | 1 | 1 | 0% | 640 | 2,536 | +296% | 0 | 0 | — |
case-16 | fail→pass | 14,665 | 5,359 | -63% | 1 | 1 | 0% | 1,553 | 2,962 | +91% | 0 | 0 | — |
case-17 | fail→fail | 8,937 | 5,247 | -41% | 1 | 1 | 0% | 1,421 | 3,029 | +113% | 0 | 0 | — |
case-18 | fail→pass | 13,921 | 12,623 | -9% | 1 | 1 | 0% | 2,277 | 4,318 | +90% | 0 | 0 | — |
case-19 | pass→pass | 5,941 | 7,025 | +18% | 1 | 1 | 0% | 1,036 | 3,373 | +226% | 0 | 0 | — |
case-20 | pass→pass | 11,768 | 7,396 | -37% | 1 | 1 | 0% | 2,236 | 3,543 | +58% | 0 | 0 | — |
case-21 | pass→pass | 7,967 | 4,837 | -39% | 1 | 1 | 0% | 1,482 | 2,985 | +101% | 0 | 0 | — |
case-22 | pass→pass | 5,135 | 5,373 | +5% | 1 | 1 | 0% | 910 | 2,900 | +219% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +41 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.