home / skills / toilahuongg / shopify-agents-kit / shopify-functions

shopify-functions skill

/.claude/skills/shopify-functions

This skill helps you implement Shopify Functions-backed backend logic in Rust or JavaScript, enabling low-latency WASM extensions for discounts, shipping, and

npx playbooks add skill toilahuongg/shopify-agents-kit --skill shopify-functions

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.4 KB
---
name: shopify-functions
description: Guide for creating backend logic using Shopify Functions (Discounts, Shipping, Payment, etc.). Covers WASM, Rust/JavaScript (Javy) implementation, and input queries.
---

# Shopify Functions

Shopify Functions differ from traditional backend apps. They are compiled to **WASM** and run on Shopify's infrastructure with extremely low latency. They are the successor to Shopify Scripts (Plus).

## 1. Concepts

-   **Deterministic**: Same input always equals same output. No random numbers, no network calls.
-   **Execution Time**: Strict limits (e.g., 5ms for logic).
-   **Languages**: Rust (First-class) or JavaScript (via Javy).

## 2. Structure

A function consists of:
1.  **`shopify.extension.toml`**: Configuration.
2.  **`input.graphql`**: Defines data sent *to* the function.
3.  **`src/run.rs` (or `.js`)**: The logic that returns an `Output`.

## 3. Workflow

1.  **Generate**: `shopify app generate extension --template product_discounts --name my-discount`
2.  **Input Query**: Modify `input.graphql` to request necessary data (Cart, Customer, etc.).
3.  **CodeGen**: Run `shopify app function typegen` to generate types from your GraphQL query.
4.  **Logic**: Implement the `run` function.
5.  **Build**: `npm run build` (compiles to `.wasm`).
6.  **Deploy**: `shopify app deploy`.

## 4. JS Example (Product Discount)

```javascript
// src/run.js
// @ts-check

/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const targets = input.cart.lines
    .filter(line => line.merchandise.product.hasAnyTag)
    .map(line => ({
      cartLine: {
        id: line.id
      }
    }));

  if (!targets.length) {
    return {
      discounts: [],
      discountApplicationStrategy: "FIRST",
    };
  }

  return {
    discounts: [
      {
        targets,
        value: {
          percentage: {
            value: "10.0"
          }
        },
        message: "VIP Discount"
      }
    ],
    discountApplicationStrategy: "FIRST",
  };
}
```

## 5. Configuration (GraphiQL)

You can't console.log in WASM. Use the **Shopify App Bridge** helper or the locally served **GraphiQL explorer** to debug inputs/outputs.

Run `npm run dev`, then open the highlighted GraphiQL URL in the terminal.

Overview

This skill guides you to create backend logic with Shopify Functions for discounts, shipping, payment, and other runtime extensions. It explains the WASM-based execution model, file structure, and the build/deploy workflow for Rust and JavaScript (Javy) implementations. The focus is on deterministic, low-latency business logic that runs on Shopify's infrastructure.

How this skill works

Shopify Functions are compiled to WebAssembly and executed within strict time and determinism constraints—no network calls or randomness. You define the data the function receives with an input GraphQL query, generate typed bindings, implement a run function that returns an Output, then compile to .wasm and deploy. Debugging is done via the GraphiQL explorer or App Bridge helpers rather than console logs in WASM.

When to use it

  • Apply cart- or product-level discounts that must run with minimal latency.
  • Customize shipping rate calculations or eligibility rules at checkout.
  • Implement payment-related validation or adjustments within Shopify’s execution window.
  • Replace legacy Shopify Scripts with modern, portable WASM functions.
  • Add promotion logic tied to cart lines, customer attributes, or product tags.

Best practices

  • Keep logic deterministic: avoid randomness, timers, and external network calls.
  • Limit execution complexity to meet strict time budgets (e.g., a few milliseconds).
  • Request only the fields you need via input.graphql to improve performance.
  • Run shopify app function typegen after changing input.graphql to keep types in sync.
  • Use local GraphiQL or App Bridge tools to inspect inputs and outputs for debugging.
  • Prefer Rust for performance-critical logic and Javy (JavaScript) for faster prototyping.

Example use cases

  • 10% VIP discount applied only to cart lines whose product has a VIP tag.
  • Custom shipping surcharge or free-shipping eligibility based on cart weight and destination.
  • Conditional payment adjustments for specific payment methods or fulfillment channels.
  • Tiered discounts where the first matching rule applies to maintain predictable pricing.
  • Product-specific promotions that target only selected merchandise IDs or variants.

FAQ

How do I debug a function if console.log doesn't work in WASM?

Use the locally served GraphiQL explorer (npm run dev) to inspect the generated input and output, or use Shopify App Bridge helpers to surface logs during development.

Should I use Rust or JavaScript (Javy)?

Choose Rust for maximum performance and safety; choose Javy (JavaScript) for faster iteration and familiarity. Both compile to WASM and must follow determinism and execution limits.