+
+
+
+`@labdigital/commercetools-mock` is an open-source project from
+[Lab Digital](https://www.labdigital.nl), a digital commerce agency specialising
+in composable, MACH-based commerce with commercetools — and the team behind
+[Evolve](https://www.evolve-platform.com), a composable agentic commerce
+platform. We build and rely on this mock to test real commercetools integrations
+every day, and we maintain it in the open under the MIT license.
+[Contributions are welcome](https://github.com/labd/commercetools-node-mock).
+
+
+
+
+
+
+
+
diff --git a/docs/src/content/docs/recipes/cart-flow.md b/docs/src/content/docs/recipes/cart-flow.md
new file mode 100644
index 00000000..1fa69f98
--- /dev/null
+++ b/docs/src/content/docs/recipes/cart-flow.md
@@ -0,0 +1,67 @@
+---
+title: Recipe — Testing a cart flow
+description: Create a product through the API, create a cart, add a line item with an update action and assert on the result.
+---
+
+This recipe drives a small checkout flow through the commercetools SDK against
+the mock. It shows the "create through the API, act, assert" pattern for a
+stateful resource and an update action.
+
+It assumes an `apiRoot` configured to talk to the mock (see
+[Quick start](/commercetools-node-mock/getting-started/quick-start/)) and the
+[shared setup](/commercetools-node-mock/recipes/vitest-setup/).
+
+```typescript
+import { expect, test } from 'vitest'
+import { apiRoot } from '../test/ct-client'
+
+test('adds a line item to a cart', async () => {
+ // 1. Create a product type and a product with a SKU
+ await apiRoot
+ .productTypes()
+ .post({ body: { key: 'shoe', name: 'Shoe', description: '', attributes: [] } })
+ .execute()
+
+ await apiRoot
+ .products()
+ .post({
+ body: {
+ key: 'boots',
+ productType: { typeId: 'product-type', key: 'shoe' },
+ name: { en: 'Boots' },
+ slug: { en: 'boots' },
+ masterVariant: {
+ sku: 'SKU-BOOTS',
+ prices: [{ value: { currencyCode: 'EUR', centAmount: 5000 } }],
+ },
+ publish: true,
+ },
+ })
+ .execute()
+
+ // 2. Create a cart
+ const { body: cart } = await apiRoot
+ .carts()
+ .post({ body: { currency: 'EUR' } })
+ .execute()
+
+ // 3. Add the product as a line item (update action)
+ const { body: updated } = await apiRoot
+ .carts()
+ .withId({ ID: cart.id })
+ .post({
+ body: {
+ version: cart.version,
+ actions: [{ action: 'addLineItem', sku: 'SKU-BOOTS', quantity: 2 }],
+ },
+ })
+ .execute()
+
+ // 4. Assert
+ expect(updated.lineItems).toHaveLength(1)
+ expect(updated.lineItems[0].quantity).toBe(2)
+})
+```
+
+The mock applies the `addLineItem` update action, bumps the cart `version`, and
+resolves the price — the same behaviour your production code relies on.
diff --git a/docs/src/content/docs/recipes/custom-types.md b/docs/src/content/docs/recipes/custom-types.md
new file mode 100644
index 00000000..76c8fa45
--- /dev/null
+++ b/docs/src/content/docs/recipes/custom-types.md
@@ -0,0 +1,64 @@
+---
+title: Recipe — Custom types & fields
+description: Create a Type through the API and use its custom fields on another resource.
+---
+
+commercetools custom fields are defined by a `Type`. This recipe creates a type
+and attaches custom fields to a customer — all through the API.
+
+```typescript
+import { expect, test } from 'vitest'
+import { apiRoot } from '../test/ct-client'
+
+test('customer carries custom fields', async () => {
+ // 1. Define a Type targeting customers
+ await apiRoot
+ .types()
+ .post({
+ body: {
+ key: 'customer-extra',
+ name: { en: 'Customer extra fields' },
+ resourceTypeIds: ['customer'],
+ fieldDefinitions: [
+ {
+ name: 'loyaltyId',
+ label: { en: 'Loyalty ID' },
+ required: false,
+ type: { name: 'String' },
+ inputHint: 'SingleLine',
+ },
+ ],
+ },
+ })
+ .execute()
+
+ // 2. Create a customer that uses the type
+ const { body: created } = await apiRoot
+ .customers()
+ .post({
+ body: {
+ email: 'jane@example.com',
+ password: 's3cret',
+ custom: {
+ type: { typeId: 'type', key: 'customer-extra' },
+ fields: { loyaltyId: 'LOYAL-42' },
+ },
+ },
+ })
+ .execute()
+
+ // 3. Read it back, expanding the type reference
+ const { body: customer } = await apiRoot
+ .customers()
+ .withId({ ID: created.customer.id })
+ .get({ queryArgs: { expand: ['custom.type'] } })
+ .execute()
+
+ expect(customer.custom?.fields.loyaltyId).toBe('LOYAL-42')
+ expect(customer.custom?.type.obj?.key).toBe('customer-extra')
+})
+```
+
+Step 3 uses commercetools
+[reference expansion](https://docs.commercetools.com/api/general-concepts#reference-expansion)
+to inline the `type` reference.
diff --git a/docs/src/content/docs/recipes/fixtures.md b/docs/src/content/docs/recipes/fixtures.md
new file mode 100644
index 00000000..252e986d
--- /dev/null
+++ b/docs/src/content/docs/recipes/fixtures.md
@@ -0,0 +1,53 @@
+---
+title: Recipe — Fixtures with fishery
+description: Build reusable, typed draft bodies with fishery and create them through the mock's API.
+---
+
+For anything beyond a trivial resource, a fixture factory keeps tests readable
+and consistent. [fishery](https://github.com/thoughtbot/fishery) pairs well with
+the mock — build **draft bodies** once and reuse them across tests.
+
+## Install
+
+```bash
+pnpm add -D fishery
+```
+
+## A customer-draft factory
+
+```typescript
+import type { CustomerDraft } from '@commercetools/platform-sdk'
+import { Factory } from 'fishery'
+
+export const customerDraftFactory = Factory.define