← commercetoolsCONTENT HISTORY

Update to commercetools

Snapshot Nov 9, 2026 · 12:08 UTC · version 0.69.0

Collection source: downloaded plugin package.

WHAT CHANGED

First saved snapshot

No earlier snapshot is available to establish a change.

Save commercetools and check future changes in Following.

Up to 3 plugins free · no card required.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Production patterns for building customer-facing storefronts on commercetools - the full B2C and B2B domain feature set. Patterns are stated as decisions plus commercetools-exact code; framework-specific implementation. Assumes a server tier exists to host the BFF. Use for PDP, PLP, cart, checkout flow, customer login, search/facets, locale handling, and any B2B- or B2C-specific feature.",
  "included_files": [
    {
      "relative_path": "references/b2b/add-api.md",
      "size_in_bytes": 5507
    },
    {
      "relative_path": "references/b2b/approval-workflows.md",
      "size_in_bytes": 10491
    },
    {
      "relative_path": "references/b2b/cart.md",
      "size_in_bytes": 5569
    },
    {
      "relative_path": "references/b2b/checkout.md",
      "size_in_bytes": 6286
    },
    {
      "relative_path": "references/b2b/customer-auth.md",
      "size_in_bytes": 3052
    },
    {
      "relative_path": "references/b2b/dashboard.md",
      "size_in_bytes": 6415
    },
    {
      "relative_path": "references/b2b/data-loading.md",
      "size_in_bytes": 2720
    },
    {
      "relative_path": "references/b2b/optional/recurring-orders.md",
      "size_in_bytes": 5966
    },
    {
      "relative_path": "references/b2b/optional/recurring-prices.md",
      "size_in_bytes": 2651
    },
    {
      "relative_path": "references/b2b/optional/superuser.md",
      "size_in_bytes": 7491
    },
    {
      "relative_path": "references/b2b/overview.md",
      "size_in_bytes": 10282
    },
    {
      "relative_path": "references/b2b/permissions.md",
      "size_in_bytes": 9510
    },
    {
      "relative_path": "references/b2b/product-detail.md",
      "size_in_bytes": 3694
    },
    {
      "relative_path": "references/b2b/product-listing.md",
      "size_in_bytes": 9426
    },
    {
      "relative_path": "references/b2b/quote-actions.md",
      "size_in_bytes": 3906
    },
    {
      "relative_path": "references/b2b/quotes.md",
      "size_in_bytes": 6331
    },
    {
      "relative_path": "references/b2b/session-and-bu.md",
      "size_in_bytes": 10480
    },
    {
      "relative_path": "references/b2b/shopping-lists.md",
      "size_in_bytes": 8056
    },
    {
      "relative_path": "references/b2b/variant-config.md",
      "size_in_bytes": 4774
    },
    {
      "relative_path": "references/b2c/checkout.md",
      "size_in_bytes": 2726
    },
    {
      "relative_path": "references/b2c/customer-auth.md",
      "size_in_bytes": 3037
    },
    {
      "relative_path": "references/b2c/navigation.md",
      "size_in_bytes": 6113
    },
    {
      "relative_path": "references/b2c/optional/bopis.md",
      "size_in_bytes": 8683
    },
    {
      "relative_path": "references/b2c/optional/bundles.md",
      "size_in_bytes": 11956
    },
    {
      "relative_path": "references/b2c/optional/promotions.md",
      "size_in_bytes": 8851
    },
    {
      "relative_path": "references/b2c/optional/recurring-orders.md",
      "size_in_bytes": 6576
    },
    {
      "relative_path": "references/b2c/optional/recurring-prices.md",
      "size_in_bytes": 2995
    },
    {
      "relative_path": "references/b2c/optional/superuser.md",
      "size_in_bytes": 9086
    },
    {
      "relative_path": "references/b2c/overview.md",
      "size_in_bytes": 5939
    },
    {
      "relative_path": "references/b2c/product-detail.md",
      "size_in_bytes": 962
    },
    {
      "relative_path": "references/b2c/product-listing.md",
      "size_in_bytes": 5393
    },
    {
      "relative_path": "references/b2c/ui-components.md",
      "size_in_bytes": 8345
    },
    {
      "relative_path": "references/b2c/variant-config.md",
      "size_in_bytes": 4716
    },
    {
      "relative_path": "references/b2c/wishlists.md",
      "size_in_bytes": 6225
    },
    {
      "relative_path": "references/core/add-api.md",
      "size_in_bytes": 7388
    },
    {
      "relative_path": "references/core/add-country.md",
      "size_in_bytes": 4544
    },
    {
      "relative_path": "references/core/add-page.md",
      "size_in_bytes": 3052
    },
    {
      "relative_path": "references/core/cart.md",
      "size_in_bytes": 6583
    },
    {
      "relative_path": "references/core/checkout-page.md",
      "size_in_bytes": 5519
    },
    {
      "relative_path": "references/core/ct-client.md",
      "size_in_bytes": 7977
    },
    {
      "relative_path": "references/core/customer-auth.md",
      "size_in_bytes": 6420
    },
    {
      "relative_path": "references/core/data-loading.md",
      "size_in_bytes": 5972
    },
    {
      "relative_path": "references/core/image-config.md",
      "size_in_bytes": 5747
    },
    {
      "relative_path": "references/core/optional/recurring-orders.md",
      "size_in_bytes": 7301
    },
    {
      "relative_path": "references/core/optional/recurring-prices.md",
      "size_in_bytes": 6862
    },
    {
      "relative_path": "references/core/performance.md",
      "size_in_bytes": 9567
    },
    {
      "relative_path": "references/core/product-detail.md",
      "size_in_bytes": 3580
    },
    {
      "relative_path": "references/core/search-facets.md",
      "size_in_bytes": 8988
    },
    {
      "relative_path": "references/core/shopping-lists.md",
      "size_in_bytes": 6263
    },
    {
      "relative_path": "references/stack/nextjs/best-practices/error-handling.md",
      "size_in_bytes": 5529
    },
    {
      "relative_path": "references/stack/nextjs/best-practices/image.md",
      "size_in_bytes": 4096
    },
    {
      "relative_path": "references/stack/nextjs/best-practices/metadata.md",
      "size_in_bytes": 4128
    },
    {
      "relative_path": "references/stack/nextjs/best-practices/server-components.md",
      "size_in_bytes": 1528
    },
    {
      "relative_path": "references/stack/nextjs/concept-mapping.md",
      "size_in_bytes": 9816
    },
    {
      "relative_path": "references/stack/nextjs/data-loading.md",
      "size_in_bytes": 9606
    },
    {
      "relative_path": "references/stack/nextjs/overview.md",
      "size_in_bytes": 5229
    },
    {
      "relative_path": "references/stack/nextjs/project-layout.md",
      "size_in_bytes": 5995
    },
    {
      "relative_path": "references/stack/nuxtjs/best-practices/error-handling.md",
      "size_in_bytes": 5198
    },
    {
      "relative_path": "references/stack/nuxtjs/best-practices/image.md",
      "size_in_bytes": 4497
    },
    {
      "relative_path": "references/stack/nuxtjs/best-practices/metadata.md",
      "size_in_bytes": 3565
    },
    {
      "relative_path": "references/stack/nuxtjs/best-practices/rendering.md",
      "size_in_bytes": 4905
    },
    {
      "relative_path": "references/stack/nuxtjs/concept-mapping.md",
      "size_in_bytes": 11635
    },
    {
      "relative_path": "references/stack/nuxtjs/data-loading.md",
      "size_in_bytes": 11255
    },
    {
      "relative_path": "references/stack/nuxtjs/overview.md",
      "size_in_bytes": 7450
    },
    {
      "relative_path": "references/stack/nuxtjs/project-layout.md",
      "size_in_bytes": 7797
    },
    {
      "relative_path": "scripts/docs-search.mjs",
      "size_in_bytes": 26546
    },
    {
      "relative_path": "scripts/graphql-schemata.mjs",
      "size_in_bytes": 25248
    },
    {
      "relative_path": "scripts/openApi-schemata.mjs",
      "size_in_bytes": 25619
    }
  ],
  "name": "commercetools-storefront",
  "skill_md_contents": "---\nname: commercetools-storefront\ndescription: Production patterns for building customer-facing storefronts on commercetools - the full B2C and B2B domain feature set. Patterns are stated as decisions plus commercetools-exact code; framework-specific implementation. Assumes a server tier exists to host the BFF. Use for PDP, PLP, cart, checkout flow, customer login, search/facets, locale handling, and any B2B- or B2C-specific feature.\nwhen_to_use:\n  - \"Implementing a commercetools storefront (BFF, sessions, carts, checkout, B2C/B2B features) regardless of frontend framework\"\n  - \"Adding a new feature to an existing commercetools storefront\"\n  - \"Building a B2C storefront: anonymous carts, customer auth, BOPIS, bundles, promotions, or CSR impersonation\"\n  - \"Building a B2B storefront: quotes, approval workflows, store-scoped pricing, purchase lists, or recurring orders\"\n  - \"Deciding server-rendered vs client-fetched data loading, designing the commercetools type boundary, or the as-associate API chain\"\n  - \"Implementing a spec/plan/tasks.md task annotated [SKILL: commercetools-storefront]\"\n  - \"An implementation-plan step that builds a storefront surface (PDP/PLP/cart/customer/B2B)\"\nmetadata:\n  contentType: SKILL\n  area:\n    - Foundations\n  docsSearch:\n    products:\n      - Composable Commerce\n      - Checkout\n      - Connect\n      - AI Hub\n---\n\n# commercetools Storefront (framework-agnostic)\n\nProduction patterns for commercetools storefronts — covering the full range from the shared BFF foundation to B2C and B2B surface-specific features. The patterns here are framework-neutral: each is stated as a decision plus commercetools-exact code. Your frontend framework supplies the implementation primitives (file layout, render and routing primitives, the cookie read/write binding).\n\n> **Architecture assumption — a server tier exists.** These patterns assume your storefront runs on a stack with a server-side tier (SSR / server components / a standalone BFF service) that can hold secrets and proxy commercetools. The BFF and secret rules below are non-negotiable and depend on this. They are designed SSR-first. For a specific framework, use its stack adapter under `references/stack/` — e.g. the **[Next.js stack](./references/stack/nextjs/overview.md)** — which maps each concept here to that framework's primitives and owns all file-layout and render-primitive details.\n\n> **Reference implementation.** Where a code example shows a file path or a render primitive, it uses the Next.js App Router as the reference implementation. The framework-neutral rule is always in the surrounding prose; the adapter pins the exact primitive.\n\n**Path & state conventions.**\n\nEach reference implementation follows these conventions for paths and state management. The conventions are not technically required, but they are widely used in production storefronts and make it easier to navigate the codebase and onboard new developers. Find the `concept-mapping.md` in your stack adapter for the exact primitives used.\n> | Convention | Meaning |\n> | --- | --- |\n> | `<server>/` | Your server-side code root; each stack pins the actual directory (Example Next.js: `lib/`) |\n> | `<api>/` | the client-facing API surface the browser calls and routes |\n> | `<server>/ct/*` | The commercetools helper modules |\n> | `<server>/ct/client` | The `apiRoot` singleton |\n> | `<server>/types` | The app type-mapping root (the boundary types) |\n> | `<server>/mappers/` | The commercetools→app mappers |\n> | **Client state** | Your framework's client-side state-management / cache layer (the specific library is a stack choice) — use it for mutable per-user data |\n\n## Workflow\n\nWhen this skill is invoked, always follow these steps:\n\n1. <!-- ct:docs-search:begin -->\n   **Docs search (required, run first)** — The first time you use this skill in a session you must run this before answering. It gathers the latest verified documentation as your primary grounding, filtered to the products this skill covers. Use this script for documentation search while working with this skill; the Knowledge MCP covers everything else. Always confirm details against retrieved documentation rather than the skill text alone:\n\n   ```bash\n   node \"<this skill's directory>/scripts/docs-search.mjs\" \\\n     --query \"<extract key terms from user's question>\" \\\n     --app-name \"<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>\" \\\n     --model \"<current-model>\" \\\n     --commercetools-project-key \"<if known>\" \\\n     --commercetools-region \"<if known>\" \\\n     --limit 10\n   ```\n\n   Pass the commercetools project key and region (as in `api.{region}.commercetools.com`) only if already in your context; otherwise omit both. Never search files or ask the user for them.\n   <!-- ct:docs-search:end -->\n\n2. **Combine with skill references** — Cross-reference the analysis output with local references in `./references/` for complete context.\n\n3. **Provide implementation guidance** — Synthesize the documentation with the specific integration mode the user is targeting.\n\n### Optional scripts\n\n**Fetch GraphQL schema** — Run this when you need context about a commercetools GraphQL query or mutation — for example, to inspect a resource's fields, types, and available operations before writing a query, or to verify a GraphQL query/mutation you have just generated against the real schema. It fetches the partial GraphQL SDL for a single commercetools resource:\n   ```bash\n   node scripts/graphql-schemata.mjs \\\n     --resource-name \"<commercetools resource, e.g. Cart, Product, Order>\" \\\n     --app-name \"<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>\" \\\n     --model \"<current-model>\"\n   ```\n   The output is the GraphQL SDL for that resource. If the resource name is not recognized, the script prints the list of valid resource names — pick the correct one and re-run. **Note:** the SDL may contain *stubbed types* — referenced resources rendered as stubs, with their real type name given in a comment. Fetch any you need separately by re-running this script with that type name as `--resource-name`.\n\n**Fetch OpenAPI (REST) schema** — Run this when you need context about a commercetools REST endpoint, request/response payload, or update action — for example, to inspect a resource's REST operations before constructing a request, or to verify a REST request/payload you have just generated against the real specification. It fetches the partial OpenAPI specification for a single commercetools resource:\n   ```bash\n   node scripts/openApi-schemata.mjs \\\n     --resource-name \"<commercetools resource, e.g. api-Cart-write, api-Customer-read, checkout-Application>\" \\\n     --app-name \"<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>\" \\\n     --model \"<current-model>\"\n   ```\n   The output is the OpenAPI specification (YAML) for that resource. REST resources use a read/write-split naming form (e.g. `api-Cart-read`, `api-Cart-write`). If the resource name is not recognized, the script prints the list of valid resource names — pick the correct one and re-run. **Note:** the spec does not include reference-expansion schemas — fetch a referenced resource's schema separately by re-running this script with that resource as `--resource-name`.\n\n## Key Takeaways\n\n**The BFF pattern is non-negotiable.** All commercetools API calls go through a server endpoint (BFF). The browser never calls commercetools directly. Secrets are never exposed to the client bundle (no public env prefix). *(This requires a server tier — see the architecture assumption above.)*\n\n**Sessions are server-managed.** The BFF owns session state and is the only tier that reads or writes it. How it's stored is a stack choice — a signed token in an HTTP-only cookie (stateless BFF), or a server-side session store keyed by an opaque cookie (stateful BFF). Either way the client never holds session secrets or raw commercetools credentials — only an opaque reference. Any session-signing secret must be strong and is never hardcoded or exposed to the client.\n\n**Server-rendered loads for catalog data; client state for mutable user state.** Catalog/immutable data (category pages, PDPs) is loaded on the server, calling `<server>/ct/*` directly. Cart, account, and user-specific data are loaded into client-side state management → server endpoint → commercetools SDK.\n\n\n**`<server>/ct/*` is server-only.** Never import it from a client component. Import types from the app type-mapping root (`<server>/types`).\n\n\n---\n\n## Decision Steps\n\nBuild a storefront in this order — each step maps to a section of the Reference Index below:\n\n1. **Choose your stack (if exists).** Pick the adapter under `references/stack/<name>/` for your frontend. It owns file layout, render/routing primitives, the session mechanism, the client-state library, and deploy.\n2. **Implement the shared foundation.** Wire the BFF boundary, sessions, commercetools client, type boundary, cart, and data-loading — `references/core/`.\n3. **Add optional core features.** Layer in cross-cutting extras (e.g. recurring prices/orders) as needed — `references/core/optional/`.\n4. **Choose B2C or B2B.** Load the matching surface for its domain features and rules — `references/b2c/` or `references/b2b/`.\n5. **Add optional surface features.** Layer in surface-specific extras .\n\n---\n\n## Reference Index\n\n### Stacks\n\nPick the adapter for your frontend stack. Each stack folder under `references/stack/<name>/` maps the framework-neutral patterns in this skill onto that stack's primitives and owns its file layout, render primitives, and deploy.\n\n| Stack | Reference | Commands |\n|-------|-----------|----------|\n| **Next.js 16** (App Router) + next-intl v4 + Tailwind v4 | [stack/nextjs/overview.md](./references/stack/nextjs/overview.md) | `/nextjs-setup-project`, `/nextjs-deploy-vercel`, `/nextjs-deploy-netlify` |\n| **Nuxt 4** (Vue, SSR) + Nitro + @nuxtjs/i18n v10 + nuxt-auth-utils + Pinia + Tailwind v4 | [stack/nuxtjs/overview.md](./references/stack/nuxtjs/overview.md) | `/nuxtjs-setup-project` |\n\n\n### Shared Foundation (`references/core/`)\n\n| Task | Reference |\n|------|-----------|\n| Scaffold a new project (deps, styling, locale routing, folder structure) | Framework-specific - see the adapter's `overview.md` |\n| commercetools SDK singleton, server-managed sessions, BFF boundary | [core/ct-client.md](./references/core/ct-client.md) |\n| Shared auth patterns: commercetools login endpoint, server endpoint structure, client state hook, logout | [core/customer-auth.md](./references/core/customer-auth.md) |\n| Add a new country / currency / locale — `COUNTRY_CONFIG` flat structure | [core/add-country.md](./references/core/add-country.md) |\n| Parallel fetching, server-side TTL caching, client-cache hydration, N+1 avoidance | [core/performance.md](./references/core/performance.md) |\n| Product image URL transforms (CDN, Imgix, Cloudinary) | [core/image-config.md](./references/core/image-config.md) |\n| Cart CRUD, cart state/context, client state hook, mini-cart drawer | [core/cart.md](./references/core/cart.md) |\n| Full-text search, facet config, URL state, renderers | [core/search-facets.md](./references/core/search-facets.md) |\n| Add a new BFF endpoint + client state hook (the 3-layer pattern) | [core/add-api.md](./references/core/add-api.md) |\n| Add a new standalone or CMS-driven page | [core/add-page.md](./references/core/add-page.md) |\n| Server-rendered vs client-fetched decisions, mappers, BFF shape, 409 retry | [core/data-loading.md](./references/core/data-loading.md) |\n| Checkout page flow, step routing, order placement | [core/checkout-page.md](./references/core/checkout-page.md) |\n| PDP route, variant selectors, shared product detail patterns | [core/product-detail.md](./references/core/product-detail.md) |\n| Shopping lists (wishlist, saved items) | [core/shopping-lists.md](./references/core/shopping-lists.md) |\n\n### Core Optional Features (`references/core/optional/`)\n| Task | Reference |\n|------|-----------|\n| Recurring prices — mapper, PDP gate, selector component, add-to-cart with recurrenceInfo | [core/recurring-prices.md](./references/core/optional/recurring-prices.md) |\n| Recurring orders — scoping, state transitions, post-checkout creation, recurrence policies | [core/recurring-orders.md](./references/core/optional/recurring-orders.md) |\n| Deploy to Vercel | Run `/deploy-vercel` — checks commercetools credentials, then hands off to Vercel's official agent skill |\n| Deploy to Netlify | Run `/deploy-netlify` — checks commercetools credentials, then hands off to Netlify's official agent skill |\n\n### B2C Storefront (`references/b2c/`)\n\n| Task | Reference |\n|------|-----------|\n| B2C overview, key takeaways, full reference index | [b2c/overview.md](./references/b2c/overview.md) |\n| Category pages, product mapper, commercetools Search API, ProductCard/Grid | [b2c/product-listing.md](./references/b2c/product-listing.md) |\n| B2C PDP route, image gallery, variant selectors, AddToCartButton | [b2c/product-detail.md](./references/b2c/product-detail.md) |\n| Register, login, anonymous cart merge, protected account layout | [b2c/customer-auth.md](./references/b2c/customer-auth.md) |\n| Multi-step checkout, shipping methods, order placement | [b2c/checkout.md](./references/b2c/checkout.md) |\n| Navigation patterns, header, mobile menu | [b2c/navigation.md](./references/b2c/navigation.md) |\n| Shared UI component library | [b2c/ui-components.md](./references/b2c/ui-components.md) |\n| PDP variant selector configuration (blocklist, swatch, sort) | [b2c/variant-config.md](./references/b2c/variant-config.md) |\n| Wishlist functionality | [b2c/wishlist.md](./references/b2c/wishlists.md) |\n\n\n### B2C Optional Features (`references/b2c/optional/`)\n\n| Task | Reference |\n|------|-----------|\n| CSR impersonation, dual session, line-item price override | [b2c/optional/superuser.md](./references/b2c/optional/superuser.md) |\n| Buy Online Pick Up In Store — channel API, per-store inventory | [b2c/optional/bopis.md](./references/b2c/optional/bopis.md) |\n| Product bundles — parent/child cart items, cascade updates | [b2c/optional/bundles.md](./references/b2c/optional/bundles.md) |\n| Product discounts, cart discounts, discount codes, promotion banners | [b2c/optional/promotions.md](./references/b2c/optional/promotions.md) |\n| Recurring prices — recurrencePrices[] array, gate | [b2c/recurring-prices.md](./references/b2c/optional/recurring-prices.md) |\n| Recurring orders — customer scoping, originOrder expand, post-checkout create, skip/setSchedule | [b2c/recurring-orders.md](./references/b2c/optional/recurring-orders.md) |\n\n### B2B Storefront (`references/b2b/`)\n\n| Task | Reference |\n|------|-----------|\n| B2B overview, key takeaways, full reference index | [b2b/overview.md](./references/b2b/overview.md) |\n| Session fields, BU/store selection, channel data, BusinessUnitContext | [b2b/session-and-bu.md](./references/b2b/session-and-bu.md) |\n| ProductApi session scoping — store, channels, price injection, availability | [b2b/product-listing.md](./references/b2b/product-listing.md) |\n| B2B PDP route, variant selectors, session-scoped pricing | [b2b/product-detail.md](./references/b2b/product-detail.md) |\n| as-associate cart CRUD, CartContext, auto-creation with BU+store | [b2b/cart.md](./references/b2b/cart.md) |\n| Cart checkout and \"Request a Quote\" submission, BU addresses, order placement | [b2b/checkout.md](./references/b2b/checkout.md) |\n| Login endpoint, BU auto-select, session fields written at login | [b2b/customer-auth.md](./references/b2b/customer-auth.md) |\n| RBAC — all permission strings, usePermissions, UI gating patterns | [b2b/permissions.md](./references/b2b/permissions.md) |\n| Quotes dashboard — CT data model, unified thread list per BU, status labels, client state hooks | [b2b/quotes.md](./references/b2b/quotes.md) |\n| Quote buyer actions — accept & place order, decline, renegotiate, state guards | [b2b/quote-actions.md](./references/b2b/quote-actions.md) |\n| Approval rules, approval flows, predicate builder, tier model | [b2b/approval-workflows.md](./references/b2b/approval-workflows.md) |\n| Dashboard shell, stat widgets, pages, sidebar nav items | [b2b/dashboard.md](./references/b2b/dashboard.md) |\n| Purchase lists (commercetools ShoppingList via as-associate, BU-scoped) | [b2b/purchase-lists.md](./references/b2b/shopping-lists.md) |\n| Add a new B2B BFF endpoint + client state hook | [b2b/add-api.md](./references/b2b/add-api.md) |\n| B2B data loading — server-rendered vs client-fetched, mappers, BFF shape | [b2b/data-loading.md](./references/b2b/data-loading.md) |\n| B2B variant selector configuration | [b2b/variant-config.md](./references/b2b/variant-config.md) |\n\n### B2B Optional Features (`references/b2b/optional/`)\n\n| Task | Reference |\n|------|-----------|\n| Superuser role — view all store carts, switch carts | [b2b/superuser.md](./references/b2b/optional/superuser.md) |\n| Recurring prices — recurrencePrices[] array, as-associate add-to-cart, PDP gate | [b2b/recurring-prices.md](./references/b2b/optional/recurring-prices.md) |\n| Recurring orders — BU scoping, cart expand, create-from-cart, duplicate, dashboard | [b2b/recurring-orders.md](./references/b2b/optional/recurring-orders.md) |\n\n---\n\n## Priority Tiers\n\n### CRITICAL\n\n- **BFF architecture** — `<server>/ct/*` is server-only. Zero commercetools SDK imports in any client component. (Requires a server tier — see the architecture assumption.)\n- **Session & client secrets** — the commercetools client secret and any session-signing secret are server-only env vars, never hardcoded and never exposed to the client bundle (no public env prefix).\n- **commercetools login endpoint** — `apiRoot.login().post()`, never `apiRoot.customers().login()`.\n- **B2B: as-associate chain** — ALL B2B writes (cart, order, quote, approval, BU) go through `apiRoot.asAssociate().*`. Never use project-level `apiRoot.*` for user-facing B2B mutations.\n- **B2B: session B2B fields** — `businessUnitKey` + `storeKey` + `distributionChannelId` + `supplyChannelId` + `productSelectionId` are always written together from `getStoreChannelData(storeKey)`.\n- **B2B: three-field locale atomicity** — `locale`, `currency`, `country` must all be updated together. Reset `cartId` on locale/currency change.\n\n> Framework-version gates, find `overview.md` of your stack.\n\n### HIGH\n\n- **Parallel fetching** — `Promise.all` for independent fetches in server-rendered loads. No request waterfalls.\n- **Type safety** — Frontend components import types from the app type-mapping root (`<server>/types`), never from `<server>/ct/*`.\n- **commercetools type boundary** — Map commercetools SDK responses to app types in `<server>/mappers/` before they leave `<server>/ct/`.\n- **Client state invalidation** — invalidate/refresh the relevant client state after login, logout, and order placement.\n- **B2B: BU key in client state-manager/cache keys** — all dashboard state is keyed by `businessUnitKey` (e.g. a `[KEY, businessUnitKey]` tuple) so it refreshes on BU switch.\n\n### MEDIUM\n\n- **Product Search API** — Use `apiRoot.products().search()`, never the deprecated `productProjections().search()`. See the `commercetools-platform` skill → [product-search.md](../commercetools-platform/references/product-search.md).\n- **Server-side TTL cache** — Wrap rarely-changing commercetools data in the framework's server-side cache-with-TTL. Never use it for per-user or per-session data. (Next.js: `unstable_cache` — see the adapter.)\n\n---\n\n## Anti-Patterns Quick Reference\n\n| Anti-pattern | Correct approach |\n|---|---|\n| Importing `<server>/ct/client` (`apiRoot`) in a client component | Use a client state hook → server endpoint → `<server>/ct/` |\n| Calling the endpoint (`fetch('/<api>/*')`) directly in a component | Encapsulate it in a client data/state module |\n| `new ClientBuilder()` inside a page or server endpoint | Singleton `apiRoot` in `<server>/ct/client` |\n| Raw `fetch()` to commercetools REST endpoints | Always use `apiRoot` — the SDK manages OAuth tokens and refresh |\n| Exposing a commercetools secret to the client bundle (public env prefix) | Server-only env var, no public prefix |\n| `product.name['en-US']` (hardcoded locale key) | `getLocalizedString(product.name, locale)` |\n| `(centAmount / 100).toFixed(2)` | `formatMoney(centAmount, currencyCode, locale)` |\n| Sequential `await` for independent fetches | `Promise.all([fetchA(), fetchB()])` |\n| `apiRoot.customers().login()` | `apiRoot.login().post()` |\n| commercetools SDK types in components | Types from `<server>/types`; mapped in `<server>/mappers/` |\n| B2B: `apiRoot.carts().post(...)` for a logged-in user | `asAssociate().withAssociateIdValue(...).inBusinessUnitKey(...).carts().post(...)` |\n| B2B: BU-scoped client state not keyed by BU | Key the state entry by `businessUnitKey` (e.g. `[KEY_ORDERS, businessUnitKey]`) |\n| B2B: `StagedQuote.sellerComment` for per-round display | `Quote.sellerComment` — the snapshot at quote creation time |\n| B2B: `apiRoot.shoppingLists()` for purchase lists | `asAssociate().*.shoppingLists()` — BU-scoped, permission-enforced |\n\n"
}

SHA-256 of public snapshot: b33cc46d1e526815302471597a2e486d415862992e38534b749bfc76a4aca57a