dist/cursor/saleor-commerce/skills/saleor-catalog/SKILL.md
Manage the Saleor catalog — products, variants, product types, categories, collections, media, and warehouse stock. Use when working with Saleor product data.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins saleor-catalogInstall 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 products variants product types for product model and GraphQL operationssite:docs.saleor.io categories collections for category tree and collection managementsite:docs.saleor.io warehouse stock allocation for inventory and warehouse operationshttps://docs.saleor.io/docs/developer/products and review Product, ProductType, and ProductVariant schemassite:docs.saleor.io product media images for media upload and assignment patternshttps://docs.saleor.io/docs/developer/channels and review channel-aware product visibility| Level | Contains | |-------|----------| | ProductType | Template: defines product and variant attributes, shipping/digital flags | | Product | Name, description, slug, category, collections, media | | ProductVariant | SKU, name, channel listings (price), stock (per warehouse), variant attributes |
| Status | Description |
|--------|-------------|
| DRAFT | Product is not visible to customers; work in progress |
| ACTIVE | Product is published and available for purchase (per channel listing) |
Products require a channel listing to be visible in a given channel. Status alone does not control storefront visibility.
A ProductType serves as a template that defines the structure for a group of products:
| Concept | Purpose |
|---------|---------|
| Product attributes | Shared attributes across all products of this type (e.g., Brand, Material) |
| Variant attributes | Attributes that differ per variant (e.g., Size, Color) |
| isShippingRequired | Whether products of this type need physical shipping |
| isDigital | Whether this type represents digital goods |
| hasVariants | Whether products support multiple variants |
| Weight | Default weight for products of this type |
| Operation | Mutation | Notes |
|-----------|----------|-------|
| Create type | productTypeCreate | Define name, attributes, shipping flag |
| Update type | productTypeUpdate | Modify existing type settings |
| Delete type | productTypeDelete | Removes type (fails if products exist) |
| Assign attribute | productAttributeAssign | Add attribute to product type |
| Unassign attribute | productAttributeUnassign | Remove attribute from type |
Each ProductVariant represents a purchasable unit within a product:
| Field | Description |
|-------|-------------|
| sku | Stock Keeping Unit (unique identifier) |
| name | Display name for the variant |
| trackInventory | Whether stock levels are tracked |
| weight | Override weight from product type |
| preorder | Preorder settings (end date, global threshold) |
| quantityLimitPerCustomer | Maximum purchase quantity per customer |
Variants have per-channel pricing. Each ProductVariantChannelListing holds:
| Field | Description |
|-------|-------------|
| price | Selling price in the channel currency |
| costPrice | Cost of goods (for margin calculations) |
| channel | The channel this listing belongs to |
Categories form a nested tree structure for organizing products:
| Feature | Detail |
|---------|--------|
| Structure | Single-root tree with unlimited nesting depth |
| Assignment | Each product belongs to exactly one category |
| SEO | Categories support seoTitle and seoDescription |
| Background image | Optional image for category pages |
| Slug | URL-friendly identifier |
| Operation | Mutation |
|-----------|----------|
| Create | categoryCreate (set parent for nesting) |
| Update | categoryUpdate |
| Delete | categoryDelete |
Collections are curated groupings of products, independent of the category tree:
| Feature | Detail |
|---------|--------|
| Purpose | Marketing-driven groupings (e.g., "Summer Sale", "Best Sellers") |
| Assignment | Many-to-many; a product can belong to multiple collections |
| Channel listing | Collections must be published per channel |
| Background image | Optional image for collection pages |
| SEO | Supports seoTitle and seoDescription |
| Operation | Mutation |
|-----------|----------|
| Create | collectionCreate |
| Add products | collectionAddProducts |
| Remove products | collectionRemoveProducts |
| Delete | collectionDelete |
Products support images and videos:
| Media Type | Upload Method |
|------------|---------------|
| Images | productMediaCreate with image file upload |
| URLs | productMediaCreate with mediaUrl for external images or videos |
| Reorder | productMediaReorder to set display order |
| Delete | productMediaDelete to remove media |
Images are served through Saleor's thumbnail system. Request specific sizes using the
thumbnailfield onProductMediawithsizeparameter.
| Operation | Query / Mutation | Notes |
|-----------|-----------------|-------|
| List products | products | Supports filtering, sorting, and channel |
| Get product | product | By ID or slug; channel required for pricing |
| Create product | productCreate | Requires productType, name, and category |
| Update product | productUpdate | Partial updates supported |
| Delete product | productDelete | Removes product and all variants |
| Create variant | productVariantCreate | Requires product ID, attributes, SKU |
| Bulk create variants | productVariantBulkCreate | Create multiple variants at once |
| Update stock | productVariantStocksUpdate | Set stock quantities per warehouse |
| Operation | Query | Notes |
|-----------|-------|-------|
| List products | products(channel: "default") | Only published, available products |
| Get product | product(slug: "...", channel: "...") | Returns pricing for the channel |
| Search | products(filter: {search: "..."}) | Full-text search on name and description |
| By category | products(filter: {categories: [...]}) | Filter by category IDs |
| By collection | collection(slug: "...") { products } | Products within a collection |
Fetch live docs for exact filter fields and sorting options -- these evolve across Saleor versions.
| Concept | Description |
|---------|-------------|
| Warehouse | Physical location where stock is held |
| Stock | Per-variant, per-warehouse quantity |
| Allocation | Reserved stock for unfulfilled orders |
| Available quantity | stock.quantity - stock.allocations |
| Operation | Mutation |
|-----------|----------|
| Update stocks | productVariantStocksUpdate |
| Create stocks | productVariantStocksCreate |
| Delete stocks | productVariantStocksDelete |
productVariantBulkCreate for efficiency when adding multiple variantstrackInventory to true for physical goods to prevent oversellingchannel when querying from the storefront to get correct pricing and availabilityFetch the Saleor product and catalog documentation for exact mutation inputs, attribute types, and channel listing patterns 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.