/commerce-app-api-mesh
Scaffold or update an Adobe API Mesh configuration (mesh.json) in front of a Commerce app: add GraphQL/OpenAPI sources, extend an existing Commerce GraphQL type with a new field, and wire a cross-source resolver for it. Use when the user mentions API Mesh, mesh.json, extending a
Claude Code
$ npx -y skills add adobe/skills --skill commerce-app-api-mesh --agent claude-code
Codex
$ npx skills add adobe/skills --skill commerce-app-api-mesh -a codex -y
Cursor
$ npx skills add adobe/skills --skill commerce-app-api-mesh -a cursor -y
Gemini CLI
$ npx skills add adobe/skills --skill commerce-app-api-mesh -a gemini-cli -y
GitHub Copilot
$ npx skills add adobe/skills --skill commerce-app-api-mesh -a github-copilot -y
OpenCode
$ npx skills add adobe/skills --skill commerce-app-api-mesh -a opencode -y
Windsurf
$ npx skills add adobe/skills --skill commerce-app-api-mesh -a windsurf -y
SKILL.md
commerce-app-api-mesh.SKILL.mdname: commerce-app-api-mesh
description: >
Scaffold or update an Adobe API Mesh configuration (mesh.json) in front of
a Commerce app: add GraphQL/OpenAPI sources, extend an existing Commerce
GraphQL type with a new field, and wire a cross-source resolver for it.
Use when the user mentions API Mesh, mesh.json, extending a Commerce
GraphQL type (e.g. adding a field to Order/CustomerOrder/Product), or
stitching a runtime action's data into the storefront's GraphQL schema.
license: Apache-2.0
compatibility: >
Requires the api-mesh CLI plugin (aio plugins install
@adobe/aio-cli-plugin-api-mesh). If wrapping a runtime action as a source,
that action must already be built and deployed.
metadata:
author: adobe
Wire API Mesh in Front of a Commerce App
Composes Commerce's own GraphQL API and this app's runtime actions into a single mesh schema. Two moves this skill covers: exposing a runtime action as a mesh source, and extending an existing Commerce type with a field resolved by delegating to that source.
This skill assumes general API Mesh knowledge (`mesh.json` anatomy, handler types, transforms, hooks, secrets, CORS, generic declarative/programmatic resolvers). If any of that is unfamiliar, load it from Adobe's own material first — see [References](#references) — rather than guessing at syntax. None of that material covers extending an existing Commerce type via `additionalResolvers` (`targetTypeName`/`sourceTypeName`/`requiredSelectionSet`/`sourceSelectionSet`) or wrapping an aio-commerce-sdk runtime action as a mesh source — that's what follows.
Prerequisites
- `aio plugins install @adobe/aio-cli-plugin-api-mesh` is installed.
- If exposing a runtime action as a source, it's already built and deployed with a real, reachable HTTPS endpoint — a source pointing at an undeployed action fails opaquely.
- Check whether a mesh already exists for this workspace: `aio api-mesh:get`. "No mesh found" → you'll `create`; otherwise you're editing an existing `mesh.json` and will `update`.
Step 1 — Confirm schema shapes via introspection
Before writing `additionalTypeDefs` or `additionalResolvers`, introspect the Commerce (or other) GraphQL source you're extending. Don't assume a type/field name from memory or a similar-sounding convention — near-miss names produce a mesh that builds successfully but whose resolver never fires.
curl -s -X POST "<graphql-endpoint>" -H "Content-Type: application/json" \
-d '{"query":"{ __type(name: \"<TargetType>\") { fields { name } } }"}'Step 2 — Scaffold sources
{
"name": "Commerce",
"handler": {
"graphql": {
"endpoint": "<commerce-graphql-endpoint>",
"operationHeaders": { "Authorization": "{context.headers.authorization}" }
}
}
}Include `operationHeaders` by default on any source whose schema has customer-, cart-, or session-scoped fields — API Mesh does **not** forward the caller's `Authorization` header automatically. Omitting it makes every authenticated query fail with the backend's own generic "not authorized" error, indistinguishable from an invalid token.
To wrap a runtime action, write a small static OpenAPI document describing just its endpoint and reference it by relative path:
{
"name": "<SourceName>",
"handler": { "openapi": { "source": "./mesh/<source>.json" } }
}The OpenAPI document itself needs enough shape for the mesh to generate a Query field from it — not just the pointer above. Minimal example for a single-endpoint runtime action:
{
"openapi": "3.0.0",
"info": { "title": "<SourceName>", "version": "1.0.0" },
"servers": [{ "url": "<runtime-action-base-url>" }],
"paths": {
"/<action-path>": {
"get": {
"operationId": "<sourceField>",
"parameters": [
{
"name": "<arg>",
"in": "query",
"required": true,
"schema": { "type": "string" }
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": { "<resultField>": { "type": "string" } }
}
}
}
}
}
}
}
}
}`operationId` becomes the Query field name — it must match `sourceFieldName` in Step 3's resolver exactly, or the resolver builds successfully but never fires.
The declared response schema must match what the action actually returns — the mesh parses according to what you declare, it doesn't reshape data.
Step 3 — Extend a type and wire the resolver
"additionalTypeDefs": "extend type <TargetType> { <newField>: String }",
"additionalResolvers": [
{
"targetTypeName": "<TargetType>",
"targetFieldName": "<newField>",
"sourceName": "<SourceName>",
"sourceTypeName": "Query",
"sourceFieldName": "<sourceField>",
"requiredSelectionSet": "{ <keyField> }",
"sourceArgs": { "<arg>": "{root.<keyField>}" },
"sourceSelectionSet": "{ <resultField> }",
"result": "<resultField>"
}
]Always pair `sourceSelectionSet` with `result` when extracting a scalar from an object-returning source field — never use `result` alone. The `result`-only path builds its selection set by hand instead of via the GraphQL parser, and breaks with `"No type was found for field node ... __typename"` specifically when the target field resolves inside a list (e.g. a parent's `items[].<newField>`). A direct root-query call to the same source field succeeds even when this bug is present, so that test alone isn't sufficient proof the resolver works.
Step 4 — Deploy and verify
If you already know a browser-based app will call this mesh, decide `responseConfig.CORS` now, before your first deploy — the browser-verification tier below exists to catch a missed CORS config, but deciding upfront avoids a second deploy cycle.
`responseConfig.CORS`
Read more
name: commerce-app-api-mesh description: > Scaffold or update an Adobe API Mesh configuration (mesh.json) in front of a Commerce app: add GraphQL/OpenAPI sources, extend an existing Commerce GraphQL type with a new field, and wire a cross-source resolver for it. Use when the user mentions API Mesh, mesh.json, extending a Commerce GraphQL type (e.g. adding a field to Order/CustomerOrder/Product), or stitching a runtime action's data into the storefront's GraphQL schema. license: Apache-2.0 compatibility: > Requires the api-mesh CLI plugin (aio plugins install @adobe/aio-cli-plugin-api-mesh). If wrapping a runtime action as a source, that action must already be built and deployed. metadata: author: adobe
Wire API Mesh in Front of a Commerce App
Composes Commerce's own GraphQL API and this app's runtime actions into a single mesh schema. Two moves this skill covers: exposing a runtime action as a mesh source, and extending an existing Commerce type with a field resolved by delegating to that source.
This skill assumes general API Mesh knowledge (`mesh.json` anatomy, handler types, transforms, hooks, secrets, CORS, generic declarative/programmatic resolvers). If any of that is unfamiliar, load it from Adobe's own material first — see [References](#references) — rather than guessing at syntax. None of that material covers extending an existing Commerce type via `additionalResolvers` (`targetTypeName`/`sourceTypeName`/`requiredSelectionSet`/`sourceSelectionSet`) or wrapping an aio-commerce-sdk runtime action as a mesh source — that's what follows.
Prerequisites
- `aio plugins install @adobe/aio-cli-plugin-api-mesh` is installed.
- If exposing a runtime action as a source, it's already built and deployed with a real, reachable HTTPS endpoint — a source pointing at an undeployed action fails opaquely.
- Check whether a mesh already exists for this workspace: `aio api-mesh:get`. "No mesh found" → you'll `create`; otherwise you're editing an existing `mesh.json` and will `update`.
Step 1 — Confirm schema shapes via introspection
Before writing `additionalTypeDefs` or `additionalResolvers`, introspect the Commerce (or other) GraphQL source you're extending. Don't assume a type/field name from memory or a similar-sounding convention — near-miss names produce a mesh that builds successfully but whose resolver never fires.
curl -s -X POST "<graphql-endpoint>" -H "Content-Type: application/json" \
-d '{"query":"{ __type(name: \"<TargetType>\") { fields { name } } }"}'Step 2 — Scaffold sources
{
"name": "Commerce",
"handler": {
"graphql": {
"endpoint": "<commerce-graphql-endpoint>",
"operationHeaders": { "Authorization": "{context.headers.authorization}" }
}
}
}Include `operationHeaders` by default on any source whose schema has customer-, cart-, or session-scoped fields — API Mesh does **not** forward the caller's `Authorization` header automatically. Omitting it makes every authenticated query fail with the backend's own generic "not authorized" error, indistinguishable from an invalid token.
To wrap a runtime action, write a small static OpenAPI document describing just its endpoint and reference it by relative path:
{
"name": "<SourceName>",
"handler": { "openapi": { "source": "./mesh/<source>.json" } }
}The OpenAPI document itself needs enough shape for the mesh to generate a Query field from it — not just the pointer above. Minimal example for a single-endpoint runtime action:
{
"openapi": "3.0.0",
"info": { "title": "<SourceName>", "version": "1.0.0" },
"servers": [{ "url": "<runtime-action-base-url>" }],
"paths": {
"/<action-path>": {
"get": {
"operationId": "<sourceField>",
"parameters": [
{
"name": "<arg>",
"in": "query",
"required": true,
"schema": { "type": "string" }
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": { "<resultField>": { "type": "string" } }
}
}
}
}
}
}
}
}
}`operationId` becomes the Query field name — it must match `sourceFieldName` in Step 3's resolver exactly, or the resolver builds successfully but never fires.
The declared response schema must match what the action actually returns — the mesh parses according to what you declare, it doesn't reshape data.
Step 3 — Extend a type and wire the resolver
"additionalTypeDefs": "extend type <TargetType> { <newField>: String }",
"additionalResolvers": [
{
"targetTypeName": "<TargetType>",
"targetFieldName": "<newField>",
"sourceName": "<SourceName>",
"sourceTypeName": "Query",
"sourceFieldName": "<sourceField>",
"requiredSelectionSet": "{ <keyField> }",
"sourceArgs": { "<arg>": "{root.<keyField>}" },
"sourceSelectionSet": "{ <resultField> }",
"result": "<resultField>"
}
]Always pair `sourceSelectionSet` with `result` when extracting a scalar from an object-returning source field — never use `result` alone. The `result`-only path builds its selection set by hand instead of via the GraphQL parser, and breaks with `"No type was found for field node ... __typename"` specifically when the target field resolves inside a list (e.g. a parent's `items[].<newField>`). A direct root-query call to the same source field succeeds even when this bug is present, so that test alone isn't sufficient proof the resolver works.
Step 4 — Deploy and verify
If you already know a browser-based app will call this mesh, decide `responseConfig.CORS` now, before your first deploy — the browser-verification tier below exists to catch a missed CORS config, but deciding upfront avoids a second deploy cycle.
`responseConfig.CORS`
Skills that teach AI coding agents to work with Adobe products. A skill is a folder with a SKILL.md that an agent loads when a task calls for it (agentskills.io).
Other skills on skills.
More skills from other plugins.
karpathy-guidelines
Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid…
agent-builder
Design and build AI agents for any domain. Use when users: (1) ask to "create an agent", "build an assistant", or "design an AI…
Questions about commerce-app-api-mesh.
- Which coding agents can use commerce-app-api-mesh?
- commerce-app-api-mesh installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

