dist/codex/shopify-commerce/skills/shopify-functions/SKILL.md
Build Shopify Functions — serverless WebAssembly extensions for discounts, delivery customization, payment customization, cart validation, cart transforms, and order routing. Use when extending Shopify's backend logic.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins shopify-functionsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch live docs:
https://shopify.dev/docs/apps/build/functions for Functions overviewsite:shopify.dev shopify functions input output for I/O schemassite:shopify.dev shopify functions api reference for function typesServerless extensions that run on Shopify's infrastructure:
| Type | Purpose | Example | |------|---------|---------| | Discount | Custom discount logic | Buy X get Y, tiered discounts | | Delivery customization | Modify shipping options | Rename, reorder, hide methods | | Payment customization | Modify payment methods | Hide, reorder, rename gateways | | Cart validation | Block or warn on cart conditions | Quantity limits, product combos | | Cart transform | Modify cart contents | Bundle expansion, auto-add items | | Fulfillment constraints | Control fulfillment behavior | Location priority, restrictions | | Order routing | Direct orders to locations | Closest warehouse, priority |
Functions receive structured JSON input and return structured JSON output:
{
"cart": {
"lines": [
{
"id": "gid://shopify/CartLine/1",
"quantity": 2,
"merchandise": {
"__typename": "ProductVariant",
"id": "gid://shopify/ProductVariant/123",
"product": {
"id": "gid://shopify/Product/456",
"hasAnyTag": true
}
},
"cost": {
"amountPerQuantity": { "amount": "29.99", "currencyCode": "USD" }
}
}
]
},
"discountNode": {
"metafield": {
"value": "{\"percentage\": 10}"
}
}
}
{
"discounts": [
{
"value": { "percentage": { "value": "10.0" } },
"targets": [
{ "productVariant": { "id": "gid://shopify/ProductVariant/123" } }
],
"message": "10% loyalty discount"
}
],
"discountApplicationStrategy": "FIRST"
}
extensions/my-discount/
├── src/
│ └── run.js # Function entry point
├── input.graphql # Defines what data the function receives
├── shopify.extension.toml # Extension configuration
└── package.json
api_version = "2025-01"
[[extensions]]
name = "My Discount"
handle = "my-discount"
type = "function"
[extensions.build]
command = "npm exec -- shopify app function build"
path = "dist/function.wasm"
[extensions.ui]
handle = "my-discount-ui"
[extensions.input.variables]
namespace = "my-app"
key = "discount-config"
Defines what Shopify data the function receives:
query Input {
cart {
lines {
id
quantity
merchandise {
... on ProductVariant {
id
product {
id
hasAnyTag(tags: ["vip"])
}
}
}
cost {
amountPerQuantity {
amount
currencyCode
}
}
}
}
discountNode {
metafield(namespace: "my-app", key: "discount-config") {
value
}
}
}
// src/run.js
export function run(input) {
const config = JSON.parse(input.discountNode.metafield?.value || '{}');
const percentage = config.percentage || 0;
const targets = input.cart.lines
.filter(line => line.merchandise?.product?.hasAnyTag)
.map(line => ({
productVariant: { id: line.merchandise.id }
}));
if (targets.length === 0) {
return { discounts: [], discountApplicationStrategy: "FIRST" };
}
return {
discounts: [{
value: { percentage: { value: String(percentage) } },
targets,
message: `${percentage}% VIP discount`,
}],
discountApplicationStrategy: "FIRST",
};
}
InstructionCountLimitExceededError if exceededshopify app function run locallyFetch the Shopify Functions documentation for exact I/O schemas, supported function types, and API version requirements before implementing.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.