mcpField
C
commercetools-storefront

commercetools-storefront

github.com/commercetools开发698 次安装5 天前更新
代码仓库

关于 commercetools-storefront

面向 commercetools 店铺开发的框架无关技能,提供共享 BFF 基础、B2C 与 B2B 功能的实现模式,并附带 Next.js 和 Nuxt 适配参考。核心原则是由服务端代理 API 并管理会话与机密信息。

主要功能

  1. 01框架无关的店铺实现模式
  2. 02服务端 BFF 与会话设计
  3. 03服务端目录加载与客户端状态
  4. 04B2C 与 B2B 功能参考
  5. 05Next.js 与 Nuxt 适配指南

适用场景

  1. 01搭建 commercetools 店铺基础架构
  2. 02实现商品目录、购物车与结账
  3. 03为 B2C 或 B2B 店铺添加领域功能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/commercetools/commercetools-ai-plugins --skill commercetools-storefront

安装后在 Claude Code 中输入/commercetools-storefront确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/b2b/
add-api.md
approval-workflows.md
cart.md
checkout.md
customer-auth.md
dashboard.md
data-loading.md
overview.md
permissions.md
product-detail.md
product-listing.md
quote-actions.md
quotes.md
session-and-bu.md
shopping-lists.md
variant-config.md
references/b2b/optional/
recurring-orders.md
recurring-prices.md
superuser.md
references/b2c/
checkout.md
customer-auth.md
navigation.md
overview.md
product-detail.md
references/b2c/optional/
bopis.md
bundles.md
promotions.md
recurring-orders.md
recurring-prices.md
superuser.md

详细介绍

commercetools Storefront(与框架无关)

适用于 commercetools 店面的生产模式——涵盖从共享 BFF 基础到 B2C 和 B2B 专属界面功能的各个方面。此处的模式与框架无关:每种模式都以一项决策和 commercetools 精确代码的形式呈现。你的前端框架负责提供实现原语(文件布局、渲染和路由原语、Cookie 读写绑定)。

架构假设——存在服务端层。 这些模式假设你的店面运行在包含服务端层的技术栈上(SSR / 服务端组件 / 独立 BFF 服务),该层能够保管密钥并代理 commercetools。以下 BFF 和密钥规则不可妥协,并且依赖这一假设。这些模式以 SSR 为先。对于特定框架,请使用 references/stack/ 下的技术栈适配器,例如 Next.js 技术栈,它会将此处的每个概念映射到相应框架的原语,并负责所有文件布局和渲染原语的细节。

参考实现。 代码示例中出现文件路径或渲染原语时,使用的是 Next.js App Router 作为参考实现。与框架无关的规则始终位于周围的说明文字中;适配器会指定确切的原语。

路径和状态约定。

每种参考实现都遵循以下路径和状态管理约定。这些约定并非技术上必需,但广泛用于生产店面,有助于浏览代码库并让新开发者快速上手。请在技术栈适配器中查找 concept-mapping.md,了解所用的确切原语。

约定含义
<server>/服务端代码根目录;每种技术栈都会指定实际目录(例如 Next.js:lib/)
<api>/面向客户端、供浏览器调用的 API 接口和路由
<server>/ct/*commercetools 辅助模块
<server>/ct/clientapiRoot 单例
<server>/types应用类型映射根目录(边界类型)
<server>/mappers/commercetools→应用的映射器
客户端状态框架的客户端状态管理 / 缓存层(具体库由技术栈决定)——用于存储每位用户可变的数据

工作流

调用此技能时,始终遵循以下步骤:

  1. 搜索文档(必需,首先运行) —— 在一个会话中首次使用此技能时,必须先运行此步骤再作答。它会收集最新且经过验证的文档,作为主要依据,并筛选出此技能涵盖的产品。使用此脚本搜索与此技能相关的文档;其他内容由 Knowledge MCP 覆盖。务必根据检索到的文档确认细节,而不能只依据技能文本:

    node "<this skill's directory>/scripts/docs-search.mjs" \
      --query "<extract key terms from user's question>" \
      --app-name "<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>" \
      --model "<current-model>" \
      --commercetools-project-key "<if known>" \
      --commercetools-region "<if known>" \
      --limit 10
    

    仅当上下文中已有 commercetools 项目密钥和区域(格式如 api.{region}.commercetools.com)时才传入;否则省略两者。切勿搜索文件或向用户索要这些信息。

  2. 结合技能参考资料 —— 将分析输出与 ./references/ 中的本地参考资料交叉核对,确保上下文完整。

  3. 提供实施指导 —— 根据用户目标集成模式,综合整理文档内容。

可选脚本

获取 GraphQL 架构 — 当你需要了解 commercetools GraphQL 查询或变更的上下文时运行此脚本,例如在编写查询前检查资源的字段、类型和可用操作,或根据实际架构验证刚生成的 GraphQL 查询/变更。此脚本会获取单个 commercetools 资源的部分 GraphQL SDL:

node scripts/graphql-schemata.mjs \
  --resource-name "<commercetools resource, e.g. Cart, Product, Order>" \
  --app-name "<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>" \
  --model "<current-model>"

输出是该资源的 GraphQL SDL。如果无法识别资源名称,脚本会打印有效资源名称列表——选择正确的名称并重新运行。**注意:**SDL 可能包含存根类型——以存根形式呈现的引用资源,其实际类型名称会写在注释中。需要获取任何此类资源时,可使用该类型名称作为 --resource-name 重新运行此脚本。

获取 OpenAPI(REST)架构 — 当你需要了解 commercetools REST 端点、请求/响应负载或更新操作的上下文时运行此脚本,例如在构造请求前检查资源的 REST 操作,或根据实际规范验证刚生成的 REST 请求/负载。此脚本会获取单个 commercetools 资源的部分 OpenAPI 规范:

node scripts/openApi-schemata.mjs \
  --resource-name "<commercetools resource, e.g. api-Cart-write, api-Customer-read, checkout-Application>" \
  --app-name "<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>" \
  --model "<current-model>"

输出是该资源的 OpenAPI 规范(YAML)。REST 资源使用读写拆分的命名形式(例如 api-Cart-read、api-Cart-write)。如果无法识别资源名称,脚本会打印有效资源名称列表——选择正确的名称并重新运行。**注意:**该规范不包含引用展开架构——需要单独获取被引用资源的架构时,可使用该资源名称作为 --resource-name 重新运行此脚本。

关键要点

**BFF 模式不可妥协。**所有 commercetools API 调用都通过服务器端点(BFF)进行。浏览器绝不直接调用 commercetools。密钥绝不会暴露在客户端代码包中(不使用公共环境变量前缀)。(这需要服务器层——请参阅上文的架构假设。)

**会话由服务器管理。**BFF 拥有会话状态,并且是唯一读取或写入会话状态的层。会话的存储方式由技术栈决定——可以在仅保存状态的 BFF 中使用 HTTP-only Cookie 保存签名令牌,也可以在有状态 BFF 中使用以不透明 Cookie 为键的服务器端会话存储。无论哪种方式,客户端都不会持有会话密钥或原始 commercetools 凭据,只会持有不透明引用。任何会话签名密钥都必须足够强,且绝不能硬编码或暴露给客户端。

**目录数据通过服务器渲染加载;可变用户状态使用客户端状态。**目录/不可变数据(类别页面、PDP)在服务器上加载,直接调用 <server>/ct/*。购物车、账户和用户专属数据则加载到客户端状态管理中 → 服务器端点 → commercetools SDK。

**<server>/ct/* 仅供服务器使用。**绝不要在客户端组件中导入它。请从应用类型映射根目录(<server>/types)导入类型。


决策步骤

按以下顺序构建店面——每个步骤都对应下方参考索引中的一个部分:

  1. **选择技术栈(如有)。**为你的前端选择 references/stack/<name>/ 下的适配器。它负责文件布局、渲染/路由原语、会话机制、客户端状态库和部署。
  2. **实现共享基础。**配置 BFF 边界、会话、commercetools 客户端、类型边界、购物车和数据加载——references/core/。
  3. **添加可选核心功能。**按需加入跨领域扩展(例如周期性价格/订单)——references/core/optional/。
  4. **选择 B2C 或 B2B。**加载对应的功能与规则——references/b2c/ 或 references/b2b/。
  5. **添加可选界面功能。**按需加入特定界面的扩展。

参考索引

技术栈

为你的前端技术栈选择适配器。references/stack/<name>/ 下的每个技术栈文件夹,都会将此技能中与框架无关的模式映射到该技术栈的基础构件,并负责其文件布局、渲染基础构件和部署。

技术栈参考文档命令
Next.js 16(App Router)+ next-intl v4 + Tailwind v4stack/nextjs/overview.md/nextjs-setup-project、/nextjs-deploy-vercel、/nextjs-deploy-netlify
Nuxt 4(Vue、SSR)+ Nitro + @nuxtjs/i18n v10 + nuxt-auth-utils + Pinia + Tailwind v4stack/nuxtjs/overview.md/nuxtjs-setup-project
共享基础(references/core/)
任务参考文档
搭建新项目(依赖项、样式、区域设置路由、文件夹结构)框架专属——请参阅适配器的 overview.md
commercetools SDK 单例、服务端管理的会话、BFF 边界core/ct-client.md
共享身份验证模式:commercetools 登录端点、服务端端点结构、客户端状态钩子、登出core/customer-auth.md
添加新的国家/地区、货币/区域设置——COUNTRY_CONFIG 扁平结构core/add-country.md
并行获取、服务端 TTL 缓存、客户端缓存水合、避免 N+1core/performance.md
产品图片 URL 转换(CDN、Imgix、Cloudinary)core/image-config.md
购物车 CRUD、购物车状态/上下文、客户端状态钩子、迷你购物车抽屉core/cart.md
全文搜索、分面配置、URL 状态、渲染器core/search-facets.md
添加新的 BFF 端点和客户端状态钩子(3 层模式)core/add-api.md
添加新的独立页面或由 CMS 驱动的页面core/add-page.md
服务端渲染与客户端获取的选择、映射器、BFF 结构、409 重试core/data-loading.md
结账页面流程、步骤路由、下单core/checkout-page.md
PDP 路由、变体选择器、共享产品详情模式core/product-detail.md
购物清单(愿望清单、已保存商品)core/shopping-lists.md
核心可选功能(references/core/optional/)
任务参考文档
周期性价格——映射器、PDP 开关、选择器组件、使用 recurrenceInfo 添加到购物车core/recurring-prices.md
周期性订单——范围限定、状态转换、结账后创建、周期性策略core/recurring-orders.md
部署到 Vercel运行 /deploy-vercel——检查 commercetools 凭据,然后交由 Vercel 官方 Agent 技能处理
部署到 Netlify运行 /deploy-netlify——检查 commercetools 凭据,然后交由 Netlify 官方 Agent 技能处理
B2C 商店前台(references/b2c/)
任务参考文档
B2C 概览、要点总结、完整参考索引b2c/overview.md
分类页面、产品映射器、commercetools Search API、ProductCard/Gridb2c/product-listing.md
B2C PDP 路由、图片库、变体选择器、AddToCartButtonb2c/product-detail.md
注册、登录、匿名购物车合并、受保护的账户布局b2c/customer-auth.md
多步骤结账、配送方式、下单b2c/checkout.md
导航模式、页眉、移动端菜单b2c/navigation.md
共享 UI 组件库b2c/ui-components.md
PDP 变体选择器配置(屏蔽列表、色板、排序)b2c/variant-config.md
心愿单功能b2c/wishlist.md
B2C 可选功能(references/b2c/optional/)
任务参考文档
CSR 身份模拟、双会话、行项目价格覆盖b2c/optional/superuser.md
在线购买、门店自提 — 渠道 API、各门店库存b2c/optional/bopis.md
产品捆绑 — 父/子购物车项目、级联更新b2c/optional/bundles.md
产品折扣、购物车折扣、折扣码、促销横幅b2c/optional/promotions.md
定期价格 — recurrencePrices[] 数组、门控b2c/recurring-prices.md
定期订单 — 客户范围限定、originOrder 扩展、结账后创建、skip/setScheduleb2c/recurring-orders.md
B2B 店面(references/b2b/)
任务参考文档
B2B 概览、要点、完整参考索引b2b/overview.md
会话字段、BU/店铺选择、渠道数据、BusinessUnitContextb2b/session-and-bu.md
ProductApi 会话范围限定——店铺、渠道、价格注入、可用性b2b/product-listing.md
B2B PDP 路由、变体选择器、会话范围限定的定价b2b/product-detail.md
as-associate 购物车 CRUD、CartContext、通过 BU+店铺自动创建b2b/cart.md
购物车结账和“申请报价”提交、BU 地址、下单b2b/checkout.md
登录端点、BU 自动选择、登录时写入的会话字段b2b/customer-auth.md
RBAC——所有权限字符串、usePermissions、UI 门控模式b2b/permissions.md
报价仪表板——CT 数据模型、每个 BU 的统一会话线程列表、状态标签、客户端状态钩子b2b/quotes.md
报价买家操作——接受并下单、拒绝、重新协商、状态检查b2b/quote-actions.md
审批规则、审批流程、谓词构建器、层级模型b2b/approval-workflows.md
仪表板框架、统计小组件、页面、侧边栏导航项b2b/dashboard.md
采购清单(通过 as-associate 使用 commercetools ShoppingList,按 BU 限定范围)b2b/purchase-lists.md
添加新的 B2B BFF 端点和客户端状态钩子b2b/add-api.md
B2B 数据加载——服务端渲染与客户端获取、映射器、BFF 结构b2b/data-loading.md
B2B 变体选择器配置b2b/variant-config.md
B2B 可选功能(references/b2b/optional/)
任务参考文档
超级用户角色——查看所有店铺购物车、切换购物车b2b/superuser.md
定期价格——recurrencePrices[] 数组、as-associate 添加到购物车、PDP 门控b2b/recurring-prices.md
定期订单——BU 范围限定、扩展购物车、从购物车创建、复制、仪表板b2b/recurring-orders.md

优先级

严重
  • BFF 架构——<server>/ct/* 仅限服务端使用。任何客户端组件中都不得导入 commercetools SDK。(需要服务端层——参见架构假设。)
  • 会话和客户端密钥——commercetools 客户端密钥及任何会话签名密钥都只能是服务端环境变量,不得硬编码,也不得暴露给客户端包(不使用公共环境变量前缀)。
  • commercetools 登录端点——使用 apiRoot.login().post(),绝不使用 apiRoot.customers().login()。
  • B2B:as-associate 调用链——所有 B2B 写入操作(购物车、订单、报价、审批、BU)都必须通过 apiRoot.asAssociate().*。面向用户的 B2B 修改绝不使用项目级 apiRoot.*。
  • B2B:会话 B2B 字段——businessUnitKey + storeKey + distributionChannelId + supplyChannelId + productSelectionId 始终必须一起通过 getStoreChannelData(storeKey) 写入。
  • B2B:三个字段的语言环境原子性——locale、currency、country 必须一起更新。语言环境或货币变更时重置 cartId。

框架版本限制:查找你所用技术栈的 overview.md。

高优先级
  • 并行获取 — 在服务端渲染的加载过程中,使用 Promise.all 并行获取互不依赖的数据。避免请求瀑布。
  • 类型安全 — 前端组件从应用类型映射根目录(<server>/types)导入类型,绝不从 <server>/ct/* 导入。
  • commercetools 类型边界 — 在 <server>/ct/ 之外使用类型前,先在 <server>/mappers/ 中将 commercetools SDK 响应映射为应用类型。
  • 客户端状态失效 — 登录、退出和下单后,使相关客户端状态失效或刷新。
  • B2B:客户端状态管理器/缓存键中的 BU 键 — 所有仪表板状态都以 businessUnitKey 为键(例如 [KEY, businessUnitKey] 元组),以便在切换 BU 时刷新。
中优先级
  • Product Search API — 使用 apiRoot.products().search(),绝不使用已弃用的 productProjections().search()。请参阅 commercetools-platform 技能 → product-search.md。
  • 服务端 TTL 缓存 — 对很少变化的 commercetools 数据使用框架的服务端 TTL 缓存。绝不要将其用于用户或会话专属数据。(Next.js:unstable_cache — 请参阅适配器。)

反模式速查

反模式正确做法
在客户端组件中导入 <server>/ct/client(apiRoot)使用客户端状态钩子 → 服务端端点 → <server>/ct/
在组件中直接调用端点(fetch('/<api>/*'))将其封装在客户端数据/状态模块中
在页面或服务端端点中调用 new ClientBuilder()在 <server>/ct/client 中使用单例 apiRoot
使用原始 fetch() 请求 commercetools REST 端点始终使用 apiRoot — SDK 会管理 OAuth 令牌及其刷新
将 commercetools 密钥暴露在客户端打包内容中(使用公开环境变量前缀)使用仅限服务端的环境变量,不加公开前缀
product.name['en-US'](硬编码区域设置键)getLocalizedString(product.name, locale)
(centAmount / 100).toFixed(2)formatMoney(centAmount, currencyCode, locale)
对互不依赖的数据依次执行 awaitPromise.all([fetchA(), fetchB()])
apiRoot.customers().login()apiRoot.login().post()
在组件中使用 commercetools SDK 类型使用来自 <server>/types 的类型;在 <server>/mappers/ 中映射
B2B:为已登录用户调用 apiRoot.carts().post(...)asAssociate().withAssociateIdValue(...).inBusinessUnitKey(...).carts().post(...)
B2B:BU 范围内的客户端状态未按 BU 设为键使用 businessUnitKey 作为状态条目的键(例如 [KEY_ORDERS, businessUnitKey])
B2B:使用 StagedQuote.sellerComment 显示每轮内容使用 Quote.sellerComment — 即创建报价时的快照
B2B:使用 apiRoot.shoppingLists() 访问采购清单使用 asAssociate().*.shoppingLists() — 受 BU 范围限制并强制执行权限

评论

支持 Markdown