dist/codex/saleor-commerce/skills/graphql-dev/SKILL.md
Write GraphQL queries, mutations, and subscriptions — fragments, code generation, TypedDocumentNode, variables, error handling, and client setup. Use when writing GraphQL code for Saleor.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins graphql-devInstall 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:
site:docs.saleor.io api-reference for the current Saleor GraphQL schema and API referencesite:the-guild.dev graphql-codegen for GraphQL Code Generator configuration and pluginssite:graphql.org learn for GraphQL specification fundamentalssaleor GraphQL TypedDocumentNode urql for typed client patternshttps://docs.saleor.io/docs/developer/api-conventions for Saleor-specific GraphQL conventions| Operation | Purpose | Saleor Example | |-----------|---------|----------------| | Query | Read data | Fetch products, orders, categories | | Mutation | Write data | Create checkout, update product, complete order | | Subscription | Real-time events | Webhook subscription payloads |
/graphql/ endpointerrors arraychannel argument or HTTP header| Fragment Use Case | Benefit | |-------------------|---------| | Product fields | Reuse across product list, detail, and search queries | | Address fields | Share between checkout, order, and customer queries | | Money fields | Consistent currency/amount selection | | Error fields | Uniform error handling across mutations | | Image fields | Consistent image URL and alt text selection |
{TypeName}Fragment (e.g., ProductFragment, AddressFragment)| Concept | Description | Example |
|---------|-------------|---------|
| Variable | Dynamic value passed to operation | $id: ID!, $channel: String! |
| Input type | Structured input for mutations | ProductCreateInput, CheckoutCreateInput |
| Required | Non-null variable | $id: ID! (with !) |
| Optional | Nullable variable | $filter: ProductFilterInput |
| Default | Variable with default value | $first: Int = 10 |
| Package | Purpose |
|---------|---------|
| @graphql-codegen/cli | Code generation CLI |
| @graphql-codegen/typescript | Generate TypeScript types from schema |
| @graphql-codegen/typescript-operations | Generate types for operations |
| @graphql-codegen/typed-document-node | Generate TypedDocumentNode objects |
| Setting | Value | Description |
|---------|-------|-------------|
| schema | Saleor GraphQL endpoint URL | Source of truth for types |
| documents | "src/**/*.graphql" or "src/**/*.ts" | Location of operations |
| generates | Output file paths | Where to write generated code |
| plugins | Array of codegen plugins | Which code to generate |
graphql-codegen after schema changes or when adding new operations| Aspect | Benefit | |--------|---------| | Query result | Fully typed response data | | Variables | Type-checked at compile time | | Fragments | Types flow through fragment composition | | IDE support | Autocomplete for fields and variables | | Refactoring | Rename detection across operations |
@graphql-codegen/typed-document-node| Error Type | Location | Cause |
|-----------|----------|-------|
| GraphQL errors | response.data.mutation.errors[] | Validation, permission, business logic |
| Network errors | Caught by client | Connection failure, timeout, 5xx |
| Schema errors | Build-time (codegen) | Operation doesn't match schema |
| Field | Type | Description |
|-------|------|-------------|
| field | String | Which input field caused the error |
| message | String | Human-readable error message |
| code | Enum | Machine-readable error code |
data.mutation.errors after every mutation| Client | Package | SSR Support | Caching | Best For |
|--------|---------|-------------|---------|----------|
| urql | @urql/core, @urql/next | Yes (via @urql/next) | Document cache, Graphcache | Saleor recommended |
| Apollo Client | @apollo/client | Yes | Normalized cache | Complex caching needs |
| graphql-request | graphql-request | N/A (no cache) | None | Simple scripts, server-side |
| gql (Python) | gql | N/A | None | Python scripts and tests |
Authorization: Bearer <token> header for authenticated operationssaleor-channel: <slug> header for channel-scoped queries| Convention | Example | Benefit |
|-----------|---------|---------|
| Prefix with verb | GetProducts, CreateCheckout | Clear intent |
| Suffix queries | ProductListQuery, OrderDetailQuery | Distinguish from mutations |
| Suffix mutations | CheckoutCreateMutation | Distinguish from queries |
| Unique names | No duplicates across codebase | Required by codegen |
Saleor uses Relay-style cursor-based pagination:
| Parameter | Type | Description |
|-----------|------|-------------|
| first | Int | Number of items from the start |
| after | String | Cursor after which to fetch |
| last | Int | Number of items from the end |
| before | String | Cursor before which to fetch |
| Field | Path | Description |
|-------|------|-------------|
| edges | connection.edges[] | Array of edge objects |
| node | edge.node | The actual entity |
| cursor | edge.cursor | Opaque cursor string |
| pageInfo.hasNextPage | connection.pageInfo | More items forward |
| totalCount | connection.totalCount | Total items matching filter |
first + after for forward pagination (most common)totalCount for large datasets (can be slow)| Method | Tool | Use Case |
|--------|------|----------|
| Introspection query | Built-in GraphQL client | Development exploration |
| GraphQL Playground | /graphql/ in browser | Interactive schema browser |
| Schema download | graphql-codegen | CI/CD and type generation |
| SDL export | rover graph introspect <url> | Save schema as .graphql file |
| Test Type | Tool | What to Test |
|-----------|------|-------------|
| Unit | Vitest, Jest | Operation result parsing, error mapping |
| Integration | Saleor test instance | Full round-trip query/mutation |
| Type check | tsc --noEmit | Generated types match operations |
| Linting | @graphql-eslint/eslint-plugin | Operation naming, fragment usage |
data.mutation.errors after every mutation callfirst/after for list queriessaleor-channel header for channel-scoped operationsgraphql-codegen in CI to catch schema mismatchesFetch the GraphQL documentation for current Saleor schema, code generation setup, and client library configuration 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.