// "Explains Saleor e-commerce domain and Configurator business rules. Covers entity identification (slug vs name), deployment pipeline stages, and configuration schema. Triggers on: entity types, deployment pipeline, config schema, slug identification, categories, products, channels, YAML configuration."
| name | understanding-saleor-domain |
| description | Explains Saleor e-commerce domain and Configurator business rules. Covers entity identification (slug vs name), deployment pipeline stages, and configuration schema. Triggers on: entity types, deployment pipeline, config schema, slug identification, categories, products, channels, YAML configuration. |
| allowed-tools | Read, Grep, Glob, Bash(pnpm:*), Bash(git:*), Bash(ls:*) |
Provide deep domain knowledge about the Saleor e-commerce platform and the Configurator's business logic for entity management, configuration, deployment, and synchronization.
A "commerce as code" CLI tool that enables declarative configuration management for Saleor e-commerce platforms. It allows developers to:
Critical Rule: Every entity has exactly ONE identification strategy.
Identified by slug field. Used for entities that need URL-friendly identifiers.
| Entity | Identifier Field | Example |
|---|---|---|
| Categories | slug | electronics |
| Channels | slug | default-channel |
| Collections | slug | summer-sale |
| Menus | slug | main-navigation |
| Products | slug | iphone-15-pro |
| Warehouses | slug | us-east-warehouse |
Implementation Pattern:
// Comparison uses slug
const isSameEntity = (local: Category, remote: Category) =>
local.slug === remote.slug;
// Lookups use slug
const existing = await repository.findBySlug(entity.slug);
Identified by name field. Used for internal configuration entities.
| Entity | Identifier Field | Example |
|---|---|---|
| ProductTypes | name | Physical Product |
| PageTypes | name | Blog Post |
| TaxClasses | name | Standard Rate |
| ShippingZones | name | North America |
| Attributes | name | Color |
Implementation Pattern:
// Comparison uses name
const isSameEntity = (local: ProductType, remote: ProductType) =>
local.name === remote.name;
Only one instance exists. No identifier needed.
| Entity | Notes |
|---|---|
| Shop | Global store settings |
Stages execute in specific order due to dependencies:
1. Validation → Pre-flight checks
2. Shop Settings → Global configuration
3. Product Types → Must exist before products
4. Page Types → Must exist before pages
5. Attributes → Used by product/page types
6. Categories → Product organization
7. Collections → Product groupings
8. Warehouses → Required for inventory
9. Shipping Zones → Geographic shipping rules
10. Products → Depends on types, categories
11. Tax Config → Tax rules and classes
12. Channels → Sales channels
13. Menus → Navigation (may reference products)
14. Models → Custom data models
Example: Cannot create a Product without its ProductType existing first.
# This product depends on "Physical Product" type
products:
- name: "iPhone 15"
slug: "iphone-15"
productType: "Physical Product" # Must exist!
Each stage follows:
shop:
# Global store settings
channels:
# Sales channel definitions
taxClasses:
# Tax rate classifications
productTypes:
# Product type templates
pageTypes:
# CMS page templates
attributes:
# Shared attribute definitions
categories:
# Product category hierarchy
collections:
# Dynamic product collections
warehouses:
# Fulfillment center definitions
shippingZones:
# Geographic shipping configurations
products:
# Product catalog
menus:
# Navigation menu structures
models:
# Custom data models
Attributes can be of various types:
| Type | Description | Example Values |
|---|---|---|
DROPDOWN | Single select | ["Red", "Blue", "Green"] |
MULTISELECT | Multiple select | ["Feature A", "Feature B"] |
RICH_TEXT | HTML content | Rich text editor |
PLAIN_TEXT | Simple text | Text input |
BOOLEAN | True/false | Checkbox |
DATE | Date picker | 2024-01-15 |
DATE_TIME | Date and time | 2024-01-15T10:30:00 |
NUMERIC | Numbers | 42.5 |
SWATCH | Color/image swatch | Color picker |
FILE | File upload | Document/image |
REFERENCE | Entity reference | Links to other entities |
Reference Attributes (Special):
attributes:
- name: "Related Products"
type: REFERENCE
entityType: PRODUCT # Must specify what it references
Large operations are chunked to avoid timeouts and rate limits:
const CHUNK_SIZE = 50; // Default chunk size
const chunks = splitIntoChunks(items, CHUNK_SIZE);
for (const chunk of chunks) {
await processChunk(chunk);
// Rate limiting handled by urql retry exchange
}
The GraphQL client handles HTTP 429 automatically:
For each entity type, comparison checks:
type DiffAction = 'create' | 'update' | 'delete' | 'unchanged';
interface DiffResult<T> {
action: DiffAction;
local?: T;
remote?: T;
changes?: FieldChange[];
}
Each entity has a dedicated comparator:
// src/core/diff/comparators/category-comparator.ts
export const compareCategorys = (
local: Category[],
remote: Category[]
): DiffResult<Category>[] => {
// Match by slug
// Compare relevant fields
// Return diff results
};
src/modules/config/schema/src/modules/<entity>/src/core/diff/comparators/// Check dependency exists before creating
const productType = await productTypeRepository.findByName(product.productType);
if (!productType) {
throw new EntityDependencyError(
`ProductType "${product.productType}" not found`
);
}
For detailed information, see:
{baseDir}/.claude/skills/saleor-domain-expert/references/entity-identification.md - Complete entity identification rules{baseDir}/.claude/skills/saleor-domain-expert/references/deployment-stages.md - Pipeline stage details{baseDir}/.claude/skills/saleor-domain-expert/references/schema-patterns.md - YAML configuration patterns{baseDir}/docs/ENTITY_REFERENCE.md - Full entity documentation{baseDir}/docs/ARCHITECTURE.md - System architecture{baseDir}/src/modules/config/schema/schema.ts - Zod schema definitionsadding-entity-types for complete implementation workflowdesigning-zod-schemas for schema patternswriting-graphql-operations for Saleor API integration