Skip to content

Commit 756b017

Browse files
tizmagikclaude
andcommitted
feat: add 7 agent skills for Shopify app development
Skills focused on mental models, gotchas, and decision trees: - shopify-functions: Wasm compilation, declarative I/O, execution order - shopify-graphql-admin: Cost-based rate limiting, GIDs, userErrors, bulk ops - shopify-app-extensions: Sandbox model, web components not React, 64KB limit - shopify-checkout-ui: Preact Signals, static vs block targets, no CSS/DOM - shopify-webhooks: TOML vs API subscriptions, GDPR compliance, idempotency - shopify-app-auth: Token exchange vs OAuth, session vs access tokens - shopify-hydrogen: React Router not Next.js, Storefront API, Oxygen hosting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9575b23 commit 756b017

7 files changed

Lines changed: 705 additions & 0 deletions

File tree

skills/shopify-app-auth/SKILL.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
name: shopify-app-auth
3+
description: "Decision guide for Shopify app authentication: token exchange, OAuth, credentials, and token types"
4+
metadata:
5+
author: shopify
6+
version: "1.0"
7+
---
8+
9+
# Shopify App Authentication
10+
11+
## Decision Tree: Which Auth Flow?
12+
13+
```
14+
Is your app embedded in Shopify Admin?
15+
├─ YES → Token Exchange (recommended)
16+
│ App Bridge session token → exchange for access token
17+
│ No redirects. Seamless UX.
18+
19+
├─ NO (standalone web app) → Authorization Code Grant (OAuth)
20+
│ Standard OAuth 2.0 redirect flow.
21+
│ Merchant sees consent screen → redirect back with code → exchange for token.
22+
23+
└─ Backend-only service (no user interaction) → Client Credentials Grant
24+
App acts on its own behalf. No merchant/user context.
25+
Limited to app-level permissions only.
26+
```
27+
28+
## Critical Confusion: Session Tokens vs Access Tokens
29+
30+
These are NOT the same thing. Mixing them up is the #1 auth mistake.
31+
32+
| | Session Token | Access Token |
33+
|---|---|---|
34+
| **What** | Short-lived JWT from App Bridge | Credential for calling Shopify APIs |
35+
| **Issued by** | App Bridge (frontend) | Shopify OAuth endpoint (backend) |
36+
| **Lifetime** | ~1 minute | Hours (online) or indefinite (offline) |
37+
| **Used for** | Proving the request comes from an embedded app | `X-Shopify-Access-Token` header on API calls |
38+
| **Alone?** | Cannot call APIs directly | Yes, this is what calls APIs |
39+
40+
Flow: App Bridge issues session token → your backend receives it → exchanges it for an access token → uses access token to call Admin API.
41+
42+
## Online vs Offline Access Tokens
43+
44+
| | Online | Offline |
45+
|---|---|---|
46+
| **Scope** | Per-user (merchant staff) | Per-store |
47+
| **Lifetime** | Expires within 24 hours | Non-expiring (default) or expiring w/ refresh token |
48+
| **Use when** | You need user-specific permissions or audit trails | Background jobs, webhooks, most common case |
49+
| **Token exchange param** | `requested_token_type: urn:ietf:params:oauth:token-type:access_token` | `requested_token_type: urn:shopify:params:oauth:token-type:offline-access-token` |
50+
51+
**Most apps need offline tokens.** Use online only when you need to scope actions to a specific staff member.
52+
53+
## Embedded App Auth (Token Exchange)
54+
55+
1. Frontend: App Bridge automatically provides a session token
56+
2. Backend: Validate the session token on every incoming request
57+
3. Backend: POST to `https://{shop}.myshopify.com/admin/oauth/access_token` with:
58+
- `client_id`, `client_secret`
59+
- `grant_type: urn:ietf:params:oauth:grant-type:token-exchange`
60+
- `subject_token: <session_token>`
61+
- `subject_token_type: urn:ietf:params:oauth:token-type:id_token`
62+
4. Use returned access token in `X-Shopify-Access-Token` header
63+
64+
Shopify CLI templates (`shopify app generate`) handle this automatically.
65+
66+
## Scopes
67+
68+
- Declared in `shopify.app.toml` under `[access_scopes]`
69+
- Requested at install time; merchant grants consent
70+
- Changing scopes requires re-authorization (merchant sees consent screen again)
71+
- Example: `scopes = "read_products,write_orders"`
72+
73+
## HMAC Verification
74+
75+
Two contexts where you verify HMAC signatures:
76+
77+
- **Webhooks**: Verify `X-Shopify-Hmac-Sha256` header against raw request body using app client secret (HMAC-SHA256, base64-encoded). The `shopify-app-react-router` library's `authenticate.webhook()` handles this.
78+
- **OAuth install requests**: Verify `hmac` query parameter by sorting remaining params, computing HMAC-SHA256 with client secret.
79+
80+
Pitfall: You must use the **raw request body** for webhook HMAC. If middleware (e.g., `express.json()`) parses the body first, verification will fail.
81+
82+
## CLI Auth Note
83+
84+
`shopify auth login` opens a browser for human interaction. It cannot be automated or scripted in CI. For CI/CD, use environment variables (`SHOPIFY_CLI_PARTNERS_TOKEN`) or app-level client credentials.
85+
86+
## Documentation
87+
88+
- Overview: https://shopify.dev/docs/apps/build/authentication-authorization
89+
- Access tokens: https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens
90+
- Token exchange: https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/token-exchange
91+
- OAuth code grant: https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/authorization-code-grant
92+
- Session tokens: https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens
93+
- Scopes: https://shopify.dev/docs/api/usage/access-scopes
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
name: shopify-app-extensions
3+
description: "Mental models and gotchas for building Shopify app extensions across admin, checkout, POS, and customer account surfaces"
4+
metadata:
5+
author: shopify
6+
version: "1.0"
7+
---
8+
9+
# Shopify App Extensions
10+
11+
## The #1 Mistake: This Is NOT React DOM
12+
13+
Extensions render in an **isolated sandbox** via Remote DOM. There is no `document`, no `window`, no CSS, no arbitrary HTML. You cannot use `<div>`, `<span>`, `<iframe>`, or `<script>` tags.
14+
15+
**What you write** looks like JSX (Preact by default), but **what renders** are Shopify web components (`<s-button>`, `<s-banner>`, `<s-stack>`, etc.). These components inherit merchant brand settings. You cannot override or inject CSS.
16+
17+
```tsx
18+
// WRONG - agents generate this constantly
19+
import React from 'react';
20+
export default function MyExtension() {
21+
return <div className="my-class"><button onClick={handleClick}>Click</button></div>;
22+
}
23+
24+
// RIGHT - Shopify UI components only
25+
import { AdminAction, Button, Text } from '@shopify/ui-extensions-react/admin';
26+
export default function MyExtension() {
27+
return (
28+
<AdminAction title="My Action">
29+
<Text>Hello</Text>
30+
<Button onPress={handlePress}>Click</Button>
31+
</AdminAction>
32+
);
33+
}
34+
```
35+
36+
Key corrections:
37+
- `onClick` -> `onPress` (Shopify component API)
38+
- No `className`, no `style` props
39+
- No HTML elements — only Shopify components from `@shopify/ui-extensions-react/{surface}`
40+
- Preact is the default scaffolding, not React. The React-like API is a compatibility layer.
41+
42+
## Extension Surfaces — Decision Guide
43+
44+
| Surface | Use When | Target Prefix |
45+
|---------|----------|---------------|
46+
| **Admin** | CRUD workflows, resource management, merchant tools | `admin.` |
47+
| **Checkout** | Cart modifications, upsells, custom fields, payment logic | `purchase.checkout.` |
48+
| **Customer Accounts** | Post-purchase, order management, account self-service | `customer-account.` |
49+
| **POS** | In-store workflows, receipt customization | `pos.` |
50+
| **Online Store** | Theme app extensions (different model — Liquid blocks, not JS sandbox) | N/A (app blocks) |
51+
52+
Admin sub-types:
53+
- **Admin Action**: Modal triggered from resource pages (orders, products, customers). Use for transactional workflows.
54+
- **Admin Block**: Persistent card on resource pages. Use for contextual info display.
55+
- **Admin Print Action**: Document generation with preview/print APIs.
56+
57+
> Full target catalog: https://shopify.dev/docs/api/admin-extensions
58+
> Checkout targets: https://shopify.dev/docs/api/checkout-ui-extensions
59+
60+
## Hard Limits & Gotchas
61+
62+
### Bundle Size: 64KB Compressed
63+
The compiled extension bundle must be under **64KB compressed**. The CLI generates `.metafile.json` (esbuild) to help analyze what's eating your budget. Heavy libraries will blow this limit instantly.
64+
65+
### All Extensions Deploy Together
66+
`shopify app deploy` creates a single app version containing ALL extensions. You cannot deploy one extension independently. Removing an extension from the codebase does NOT auto-remove it from the app — explicit removal is required.
67+
68+
### Extension-Only Apps Use Custom Distribution Only
69+
Apps with no web server (extension-only) cannot be listed on the Shopify App Store. They must use custom distribution (direct install links).
70+
71+
### Some Extensions Require Review
72+
Certain extension types require Shopify review before release. You cannot deploy an app version containing reviewable extensions until approved.
73+
74+
### No Direct Network Access in Some Surfaces
75+
Checkout extensions cannot make arbitrary fetch calls. Use the `fetch` API provided by the extension API, which is proxied and restricted.
76+
77+
## Configuration: shopify.extension.toml
78+
79+
Every extension has a `shopify.extension.toml` in its directory. This defines the extension type, targets, metafields access, and capabilities.
80+
81+
```toml
82+
# Example: extensions/my-action/shopify.extension.toml
83+
api_version = "2025-01"
84+
[[targeting]]
85+
module = "./src/ActionExtension.tsx"
86+
target = "admin.product-details.action.render"
87+
```
88+
89+
> Per-type TOML schemas: https://shopify.dev/docs/apps/build/app-extensions
90+
91+
## CLI Workflow
92+
93+
```bash
94+
# Scaffold a new extension (interactive — picks type and surface)
95+
shopify app generate extension
96+
97+
# Start dev server with hot reload
98+
shopify app dev
99+
100+
# Deploy all extensions as a new app version
101+
shopify app deploy
102+
```
103+
104+
The CLI knows about these extension types (from source `specifications/`):
105+
`ui_extension`, `checkout_ui_extension`, `checkout_post_purchase`, `pos_ui_extension`, `function`, `theme`, `web_pixel_extension`, `flow_action`, `flow_trigger`, `flow_template`, `payments_app_extension`, `product_subscription`, `tax_calculation`, `editor_extension_collection`
106+
107+
## Documentation Pointers
108+
109+
- Extensions overview: https://shopify.dev/docs/apps/build/app-extensions
110+
- Admin extensions: https://shopify.dev/docs/apps/build/admin
111+
- Admin components API: https://shopify.dev/docs/api/admin-extensions/components
112+
- Checkout extensions: https://shopify.dev/docs/api/checkout-ui-extensions
113+
- Functions (backend logic): https://shopify.dev/docs/apps/build/functions
114+
- Extension TOML config: https://shopify.dev/docs/apps/build/app-extensions/configuration
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
name: shopify-checkout-ui
3+
description: "Constraints, gotchas, and mental model for building Shopify Checkout UI Extensions"
4+
metadata:
5+
author: shopify
6+
version: "1.0"
7+
---
8+
9+
# Shopify Checkout UI Extensions
10+
11+
## Mental Model
12+
13+
Checkout is the highest-stakes surface in commerce. Bugs here lose revenue. Extensions run in a **sandboxed Web Worker** -- there is no DOM, no `window`, no `document`, no `<script>` tags, no arbitrary HTML. Only Shopify-provided components render. The platform controls layout, accessibility, and branding. You write logic and declare UI; Shopify renders it natively.
14+
15+
## Components Are Web Components (`<s-*>`), Not React DOM
16+
17+
- All UI uses custom HTML elements: `<s-text>`, `<s-button>`, `<s-stack>`, `<s-grid>`, `<s-box>`, etc.
18+
- These are **not** React components. They follow standard web component property/attribute patterns.
19+
- Preact is the default framework. Use Preact hooks (`useState`, `useEffect`) and JSX with `<s-*>` elements.
20+
- In JSX, props that match an element property are set as properties; otherwise as attributes.
21+
- Event handlers use camelCase in JSX (`onClick`, `onInput`, `onChange`). Under the hood they become `addEventListener` calls.
22+
- Form inputs return **string** values, even for numeric fields. Multi-selects use a `values` prop (string array).
23+
- `<s-clickable>` is an escape hatch; prefer `<s-button>` and `<s-link>` first.
24+
25+
## Data Access: Preact Signals, Not Hooks
26+
27+
- The global `shopify` object exposes all checkout APIs.
28+
- APIs with a `value` property are **Preact Signals** (e.g., `shopify.shippingAddress.value`). Preact auto-re-renders when signals change.
29+
- Do NOT use React-style hooks for checkout data. Read from `shopify.*` signals directly.
30+
31+
## Static vs Block Targets
32+
33+
| Type | Behavior | Use When |
34+
|------|----------|----------|
35+
| **Static** | Tied to a core checkout feature (e.g., before/after shipping methods). Disappears when that feature is hidden. | Content is tightly coupled to a checkout step. |
36+
| **Block** | Merchant-positionable in the checkout editor. Always renders regardless of which features are active. | Content is independent (e.g., order notes, banners, loyalty points). |
37+
38+
- Register targets in `shopify.extension.toml` via `[[extensions.targeting]]`.
39+
- Block targets support multiple placements with placement references (`INFORMATION1`, `DELIVERY1`, `PAYMENT1`, etc.).
40+
- One extension can support multiple targets, but each target needs its own `module` file with a `default export`.
41+
42+
## 64 KB Compressed Bundle Limit
43+
44+
- Hard limit enforced at **deploy time** -- `shopify app deploy` will fail if exceeded.
45+
- This means: no large libraries, no bundled CSS frameworks, no heavy GraphQL clients with DOM dependencies.
46+
- Analyze with `shopify app build` and check output size. Keep dependencies minimal.
47+
48+
## Network Constraints
49+
50+
- **No arbitrary `fetch`** by default. Extensions run in a Web Worker with restricted network access.
51+
- **Storefront API**: Enable `api_access` capability in TOML. Use the `query()` helper or the global `fetch` (auto-authenticated). Available scopes are unauthenticated read-only (products, collections, metaobjects, selling plans).
52+
- **External network calls**: Require `network_access` capability AND Partner Dashboard approval. Your server **must** respond with `Access-Control-Allow-Origin: *` (CORS for any origin). The worker origin may change without notice.
53+
- **Prefer metafields over network calls**: Use Admin API to write metafields ahead of checkout, then read them via `appMetafields` in the extension. Faster, no external call needed.
54+
- Session tokens prove claim integrity but do NOT prove the request came from Shopify. Never expose sensitive endpoints that trust only a session token.
55+
56+
## No CSS Overrides
57+
58+
- Components inherit the merchant's brand settings automatically.
59+
- You **cannot** override or inject CSS. There is no style API.
60+
- Layout control is through component props only: `<s-stack>`, `<s-grid>`, `<s-box>` with `gap`, `padding`, `direction` props.
61+
- Scale uses middle-out naming: `small-300 < small-100 < base < large-100 < large-300`.
62+
- Responsive values use container query syntax: `@container (inline-size > 500px) large, small`.
63+
64+
## Other Critical Gotchas
65+
66+
- **Shopify Plus only**: Extensions in the information, shipping, and payment steps require Shopify Plus.
67+
- **`block_progress` capability**: Must be declared in TOML for validation that blocks checkout. Merchants can disable it -- check `extension.capabilities` at runtime and show a warning fallback.
68+
- **Settings**: Up to 20 fields per extension, configured in TOML. All settings are optional from the merchant's perspective -- code defensively.
69+
- **Metafields**: Declare needed metafields in TOML. Use `$app` prefix for app-owned metafields. Only specific resources supported: cart, customer, product, variant, shop, company, companyLocation, shopUser.
70+
- **No DOM APIs**: GraphQL clients like Apollo that use DOM APIs will not work. Use lightweight alternatives or the built-in `query()` helper.
71+
72+
## Documentation Pointers
73+
74+
| Topic | URL |
75+
|-------|-----|
76+
| Overview & getting started | https://shopify.dev/docs/api/checkout-ui-extensions |
77+
| Extension targets reference | https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview |
78+
| Web components (UI library) | https://shopify.dev/docs/api/checkout-ui-extensions/using-polaris-components |
79+
| Configuration (TOML) | https://shopify.dev/docs/api/checkout-ui-extensions/configuration |
80+
| Checkout APIs | https://shopify.dev/docs/api/checkout-ui-extensions/apis |
81+
| Tutorials & use cases | https://shopify.dev/docs/apps/build/checkout |
82+
| Bundle size analysis | https://shopify.dev/docs/apps/build/app-extensions#analyzing-bundle-size |
83+
| Figma UI kit | https://www.figma.com/community/file/1554582792754361051 |

0 commit comments

Comments
 (0)