From commercetools
Build, test, deploy, and install commercetools Connect applications (connectors) in TypeScript/Node. Guides API extensions, subscriptions, jobs, Merchant Center custom apps, and deployment lifecycle.
How this skill is triggered — by the user, by Claude, or both
Slash command
/commercetools:commercetools-connectThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Intent-driven guidance for building **production-ready** Connect applications. This skill teaches the decision frameworks, platform contracts, and best practices that survive a production-readiness review — not a single connector's code. It generalizes patterns (and warns against anti-patterns) found in real connectors, and grounds every platform fact in official docs.
examples/prompts/signature-required.mdreferences/architecture-decisions.mdreferences/connect-cli.mdreferences/deployment-installation.mdreferences/event-applications.mdreferences/job-applications.mdreferences/lifecycle-scripts.mdreferences/merchant-center-cli.mdreferences/merchant-center-customizations.mdreferences/monorepo-with-storefront.mdreferences/observability-operations.mdreferences/project-structure.mdreferences/security.mdreferences/service-applications.mdreferences/testing.mdscripts/docs-search.mjsscripts/graphql-schemata.mjsscripts/openApi-schemata.mjsIntent-driven guidance for building production-ready Connect applications. This skill teaches the decision frameworks, platform contracts, and best practices that survive a production-readiness review — not a single connector's code. It generalizes patterns (and warns against anti-patterns) found in real connectors, and grounds every platform fact in official docs.
Language scope: Connect applications can be written in JavaScript/TypeScript or Java (docs); the create-connect-app template supports JS and TS. This skill targets TypeScript/Node — the decision frameworks, platform contracts (timeouts, ack semantics, scopes, lifecycle), and connect.yaml guidance are language-agnostic and apply equally to a Java connector, but the code snippets and the supertest + msw test stack are Node/Express-specific.
Tooling — use the Connect CLI, don't hand-roll. Scaffold, run, and ship with the official Connect CLI (@commercetools/cli). Every CLI command, the bootstrap flow, and the pinned dependency versions live in one place: the Connect CLI reference (connect-cli.md). Merchant Center custom applications/views are the exception: they use a separate frontend toolchain (@commercetools-frontend/*) and only ride the Connect CLI at deploy time and directory structure — see merchant-center-cli.md and merchant-center-customizations.md.
When this skill is invoked, always follow these steps:
Docs search (required, run first) — Always begin by searching docs for this skill. This is the mandatory grounding step: it gathers the latest verified documentation as context for you (the agent). Do not skip it, and do not replace it with another tool (such as an MCP documentation-search tool) This script optimizes for tuned search results — run this command:
node scripts/docs-search.mjs \
--query "<extract key terms from user's question>" \
--app-name "<current-app ex: claude, copilot, codex>" \
--model "<current-model>" \
--skill-name "commercetools-connect" \
--limit 10
Use its output as your primary grounding. You may additionally use the commercetools Knowledge MCP or https://docs.commercetools.com/connect for deeper follow-up.
Route with the decision framework (below) — Pick the application type and lock in the sync-vs-async contract before writing code. The contract determines almost every later decision.
Open the matching reference(s) in ./references/ and build to their patterns and ## Checklist.
Gate on the production-readiness checklist (below) before declaring the connector done.
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:
node scripts/graphql-schemata.mjs \
--resource-name "<commercetools resource, e.g. Cart, Product, Order>" \
--app-name "<current-app, e.g. claude, copilot, cursor, codex>" \
--model "<current-model>" \
--skill-name "commercetools-connect"
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.
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:
node scripts/openApi-schemata.mjs \
--resource-name "<commercetools resource, e.g. api-Cart-write, api-Customer-read, checkout-Application>" \
--app-name "<current-app, e.g. claude, copilot, cursor, codex>" \
--model "<current-model>" \
--skill-name "commercetools-connect"
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.
A Connector is one repository declaring one or more applications in connect.yaml. Pick each application's type by how your code is invoked and which way data flows, not by what it does.
Two things to fix first:
service is just an HTTP endpoint, not necessarily an API Extension. A service app exposes an HTTP endpoint. That endpoint can be registered as an API Extension (commercetools calls it synchronously inside an operation) or be a plain inbound webhook / REST API that an external system calls to push data in. These are two modes with different contracts.| Trigger / need | Type | How your code is invoked | Hard contract |
|---|---|---|---|
| Block or modify a commercetools operation before it persists (validate a cart, inject tax, reject an order) | service as API Extension | commercetools calls your endpoint synchronously during the API request (registered as an Extension) | Extension response limit: 2 s default, 10 s self-service max (per-project increases available via support request, subject to performance review). Your latency and downtime become the platform's. |
| An external system pushes data into commercetools as it changes (system A updates a product → upsert it into commercetools) | service as inbound webhook / API | the external system calls your endpoint | 5-min service request timeout. You authenticate the caller and call the commercetools API yourself; no Extension is registered. |
| React to a commercetools change after it happened (sync a confirmed order to a WMS, send an email, index a product) | event (Subscription handler) | commercetools delivers a Subscription message to a queue → your handler | At-least-once, no ordering, redelivery on non-ack. Must be idempotent. |
| Scheduled or on-demand batch (nightly poll an external system and upsert, reconcile, cleanup, bulk import) | job | a cron scheduler (properties.schedule) | Request times out after 30 min. No concurrency guard — you own locking. |
| Add UI inside the Merchant Center | merchant-center-custom-application (full-page) / merchant-center-custom-view (embedded panel) | Hosted React app built with the MC CLI, deployed via Connect | Separate frontend toolchain (@commercetools-frontend/*) + a config-file contract; ships as a merchant-center-* app in connect.yaml. → merchant-center-cli.md, merchant-center-customizations.md |
| Serve static files / a CDN bundle | assets | Static host | — |
A single connector commonly combines types (e.g. a service API Extension that calculates tax on the cart plus an event handler that commits the transaction when the order is placed; or a service inbound webhook for live pushes plus a job for nightly full reconciliation).
Detail and trade-offs: architecture-decisions.md.
The expensive mistakes come from not pricing the contract you just chose:
service as API Extension couples your availability and latency to the commercetools operation. A slow or down extension makes carts and orders slow or impossible. So: a tight outbound timeout under the extension timeout, a deliberate fail-open vs. fail-closed decision, and minimizing work on the hot path (skip redundant external calls).service as inbound webhook is not coupled to a commercetools operation (the 5-min service timeout applies, not the 2 s extension limit), but you own everything: authenticate the caller, validate the payload, and make the write idempotent (the same product update may arrive twice) — upsert by key, don't blind-create. Decide what a failed write returns so the caller can retry safely.event) trades immediacy for resilience but hands you at-least-once delivery, no ordering, and redelivery. So: idempotency keyed on a stable identifier, redelivery-safe acks (2xx for "don't send again"), re-fetch the resource by ID rather than trusting a possibly-stale or omitted payload, and self-change filtering to avoid loops.job owns its own scheduling headroom, overlap locking, and restart-safe checkpointing; each unit of work must be idempotent so a re-run or overlap can't double-write.If you cannot articulate, in one sentence each, your latency budget (extension), your idempotency strategy (inbound webhook / event / job), and your fail/retry behavior, you are not ready to write the handler.
A connector is not done until every applicable item holds. Each maps to a reference with the implementation pattern.
102/200/201/202/204) for handled and irrelevant-but-acked messages; anything other than 102, 200, 201, 202, or 204 triggers a retry. → event-applications.mdresource.id; required when payloadNotIncluded is set. → event-applications.mdAuthorizationHeaderAuthentication (or AzureFunctions) and validate that secret in-app. Webhooks from external systems validate a full JWT (signature, issuer, audience, subject, expiry, algorithm). → security.mdinheritAs.apiClient.scopes with only the scopes the apps need (e.g. manage_orders, manage_subscriptions, manage_extensions) — not an admin/manage_project client. → security.mdsecuredConfiguration. API keys, client secrets, JWT secrets are never standardConfiguration and never hardcoded. → security.mdmessage.data is base64) and validated (→ JSON → resource ref → notificationType) before any processing; malformed envelopes rejected. → event-applications.mdconnect.yaml endpoint. The Express router is mounted at the same base path as the app's endpoint (e.g. endpoint: /service ↔ app.use('/service', router)), or the platform's traffic 404s. → project-structure.md@commercetools/platform-sdk@^8 + @commercetools/ts-client@^4 (not the legacy @commercetools/sdk-client-v2). Java: spring-boot-starter-parent 3.5.15+ and commercetools Java SDK 19+. Typed end to end, no any escapes, mapped at the boundary. → connect-cli.md (Step 3).X-Correlation-ID for extensions, resource.id + sequenceNumber for events) on every log line for a request. → observability-operations.md/status-style route returns 200 for liveness. → observability-operations.mdpostDeploy creates resources get-then-update (create only if absent), never blind delete-then-recreate. preUndeploy cleans them up. → lifecycle-scripts.mdpostDeploy test-connects to external services and surfaces invalid credentials immediately. → lifecycle-scripts.mdcommercetools connect application test. At minimum: the parameterized auth-rejection matrix (missing/expired/wrong-issuer/wrong-audience/alg:none), envelope/ack edge cases (event) or the pure business logic + response actions (service), an idempotency/duplicate-delivery test, and idempotent postDeploy registration. A couple of happy-path tests is not enough. → testing.mdany escapes. No commented-out blocks; SDK types preserved end to end. → project-structure.mdcommercetools connect init; commercetools connect validate passes. → connect-cli.md (Step 2)connect.yaml key), and the poison-message/replay runbook. → deployment-installation.md| Concern | Reference |
|---|---|
Connect CLI mechanics: install/auth, connect init templates, pinned versions, build/test/validate, stage/preview/publish/deploy commands | connect-cli.md |
Merchant Center CLI: scaffold with create-mc-app; run/build/serve/login/config:sync with mc-scripts; pin @commercetools-frontend/* | merchant-center-cli.md |
Custom application vs custom view; config-file contract; develop/test locally; deploy via Connect (connect.yaml merchant-center-* types, order of operations) | merchant-center-customizations.md |
| Monorepo holding a connector + a storefront: root-sibling layout, why no npm workspaces, the two independent deploy lifecycles | monorepo-with-storefront.md |
| event vs service vs job; sync vs async contract cost | architecture-decisions.md |
| CLI scaffold + local dev, monorepo layout, client setup (ts-client), connect.yaml anatomy, route↔endpoint matching, fail-fast env validation | project-structure.md |
| subscriptions: envelope, ack semantics, idempotency, redelivery, re-fetch, Pub/Sub destination | event-applications.md |
| API extensions: authenticated registration, triggers, timeout budget, fail-open/closed, hot-path | service-applications.md |
| scheduled/on-demand jobs: schedule, timeout, concurrency, checkpointing | job-applications.md |
| post-deploy/pre-undeploy: idempotent registration, schema-as-code, deploy-time validation | lifecycle-scripts.md |
| endpoint auth, least-privilege scopes, securedConfiguration, error hygiene | security.md |
| structured logs + correlation IDs, health, feature flags, runbook, DLQ | observability-operations.md |
| auth/envelope test matrices, supertest + msw patterns, what to mock | testing.md |
| connect.yaml config, sandbox→preview→publish, install, redeploy, certification, regions, CLI | deployment-installation.md |
Related skills: SDK client setup, scopes, query predicates, and core data model live in commercetools-platform — link to it rather than restating client/auth basics here.
npx claudepluginhub commercetools/commercetools-ai-plugins --plugin commercetoolsCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.