关于 ce-setup
面向开发者的 Commerce Engine SDK 设置技能,帮助根据项目框架配置店面 SDK。内容涵盖初始化、环境变量、会话存储,以及公开读取与会话操作的访问方式。
主要功能
- 01识别项目框架并选择入口
- 02安装并初始化店面 SDK
- 03配置环境变量和会话存储
- 04区分公开读取与会话流程
- 05说明 Hosted Checkout 令牌同步
适用场景
- 01为 Next.js 或 SPA 配置 SDK
- 02为 SSR 框架设置服务端会话
- 03将 Hosted Checkout 接入店面 SDK
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ commercengine/ skills --skill ce-setup安装后在 Claude Code 中输入/ce-setup确认已加载。
附带文件.claude-plugin/plugin.json.cursor-plugin/plugin.json
详细介绍
LLM Docs 标头:所有发送到
https://llm-docs.commercengine.io的请求必须包含Accept: text/markdown标头(或在 URL 路径末尾追加.md)。若未包含该标头,响应将返回 HTML,而不是可解析的 Markdown。
设置 Commerce Engine
此技能用于设置最新版 Commerce Engine SDK。
当前心智模型
所有框架均安装 @commercengine/storefront——一个带有子路径导出的统一软件包:
- SPA:
import { createStorefront } from "@commercengine/storefront"→storefront.public()/storefront.session() - Next.js:
import { createNextjsStorefront } from "@commercengine/storefront/nextjs"→storefront.publicStorefront()/storefront.clientStorefront()/await storefront.serverStorefront() - TanStack Start:
import { createTanStackStartStorefront } from "@commercengine/storefront/tanstack-start"→storefront.publicStorefront()/storefront.clientStorefront()+ 单独的服务端入口,用于serverStorefront() - Astro:
import { createAstroStorefront } from "@commercengine/storefront/astro"→storefront.publicStorefront()/storefront.clientStorefront()+ 单独的服务端入口,用于serverStorefront(cookies) - SvelteKit:
import { createSvelteKitStorefront } from "@commercengine/storefront/sveltekit"→storefront.publicStorefront()/storefront.clientStorefront()+ 单独的服务端入口,用于serverStorefront(cookies)
快速参考
| 步骤 | 操作 |
|---|---|
| 1. 检测框架 | 检查 package.json 和配置文件 |
| 2. 安装 SDK | @commercengine/storefront(适用于所有框架) |
| 3. 初始化 storefront | SPA:createStorefront(...),Next.js:createNextjsStorefront(...),TanStack Start:createTanStackStartStorefront(...),Astro:createAstroStorefront(...),SvelteKit:createSvelteKitStorefront(...) |
| 4. 设置环境变量 | Next.js:NEXT_PUBLIC_*,TanStack Start / SPA:VITE_*,Astro / SvelteKit:PUBLIC_* |
| 5. 引导会话 | SPA:如果希望在启动时预先设置会话,请调用一次 sdk.ensureAccessToken();SSR 框架:在客户端组件中调用 storefront.bootstrap() |
| 6. 使用正确的访问器 | 公共读取:publicStorefront() / public();会话流程:clientStorefront() / serverStorefront() / session() |
| 7. 托管结账(如使用) | 必需:设置 authMode: "provided" 并进行双向令牌同步(适用于任何使用 Storefront SDK 的应用) |
标准设置(Storefront + 托管结账)
如果应用在使用 Storefront SDK 的同时也使用托管结账,则必须设置 authMode: "provided" 并进行双向令牌同步,不能省略。SDK 会为 API 调用管理自己的会话;若不使用 provided 模式,结账会创建另一个独立会话。标准设置如下:
- Storefront SDK 管理会话状态。
- 托管结账以
authMode: "provided"模式运行。 - 在应用启动时初始化一次结账,而不是针对每个路由或组件渲染都初始化。
- 双向令牌同步是必需的:
- SDK -> 结账,通过
updateTokens(...) - 结账 -> SDK,通过
onTokensUpdated
- SDK -> 结账,通过
import {
BrowserTokenStorage,
createStorefront,
} from "@commercengine/storefront";
import { getCheckout, initCheckout } from "@commercengine/checkout";
const tokenStorage = new BrowserTokenStorage("myapp_");
export const storefront = createStorefront({
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
session: {
tokenStorage,
// Note: in SPA (createStorefront), onTokensUpdated is nested inside `session`.
// In SSR wrappers (createNextjsStorefront / createTanStackStartStorefront),
// it is a top-level config property — do not nest it under `session` there.
onTokensUpdated: (accessToken, refreshToken) => {
getCheckout().updateTokens(accessToken, refreshToken);
},
},
});
const sessionSdk = storefront.session();
const accessToken = await sessionSdk.ensureAccessToken();
const refreshToken = await tokenStorage.getRefreshToken();
initCheckout({
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
authMode: "provided",
accessToken: accessToken ?? undefined,
refreshToken: refreshToken ?? undefined,
onTokensUpdated: ({ accessToken, refreshToken }) => {
void sessionSdk.setTokens(accessToken, refreshToken);
},
});
框架检测
检查 package.json 和配置文件以识别框架:
| 指示项 | 框架 | 导入路径 | 会话存储 |
|---|---|---|---|
依赖项中有 next,且有 next.config.* | Next.js | @commercengine/storefront/nextjs | 内置(基于 cookie) |
依赖项中有 @tanstack/react-start | TanStack Start | @commercengine/storefront/tanstack-start | 内置(基于 cookie) |
依赖项中有 astro | Astro | @commercengine/storefront/astro | 内置(基于 cookie) |
依赖项中有 @sveltejs/kit | SvelteKit | @commercengine/storefront/sveltekit | 内置(基于 cookie) |
依赖项中有 nuxt | Nuxt | @commercengine/storefront + @commercengine/ssr-utils | ServerTokenStorage |
有 vite.config.* + 浏览器应用 | React / Vue / Svelte / Solid SPA | @commercengine/storefront | BrowserTokenStorage |
依赖项中有 express | Express / Node.js | @commercengine/storefront | MemoryTokenStorage 或自定义 TokenStorage |
| 以上皆无 | Vanilla JS | @commercengine/storefront | BrowserTokenStorage |
决策树
User Request: "Set up Commerce Engine" / "Add e-commerce"
│
├─ Read package.json + config files
│
├─ Next.js detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createNextjsStorefront() from @commercengine/storefront/nextjs
│ │ → Root layout uses storefront.publicStorefront() + StorefrontBootstrap
│ │ → See ce-ssr-patterns for request-bound usage
│ └─ NO ↓
│
├─ TanStack Start detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createTanStackStartStorefront() from @commercengine/storefront/tanstack-start
│ │ → Server-only: createTanStackStartServerStorefront() from .../tanstack-start/server
│ └─ NO ↓
│
├─ Astro detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createAstroStorefront() from @commercengine/storefront/astro
│ │ → Server-only: createAstroServerStorefront() from .../astro/server
│ └─ NO ↓
│
├─ SvelteKit detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createSvelteKitStorefront() from @commercengine/storefront/sveltekit
│ │ → Server-only: createSvelteKitServerStorefront() from .../sveltekit/server
│ └─ NO ↓
│
├─ Other SSR framework (Nuxt)?
│ ├─ YES → Install @commercengine/storefront + @commercengine/ssr-utils
│ │ → Use ServerTokenStorage with CookieAdapter
│ └─ NO → Install @commercengine/storefront
│ → Use BrowserTokenStorage (SPA) or MemoryTokenStorage (Node)
│
├─ Using Hosted Checkout?
│ ├─ YES → Install @commercengine/checkout
│ │ → authMode: "provided"
│ │ → Two-way token sync (SDK ↔ checkout)
│ └─ NO → SDK-only setup
│
└─ Create one storefront factory and use the framework-appropriate accessors
按框架设置
Next.js(App Router)
npm install @commercengine/storefront
// lib/storefront.ts
import { Environment } from "@commercengine/storefront";
import { createNextjsStorefront } from "@commercengine/storefront/nextjs";
export const storefront = createNextjsStorefront({
storeId: process.env.NEXT_PUBLIC_STORE_ID!,
apiKey: process.env.NEXT_PUBLIC_API_KEY!,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
});
// components/storefront-bootstrap.tsx
"use client";
import { useEffect } from "react";
import { storefront } from "@/lib/storefront";
export function StorefrontBootstrap() {
useEffect(() => {
storefront.bootstrap().catch(console.error);
}, []);
return null;
}
根布局是一个 Server Component,但可以将 StorefrontBootstrap(Client Component)作为子组件渲染——这是标准的 Next.js 组合方式。尽可能将引导组件放在组件树的高层。
// app/layout.tsx (Server Component — this is fine)
import { storefront } from "@/lib/storefront";
import { StorefrontBootstrap } from "@/components/storefront-bootstrap";
const { data: storeConfig } = await storefront.publicStorefront().store.getStoreConfig();
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<StorefrontBootstrap />
<header>{storeConfig?.store_config?.brand.name}</header>
{children}
</body>
</html>
);
}
如需了解完整的 Next.js 请求模型,请参阅
ce-ssr-patterns。使用托管结账? 请参阅
ce-cart-checkout和references/hosted-checkout.md,了解令牌同步模式。
# .env.local
NEXT_PUBLIC_STORE_ID=your-store-id
NEXT_PUBLIC_API_KEY=your-api-key
TanStack Start
npm install @commercengine/storefront
// lib/storefront.ts
import { Environment } from "@commercengine/storefront";
import { createTanStackStartStorefront } from "@commercengine/storefront/tanstack-start";
export const storefrontConfig = {
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
};
export const storefront = createTanStackStartStorefront(storefrontConfig);
// lib/storefront.server.ts (server-only module)
import { createTanStackStartServerStorefront } from "@commercengine/storefront/tanstack-start/server";
import { storefrontConfig } from "./storefront";
const serverStorefrontFactory = createTanStackStartServerStorefront(storefrontConfig);
export function serverStorefront() {
return serverStorefrontFactory.serverStorefront();
}
// components/storefront-bootstrap.tsx
import { useEffect } from "react";
import { storefront } from "@/lib/storefront";
export function StorefrontBootstrap() {
useEffect(() => {
storefront.bootstrap().catch(console.error);
}, []);
return null;
}
在根布局(__root.tsx)中挂载 StorefrontBootstrap。
# .env
VITE_STORE_ID=your-store-id
VITE_API_KEY=your-api-key
Astro
npm install @commercengine/storefront
// src/lib/storefront-config.ts
import { Environment } from "@commercengine/storefront";
import type { AstroStorefrontConfig } from "@commercengine/storefront/astro";
export const storefrontConfig: AstroStorefrontConfig = {
storeId: import.meta.env.PUBLIC_STORE_ID,
apiKey: import.meta.env.PUBLIC_API_KEY,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
};
// src/lib/storefront.ts
import { createAstroStorefront } from "@commercengine/storefront/astro";
import { storefrontConfig } from "./storefront-config";
export const storefront = createAstroStorefront(storefrontConfig);
// src/lib/server-storefront.ts (server-only)
import { createAstroServerStorefront } from "@commercengine/storefront/astro/server";
import { storefrontConfig } from "./storefront-config";
export const serverStorefront = createAstroServerStorefront(storefrontConfig);
在根布局脚本中进行引导,然后在 SSR 页面/API 路由中使用 serverStorefront.serverStorefront(Astro.cookies)。
如需了解完整的 Astro 请求模型,请参阅
ce-ssr-patterns。
# .env
PUBLIC_STORE_ID=your-store-id
PUBLIC_API_KEY=your-api-key
SvelteKit
npm install @commercengine/storefront
// src/lib/storefront-config.ts
import { Environment } from "@commercengine/storefront";
import type { SvelteKitStorefrontConfig } from "@commercengine/storefront/sveltekit";
import { env } from "$env/static/public";
export const storefrontConfig: SvelteKitStorefrontConfig = {
storeId: env.PUBLIC_STORE_ID,
apiKey: env.PUBLIC_API_KEY,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
};
// src/lib/storefront.ts
import { createSvelteKitStorefront } from "@commercengine/storefront/sveltekit";
import { storefrontConfig } from "./storefront-config";
export const storefront = createSvelteKitStorefront(storefrontConfig);
// src/lib/server/storefront.ts (server-only — $lib/server/ is enforced by SvelteKit)
import { createSvelteKitServerStorefront } from "@commercengine/storefront/sveltekit/server";
import { storefrontConfig } from "$lib/storefront-config";
export const serverStorefront = createSvelteKitServerStorefront(storefrontConfig);
通过 onMount 在根 +layout.svelte 中进行引导,然后在服务器加载函数、钩子和操作中使用 serverStorefront.serverStorefront(cookies)。
如需了解完整的 SvelteKit 请求模型,请参阅
ce-ssr-patterns。
# .env
PUBLIC_STORE_ID=your-store-id
PUBLIC_API_KEY=your-api-key
React / Vue / Svelte / Solid(SPA)
npm install @commercengine/storefront
// lib/storefront.ts
import {
BrowserTokenStorage,
Environment,
createStorefront,
} from "@commercengine/storefront";
export const storefront = createStorefront({
storeId: import.meta.env.VITE_STORE_ID,
environment: import.meta.env.PROD ? Environment.Production : Environment.Staging,
apiKey: import.meta.env.VITE_API_KEY,
session: {
tokenStorage: new BrowserTokenStorage("myapp_"),
},
});
// Public reads
const { data: products } = await storefront.public().catalog.listProducts();
// Live session flows
const sessionSdk = storefront.session();
await sessionSdk.ensureAccessToken();
# .env
VITE_STORE_ID=your-store-id
VITE_API_KEY=your-api-key
Node.js / Express
npm install @commercengine/storefront
import {
Environment,
MemoryTokenStorage,
createStorefront,
} from "@commercengine/storefront";
export const storefront = createStorefront({
storeId: process.env.CE_STORE_ID!,
environment: process.env.NODE_ENV === "production" ? Environment.Production : Environment.Staging,
apiKey: process.env.CE_API_KEY!,
session: {
tokenStorage: new MemoryTokenStorage(),
},
});
会话存储指南
| 存储 | 使用场景 | 持久性 | SSR 安全 |
|---|---|---|---|
BrowserTokenStorage | 浏览器 SPA | localStorage | 否 |
CookieTokenStorage | 浏览器 cookie / 跨标签页 cookie 同步 | Cookies | 仅限浏览器 |
MemoryTokenStorage | 服务端或临时存储 | 内存中 | 是 |
ServerTokenStorage | 使用请求 cookie 的 SSR 框架 | 通过框架适配器使用 Cookies | 是 |
对于实时 SSR 请求流程,请使用 @commercengine/ssr-utils 中的 ServerTokenStorage。不要将 CookieTokenStorage 用作 SSR 服务端的主要存储层。
首次 API 调用
可立即执行公开读取操作:
const { data: products } = await storefront.public().catalog.listProducts();
如果应用需要提前创建实时匿名/已登录会话,请在启动期间执行一次:
const sessionSdk = storefront.session();
await sessionSdk.ensureAccessToken();
const { data: wishlist } = await sessionSdk.cart.getWishlist();
常规的会话感知型 SDK 方法,例如 sdk.cart.getWishlist()、sdk.cart.addToWishlist()、sdk.cart.getUserCart() 和 sdk.customer.listAddresses(),无需手动调用 ensureAccessToken()。中间件和重载会自动处理会话创建和 ID 解析。如果应用需要提前引导,请在启动期间调用一次,而不要在各处功能代码中散布 ensureAccessToken()。
Session 辅助方法
大多数需要 user_id 或 customer_id 的会话 SDK 方法都有无参数重载,可从当前会话中自动解析。你无需手动获取 ID 并传入。例如:
// Preferred — SDK auto-resolves user_id from session
const { data } = await sdk.cart.getUserCart();
const { data: wishlist } = await sdk.cart.getWishlist();
const { data: orders } = await sdk.order.listOrders();
const { data: addresses } = await sdk.customer.listAddresses();
// Only pass IDs explicitly when operating on behalf of a different user (admin scenarios)
const { data } = await sdk.cart.getUserCart({ user_id: "other_user_id" });
具有无参数重载的方法(自动解析 user_id 或 customer_id):
- 购物车:
getUserCart()、deleteUserCart()、getWishlist()、addToWishlist()、removeFromWishlist() - 订单:
listOrders() - 客户:
listAddresses()、createAddress()、getAddress()、updateAddress()、deleteAddress()、getLoyaltyDetails()、listLoyaltyPointsActivity()、listCustomerReviews()、listSavedPaymentMethods()、listCustomerCards()
Auth 客户端方法仍需要显式 ID——getUserDetails({ id })、updateUserDetails({ id }) 等。对于这些调用,请使用 sdk.getUserId() 获取当前用户的 ID。
仍需要会话辅助方法的情况
| 辅助方法 | 使用时机 |
|---|---|
ensureAccessToken() | 在启动期间调用一次,以便在你明确希望提前建立会话时使用 |
getAccessToken() | 被动读取当前令牌(传入 Hosted Checkout 初始化流程) |
sdk.session.peekRefreshToken() | 被动读取当前刷新令牌(传入 Hosted Checkout 初始化流程) |
setTokens(accessToken, refreshToken?) | 将 Hosted Checkout 中的令牌同步回 SDK |
getUserId() | 传入需要显式 { id } 的 Auth 客户端方法 |
getUserInfo() | 读取用户信息以用于 UI 显示(姓名、邮箱),无需调用 API——从 JWT 解码 |
isLoggedIn() / isAnonymous() | 条件式 UI 渲染(显示登录按钮或账户菜单) |
sdk.session——Peek 与 Ensure
session 属性提供两种模式,可进行精细控制:
Peek——被动读取,不会创建会话或刷新令牌,失败时返回 null:
sdk.session.peekAccessToken()/peekRefreshToken()/peekUserInfo()/peekUserId()/peekCustomerId()
Ensure——可能会创建匿名会话或刷新过期令牌,失败时抛出异常:
sdk.session.ensureAccessToken()/ensureUserInfo()/ensureUserId()/ensureCustomerId()
如果你想在不产生副作用的情况下获取当前状态(例如,将令牌传入 Hosted Checkout 初始化流程),请使用 peek。如果在进行任何其他会话调用之前,你明确需要有效令牌或身份信息,请使用 ensure。大多数购物车、订单和客户方法已在内部处理这些操作。
环境变量
| 变量 | 必需 | 说明 |
|---|---|---|
CE_STORE_ID / NEXT_PUBLIC_STORE_ID | 是 | 你的商店标识符 |
CE_API_KEY / NEXT_PUBLIC_API_KEY | 是 | Storefront API 密钥 |
CE_ENVIRONMENT / NEXT_PUBLIC_ENVIRONMENT | 否 | staging 或 production |
默认请求头
SDK 在配置中支持 defaultHeaders。这对拥有客户群组、且价格和促销因群组而异的 B2B 商店很有用。
const storefront = createStorefront({
storeId: "...",
apiKey: "...",
defaultHeaders: {
customer_group_id: "01JHS28V83KDWTRBXXJQRTEKA0",
},
session: {
tokenStorage: new BrowserTokenStorage("myapp_"),
},
});
登录后,根据用户资料或 Auth 响应设置 customer_group_id。相关目录方法会自动接收此值。
分析
分析在服务端进行并自动处理。Commerce Engine 按照 Segment 规范收集电商事件。商家可通过 Admin 集成将这些事件路由到 Segment、Rudderstack 或类似工具。商店前端代码无需手动接入分析功能。
常见问题
| 级别 | 问题 | 解决方案 |
|---|---|---|
| 高 | 在购物车/身份验证/客户/订单流程中使用 public() | 对任何实时用户或匿名会话操作,都使用 session() |
| 高 | 将 CookieTokenStorage 用作 SSR 服务端存储 | 使用 @commercengine/ssr-utils 中的 ServerTokenStorage,或使用 Next.js / TanStack Start 的内置包装器 |
| 高 | 在 SSR 应用中跳过 StorefrontBootstrap | 在根布局中挂载一个调用 storefront.bootstrap() 一次的客户端组件 |
| 中 | 在构建/预渲染代码中初始化匿名身份验证 | 改用 public() |
| 中 | 在公共客户端和会话客户端之间重复配置 | 优先使用一个 createStorefront(...) 工厂 |
另请参阅
ssr-patterns/- Next.js 和 TanStack Start 的publicStorefront()/clientStorefront()/serverStorefront()模式ssr/- 使用@commercengine/ssr-utils的自定义 SSR 绑定(Nuxt 和其他不受支持的框架)auth/- 身份验证流程cart-checkout/- Hosted Checkout 同步模式