sales-app-extensibility
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSales App Extensibility
Sales App 扩展性
When this skill applies
适用场景
Use this skill when building, customizing, or deploying extensions for VTEX Sales App.
- Adding features to the cart page (promotions, loyalty, services)
- Adding features to the Product Detail Page (badges, recommendations, warranties)
- Adding features to the menu (user profile, navigation, metrics)
- Integrating external APIs into Sales App extensions
- Generating, scaffolding, or validating extension code for Sales App
Do not use this skill for:
- Regular FastStore storefront customization (use )
faststore-storefront - Building VTEX IO apps (use skills)
vtex-io-* - Sales App core development or framework modifications
当你需要构建、定制或部署VTEX Sales App扩展时使用此技能。
- 为购物车页面添加功能(促销、会员服务、增值服务)
- 为商品详情页(PDP)添加功能(标识、推荐、保修服务)
- 为菜单添加功能(用户资料、导航、数据统计)
- 将外部API集成到Sales App扩展中
- 生成、搭建或验证Sales App扩展代码
请勿将此技能用于:
- 常规FastStore店铺定制(请使用技能)
faststore-storefront - 构建VTEX IO应用(请使用系列技能)
vtex-io-* - Sales App核心开发或框架修改
Prerequisite: FastStore project
先决条件:FastStore 项目
The project root must contain: , , , , .
biome.jsonfaststore.jsonpackage.jsontsconfig.jsonturbo.jsonIf any are missing, STOP. The user must install FastStore first:
bash
npx @vtex/fsp-cli init项目根目录必须包含:、、、、。
biome.jsonfaststore.jsonpackage.jsontsconfig.jsonturbo.json如果缺少任何文件,请停止操作。用户必须先安装FastStore:
bash
npx @vtex/fsp-cli initPrompt: "What is the application name?" → enter name or press Enter for default
提示:"What is the application name?" → 输入应用名称或按回车使用默认值
cd <application-name> && yarn
Documentation: https://beta.fast.store/getting-startedcd <application-name> && yarn
文档:https://beta.fast.store/getting-startedPrerequisite: Sales App module
先决条件:Sales App 模块
Inside the FastStore project, a Sales App workspace must exist (typically at ) with , , and . Check root for a path containing . If missing, STOP:
packages/sales-appsrc/package.jsontsconfig.jsonpackage.json"workspaces"sales-appbash
yarn add @vtex/sales-app -D -W
npx fsp create在FastStore项目中,必须存在Sales App工作区(通常位于),且包含、和。检查根目录的字段,确认是否包含指向的路径。如果缺少,请停止操作:
packages/sales-appsrc/package.jsontsconfig.jsonpackage.json"workspaces"sales-appbash
yarn add @vtex/sales-app -D -W
npx fsp createPrompts: account name → "Sales App" → path (default or custom)
提示:账户名称 → "Sales App" → 路径(默认或自定义)
Then add the path to root package.json "workspaces" array
然后将路径添加到根目录package.json的"workspaces"数组中
yarn install
Documentation: https://beta.fast.store/sales-app/setting-up
**Do NOT proceed to discovery or code generation until both prerequisites are confirmed.**yarn install
文档:https://beta.fast.store/sales-app/setting-up
**在确认两个先决条件都满足之前,请勿进行发现或代码生成步骤。**Decision rules
决策规则
Follow the mandatory 6-step workflow in order. Do not skip steps.
| Step | Purpose | Gate |
|---|---|---|
| 0 | Check prerequisites | FastStore + Sales App installed → proceed; otherwise STOP |
| 1 | Discovery | Understand what the user wants to build |
| 2 | Requirements & Plan | Map requirements → generate plan → wait for user approval |
| 3 | Code Generation & Validation | Generate component + CSS + index.tsx → validate |
| 4 | Documentation | Generate |
| 5 | Local Testing | Provide dev commands and URLs |
| 6 | Build & Deploy | Build command → deployment guide |
请严格按照以下6步工作流执行,不得跳过任何步骤。
| 步骤 | 目的 | 准入条件 |
|---|---|---|
| 0 | 检查先决条件 | 已安装FastStore + Sales App → 继续;否则停止 |
| 1 | 需求发现 | 理解用户想要构建的功能 |
| 2 | 需求与规划 | 梳理需求 → 生成规划 → 等待用户确认 |
| 3 | 代码生成与验证 | 生成组件 + CSS + index.tsx → 验证 |
| 4 | 文档生成 | 生成 |
| 5 | 本地测试 | 提供开发命令和测试URL |
| 6 | 构建与部署 | 提供构建命令 → 部署指南 |
Extension point selection
扩展点选择
| Extension Point | Category | Available Hooks | Layout Shift |
|---|---|---|---|
| Cart | useCart, useExtension | No |
| Cart | useCart, useCartItem, useExtension | Yes |
| Cart | useCart, useExtension | Yes |
| PDP | usePDP, useCart, useExtension | Yes |
| PDP | usePDP, useCart, useExtension | Yes |
| PDP | usePDP, useCart, useExtension | Yes |
| Menu | useExtension | No |
| Menu | useCurrentUser, useExtension | No |
| 扩展点 | 分类 | 可用Hooks | 是否会导致布局偏移 |
|---|---|---|---|
| 购物车 | useCart, useExtension | 否 |
| 购物车 | useCart, useCartItem, useExtension | 是 |
| 购物车 | useCart, useExtension | 是 |
| PDP | usePDP, useCart, useExtension | 是 |
| PDP | usePDP, useCart, useExtension | 是 |
| PDP | usePDP, useCart, useExtension | 是 |
| 菜单 | useExtension | 否 |
| 菜单 | useCurrentUser, useExtension | 否 |
Hook availability
Hook 可用性
- useCart → all cart + PDP extensions
- useCartItem → only
cart.cart-item.after - useCurrentUser → only
menu.drawer-content - usePDP → PDP extensions only
- useExtension → all extension points
- useCart → 所有购物车 + PDP扩展
- useCartItem → 仅适用于
cart.cart-item.after - useCurrentUser → 仅适用于
menu.drawer-content - usePDP → 仅适用于PDP扩展
- useExtension → 所有扩展点
Template selection
模板选择
- No API + no hooks → simple template
- No API + hooks → hook template
- API + no auth → API template
- API + VTEX IO proxy → IO proxy template (recommended)
- API + direct auth → direct auth template (insecure, warn user)
- API doc provided → generate TypeScript interfaces from extracted response shapes; no API doc → use placeholder
${DATA_INTERFACE}
- 无API + 无hooks → 简单模板
- 无API + 有hooks → Hook模板
- 有API + 无鉴权 → API模板
- 有API + VTEX IO代理 → IO代理模板(推荐)
- 有API + 直接鉴权 → 直接鉴权模板(不安全,需提醒用户)
- 提供API文档 → 从提取的响应结构生成TypeScript接口;无API文档 → 使用占位符
${DATA_INTERFACE}
API authentication strategy
API鉴权策略
- Recommended: VTEX IO Proxy App — IO app stores keys server-side. Extension uses with a relative path (
credentials: 'include')./_v/my-api/data - Insecure: Direct Auth — Keys in frontend code, visible in browser. Testing/development only.
- 推荐:VTEX IO代理应用 — IO应用在服务端存储密钥。扩展使用和相对路径(
credentials: 'include')。/_v/my-api/data - 不安全:直接鉴权 — 密钥存于前端代码中,可在浏览器中查看。仅用于测试/开发环境。
Hard constraints
硬性约束
Constraint: Component must return JSX.Element, never null
约束:组件必须返回JSX.Element,绝对不能返回null
defineExtensionsExtensionPointComponentElementElement | nullWhy this matters
Returning causes a TypeScript compilation error. The build will fail.
nullDetection
in any component registered with .
return nulldefineExtensionsCorrect
typescript
export function MyExtension(): JSX.Element {
if (!data) return (<></>);
return <div>{data.value}</div>;
}Wrong
typescript
export function MyExtension(): JSX.Element | null {
if (!data) return null;
return <div>{data.value}</div>;
}defineExtensionsExtensionPointComponentElementElement | null重要性
返回null会导致TypeScript编译错误,构建将失败。
检测方式
任何通过注册的组件中出现。
defineExtensionsreturn null正确示例
typescript
export function MyExtension(): JSX.Element {
if (!data) return (<></>);
return <div>{data.value}</div>;
}错误示例
typescript
export function MyExtension(): JSX.Element | null {
if (!data) return null;
return <div>{data.value}</div>;
}Constraint: Guard optional properties before use
约束:使用可选属性前必须进行校验
CartItem.manualPriceCartItem.productRefIdCartItem.attachmentsWhy this matters
TypeScript strict mode rejects accessing possibly-undefined values.
Detection
, , or without , , , or .
item.manualPriceitem.productRefIditem.attachments?.??&&!= nullCorrect
typescript
const price = item.manualPrice ?? item.sellingPrice;
const refId = item.productRefId ?? 'N/A';
const count = item.attachments?.length ?? 0;Wrong
typescript
const price = item.manualPrice;
const refId = item.productRefId.toUpperCase();
const count = item.attachments.length;CartItem.manualPriceCartItem.productRefIdCartItem.attachments重要性
TypeScript严格模式禁止访问可能未定义的值。
检测方式
使用、或时未使用、、或进行校验。
item.manualPriceitem.productRefIditem.attachments?.??&&!= null正确示例
typescript
const price = item.manualPrice ?? item.sellingPrice;
const refId = item.productRefId ?? 'N/A';
const count = item.attachments?.length ?? 0;错误示例
typescript
const price = item.manualPrice;
const refId = item.productRefId.toUpperCase();
const count = item.attachments.length;Constraint: useCartItem().item may be undefined
约束:useCartItem().item可能为undefined
itemuseCartItem()CartItem | undefinedWhy this matters
Accessing properties on causes a runtime crash.
undefinedDetection
Destructured from used without guard.
itemuseCartItem()if (!item)Correct
typescript
const { item } = useCartItem();
if (!item) return (<></>);
return <div>{item.name}</div>;Wrong
typescript
const { item } = useCartItem();
return <div>{item.name}</div>;从获取的类型为。
useCartItem()itemCartItem | undefined重要性
访问undefined的属性会导致运行时崩溃。
检测方式
从解构的未使用进行校验就直接使用。
useCartItem()itemif (!item)正确示例
typescript
const { item } = useCartItem();
if (!item) return (<></>);
return <div>{item.name}</div>;错误示例
typescript
const { item } = useCartItem();
return <div>{item.name}</div>;Constraint: Never expose authentication keys in frontend code
约束:绝对不能在前端代码中暴露鉴权密钥
API keys in headers are visible in the browser network tab.
fetchWhy this matters
Leaked keys compromise the external service.
Detection
Literal auth header values in : , .
fetch()'x-api-key': '...''Authorization': 'Bearer ...'Correct
typescript
const response = await fetch('/_v/my-api/data', {
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
});Wrong
typescript
const response = await fetch('https://api.example.com/data', {
headers: { 'x-api-key': 'sk-secret-key-12345' },
});fetch重要性
密钥泄露会危及外部服务安全。
检测方式
中出现字面量鉴权头值:、。
fetch()'x-api-key': '...''Authorization': 'Bearer ...'正确示例
typescript
const response = await fetch('/_v/my-api/data', {
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
});错误示例
typescript
const response = await fetch('https://api.example.com/data', {
headers: { 'x-api-key': 'sk-secret-key-12345' },
});Constraint: IO Proxy must use relative paths only
约束:IO代理必须仅使用相对路径
The Sales App internal proxy resolves the domain automatically.
Why this matters
A full URL bypasses the proxy, breaking session cookies and causing CORS errors.
Detection
in IO proxy components.
fetch('https://{account}.myvtex.com/...')Correct
typescript
await fetch('/_v/my-loyalty-api/points', { credentials: 'include' });Wrong
typescript
await fetch('https://myaccount.myvtex.com/_v/my-loyalty-api/points');Sales App内部代理会自动解析域名。
重要性
使用完整URL会绕过代理,破坏会话cookie并导致CORS错误。
检测方式
IO代理组件中出现。
fetch('https://{account}.myvtex.com/...')正确示例
typescript
await fetch('/_v/my-loyalty-api/points', { credentials: 'include' });错误示例
typescript
await fetch('https://myaccount.myvtex.com/_v/my-loyalty-api/points');Constraint: defineExtensions is required in index.tsx
约束:index.tsx中必须使用defineExtensions
Entry point must use from .
defineExtensions@vtex/sales-appWhy this matters
Without it, the build succeeds but no extensions render.
Detection
Missing import or call in .
defineExtensionsindex.tsxCorrect
typescript
import { defineExtensions } from '@vtex/sales-app';
import { MyExtension } from './components/MyExtension';
export default defineExtensions({ 'cart.cart-list.after': MyExtension });Wrong
typescript
import { MyExtension } from './components/MyExtension';
export default { 'cart.cart-list.after': MyExtension };入口文件必须使用中的。
@vtex/sales-appdefineExtensions重要性
如果不使用,构建会成功但扩展无法渲染。
检测方式
中缺少的导入或调用。
index.tsxdefineExtensions正确示例
typescript
import { defineExtensions } from '@vtex/sales-app';
import { MyExtension } from './components/MyExtension';
export default defineExtensions({ 'cart.cart-list.after': MyExtension });错误示例
typescript
import { MyExtension } from './components/MyExtension';
export default { 'cart.cart-list.after': MyExtension };Constraint: Extension point names must match exactly
约束:扩展点名称必须完全匹配
IDs are a fixed set. Non-existent names silently fail.
Why this matters
The extension renders nowhere. No build error — invisible at runtime.
Detection
Any name not in: , , , , , , , .
cart.cart-list.aftercart.cart-item.aftercart.order-summary.afterpdp.sidebar.beforepdp.sidebar.afterpdp.content.aftermenu.itemmenu.drawer-contentCorrect
typescript
defineExtensions({ 'cart.cart-list.after': MyExtension });Wrong
typescript
defineExtensions({ 'cart.list.after': MyExtension });扩展点ID是固定集合,不存在的名称会导致静默失败。
重要性
扩展无法在任何位置渲染,且无构建错误——仅在运行时不可见。
检测方式
使用的名称不在以下列表中:、、、、、、、。
cart.cart-list.aftercart.cart-item.aftercart.order-summary.afterpdp.sidebar.beforepdp.sidebar.afterpdp.content.aftermenu.itemmenu.drawer-content正确示例
typescript
defineExtensions({ 'cart.cart-list.after': MyExtension });错误示例
typescript
defineExtensions({ 'cart.list.after': MyExtension });Constraint: Hooks must be used in compatible extension points
约束:Hooks必须在兼容的扩展点中使用
Each hook has an restriction.
available_inWhy this matters
Hook context is only mounted for specific extension points. Using elsewhere throws runtime errors.
Detection
in PDP/menu. in cart. in menu/cart-list.
useCartItemuseCurrentUserusePDPCorrect
typescript
// useCartItem in cart.cart-item.after ✓
defineExtensions({ 'cart.cart-item.after': ItemWarranty });Wrong
typescript
// useCartItem in pdp.sidebar.after ✗ — will fail at runtime
defineExtensions({ 'pdp.sidebar.after': ItemWarranty });每个Hook都有限制。
available_in重要性
Hook上下文仅在特定扩展点中挂载,在其他位置使用会抛出运行时错误。
检测方式
在PDP/菜单中使用;在购物车中使用;在菜单/购物车列表中使用。
useCartItemuseCurrentUserusePDP正确示例
typescript
// useCartItem 在 cart.cart-item.after 中使用 ✓
defineExtensions({ 'cart.cart-item.after': ItemWarranty });错误示例
typescript
// useCartItem 在 pdp.sidebar.after 中使用 ✗ — 运行时会失败
defineExtensions({ 'pdp.sidebar.after': ItemWarranty });Constraint: Always present execution plan and wait for approval
约束:必须先展示执行计划并等待用户确认
Do not generate code until the user confirms the plan.
Why this matters
Generating without agreement wastes effort and may produce the wrong extension.
Detection
Jumping from discovery to code generation without presenting a plan.
Correct
Discovery → Requirements → Present plan → User approves → Generate code.
Wrong
Discovery → Generate code immediately.
在用户确认计划之前,请勿生成代码。
重要性
未经确认就生成代码会浪费精力,且可能生成不符合需求的扩展。
检测方式
从需求发现直接跳转到代码生成,未展示计划。
正确流程
需求发现 → 需求梳理 → 展示计划 → 用户确认 → 生成代码。
错误流程
需求发现 → 立即生成代码。
Preferred pattern
推荐模式
Workflow overview
工作流概述
Step 0 — Check FastStore + Sales App prerequisites. STOP if missing.
Step 1 — Discovery. Detect use case from keywords, ask follow-up questions, determine API auth strategy. If the user provides API documentation (URL, OpenAPI/Swagger file, Markdown, or inline text), ingest it to extract endpoint details and response shapes — skip the equivalent manual questions. Validate extracted information with the user. Load the discovery reference for detailed question flows and the API Documentation Ingestion section.
Step 2 — Map requirements to extension point + hooks + template. Present plan. Wait for approval.
Step 3 — Generate component, CSS, and index.tsx. Validate against the 10-point checklist. If API documentation was ingested in Step 1, generate TypeScript interfaces from the extracted response shapes and use them in the component instead of the placeholder. If the extension calls 2+ endpoints, extract fetch logic into custom hook(s). Load the code templates reference for all template patterns, the type generation rules, the custom fetch hook pattern, and the types reference for hook return types and TypeScript definitions.
${DATA_INTERFACE}Step 4 — Generate documentation file at inside the Sales App package. Create the folder if it does not exist. The document must contain:
docs/<ExtensionName>.mddocs/- Extension name — title matching the component name.
- Overview — one-paragraph summary of what the extension does and why it was built.
- Extension point — which extension point it registers on (e.g., ) and why that point was chosen.
cart.cart-list.after - Hooks used — list each hook (,
useCart, etc.) with a brief explanation of what data it provides to this extension.usePDP - Component structure — description of the component tree, props, and state management.
- Styling — CSS module file name and summary of key classes.
- API integration (if applicable) — endpoint, auth strategy (IO Proxy or direct), request/response shape.
- Source documentation: URL or file path of the original API documentation, if provided.
- Generated types: list of TypeScript interfaces generated from the API documentation.
- Note which fields are optional () vs required per the documentation.
?
- How to test — dev server command and URL to reach the extension.
- Known constraints — any guards, edge cases, or limitations (e.g., may be undefined).
useCartItem().item
Template for the documentation file:
markdown
undefined步骤0 — 检查FastStore + Sales App先决条件。如果缺少,停止操作。
步骤1 — 需求发现。从关键词中检测用例,提出后续问题,确定API鉴权策略。如果用户提供了API文档(URL、OpenAPI/Swagger文件、Markdown或内联文本),导入文档以提取端点详情和响应结构——跳过相应的手动提问环节。与用户确认提取的信息是否正确。如需详细的提问流程和API文档导入说明,请查看需求发现参考文档。
步骤2 — 将需求映射到扩展点 + Hooks + 模板。展示计划,等待用户确认。
步骤3 — 生成组件、CSS和index.tsx。根据10点检查清单进行验证。如果步骤1中导入了API文档,从提取的响应结构生成TypeScript接口,并在组件中使用这些接口替代占位符。如果扩展调用2个及以上端点,将fetch逻辑提取到自定义Hook中。如需所有模板模式、类型生成规则、自定义fetch Hook模式以及Hook返回类型和TypeScript定义,请查看代码模板参考文档和类型参考文档。
${DATA_INTERFACE}步骤4 — 在Sales App包内生成文档文件。如果文件夹不存在,请创建。文档必须包含以下内容:
docs/<ExtensionName>.mddocs/- 扩展名称 — 与组件名称匹配的标题。
- 概述 — 一段文字总结扩展的功能和构建目的。
- 扩展点 — 扩展注册的位置(例如)以及选择该位置的原因。
cart.cart-list.after - 使用的Hooks — 列出每个Hook(、
useCart等),并简要说明它为该扩展提供了哪些数据。usePDP - 组件结构 — 描述组件树、属性和状态管理方式。
- 样式 — CSS模块文件名和关键类的说明。
- API集成(如适用) — 端点、鉴权策略(IO代理或直接鉴权)、请求/响应结构。
- 源文档:如果提供了原始API文档,请注明其URL或文件路径。
- 生成的类型:列出从API文档生成的TypeScript接口。
- 标注哪些字段是可选()的,哪些是必填的。
?
- 测试方法 — 开发服务器命令和访问扩展的URL。
- 已知约束 — 任何校验规则、边缘情况或限制(例如可能为undefined)。
useCartItem().item
文档文件模板:
markdown
undefined<ExtensionName>
<ExtensionName>
Overview
概述
<One-paragraph description of the extension purpose and value.>
<一段描述扩展用途和价值的文字。>
Extension point
扩展点
- Point:
<extension.point.name> - Rationale: <Why this extension point was selected.>
- 位置:
<extension.point.name> - 选择理由: <选择该扩展点的原因。>
Hooks used
使用的Hooks
| Hook | Purpose |
|---|---|
| <What data it provides here> |
| Hook | 用途 |
|---|---|
| <在此处提供的数据内容> |
Component structure
组件结构
<Describe the component tree, key props, and internal state.>
<描述组件树、关键属性和内部状态。>
Styling
样式
- File:
<ComponentName>.module.css - <Summary of key CSS classes and design decisions.>
- 文件:
<ComponentName>.module.css - <关键CSS类和设计决策的说明。>
API integration
API集成
- Endpoint:
/_v/... - Auth strategy: IO Proxy / Direct / None
- Request/Response: <Brief shape description.>
- 端点:
/_v/... - 鉴权策略: IO代理 / 直接鉴权 / 无
- 请求/响应: <简要描述结构。>
How to test
测试方法
Run and navigate to to verify the extension renders.
yarn fsp dev {account}https://{account}.myvtex.com/sales-app/...运行,并导航到验证扩展是否渲染。
yarn fsp dev {account}https://{account}.myvtex.com/sales-app/...Known constraints
已知约束
- <Guard or limitation 1>
- <Guard or limitation 2>
**Step 5** — Provide local dev commands and test URLs. Load the [dev/build/deploy reference](references/local-dev-build-and-deploy.md).
**Step 6** — Build command and deployment guide. Load the [dev/build/deploy reference](references/local-dev-build-and-deploy.md).- <校验规则或限制1>
- <校验规则或限制2>
**步骤5** — 提供本地开发命令和测试URL。如需详细信息,请查看[开发/构建/部署参考文档](references/local-dev-build-and-deploy.md)。
**步骤6** — 提供构建命令和部署指南。如需详细信息,请查看[开发/构建/部署参考文档](references/local-dev-build-and-deploy.md)。Reference Files
参考文件
Load these on demand based on what the task requires. Do not load all of them upfront.
| File | Load when… |
|---|---|
| references/extension-points-hooks-and-types.md | Choosing an extension point, selecting hooks, looking up TypeScript types ( |
| references/code-templates-and-patterns.md | Generating extension code — simple, hook, API, IO Proxy, or Direct Auth templates; CSS module pattern; |
| references/discovery-and-use-cases.md | Running Step 1 (Discovery) — use case detection keywords, follow-up questions, API auth decision tree, IO Proxy vs Direct Auth flow |
| references/local-dev-build-and-deploy.md | Running Steps 5–6 — dev server commands, test URLs, build command, common build errors, FastStore WebOps deployment, monitoring, rollback |
根据任务需求按需加载这些文件,无需预先全部加载。
| 文件 | 加载时机 |
|---|---|
| references/extension-points-hooks-and-types.md | 选择扩展点、挑选Hooks、查询TypeScript类型( |
| references/code-templates-and-patterns.md | 生成扩展代码时——简单模板、Hook模板、API模板、IO代理模板或直接鉴权模板;CSS模块模式;使用 |
| references/discovery-and-use-cases.md | 执行步骤1(需求发现)时——用例检测关键词、后续问题、API鉴权决策树、IO代理与直接鉴权流程 |
| references/local-dev-build-and-deploy.md | 执行步骤5-6时——开发服务器命令、测试URL、构建命令、常见构建错误、FastStore WebOps部署、监控、回滚 |
Common failure modes
常见失败模式
- Returning null instead of empty fragment — not allowed; use
return null. Build fails.return (<></>) - Accessing item.manualPrice without guard — TypeScript "possibly undefined" error. Use .
?? - Using useCartItem outside cart.cart-item.after — Hook context only exists there. Runtime error.
- Hardcoding auth tokens in frontend fetch — Keys visible in browser. Use VTEX IO proxy.
- Using full URL with IO Proxy — Bypasses internal proxy. Use relative path .
/_v/... - Placing code outside packages/sales-app/src/ — Not included in build.
- Missing defineExtensions in index.tsx — Extension compiles but never renders.
- Skipping prerequisite checks — Generating code without FastStore/Sales App installed.
- Not presenting plan — User may want a different approach. Always confirm.
- Invented extension point names — instead of
cart.list.afterfails silently.cart.cart-list.after - Skipping documentation — Extension generated without . Future developers won't understand the extension's purpose, hooks, or constraints.
docs/<ExtensionName>.md - Inventing API response types — Generated interface doesn't match actual API. If documentation was provided, derive types from it; if not, ask the user for a sample JSON response.
- Ignoring provided API documentation — User provided a URL or file but agent asked manual questions anyway. Always check for documentation first and use the API Documentation Ingestion flow.
- Inline fetch with 2+ endpoints — Multiple calls inside the component body. Extract into custom hook(s) in
fetch.hooks/use{Purpose}.ts
- 返回null而非空片段 — 不允许;请使用
return null。构建会失败。return (<></>) - 未校验就访问item.manualPrice — TypeScript提示"可能未定义"错误。请使用。
?? - 在cart.cart-item.after之外使用useCartItem — Hook上下文仅在该扩展点存在。运行时会出错。
- 在前端fetch中硬编码鉴权令牌 — 密钥可在浏览器中查看。请使用VTEX IO代理。
- IO代理使用完整URL — 绕过内部代理。请使用相对路径。
/_v/... - 代码放在packages/sales-app/src/之外 — 不会被包含在构建中。
- index.tsx中缺少defineExtensions — 扩展编译成功但无法渲染。
- 跳过先决条件检查 — 在未安装FastStore/Sales App的情况下生成代码。
- 未展示计划 — 用户可能需要不同的实现方式。请务必先确认。
- 使用不存在的扩展点名称** — 例如使用而非
cart.list.after会导致静默失败。cart.cart-list.after - 跳过文档生成 — 生成的扩展没有。后续开发者无法理解扩展的用途、使用的Hooks或约束。
docs/<ExtensionName>.md - 自行编写API响应类型 — 生成的接口与实际API不匹配。如果提供了文档,请从中推导类型;如果没有,请向用户索要JSON响应示例。
- 忽略用户提供的API文档 — 用户提供了URL或文件,但仍手动提问。请始终先检查是否有文档,并使用API文档导入流程。
- 在组件中内联多个fetch调用 — 组件体内有2个及以上调用。请将逻辑提取到
fetch中的自定义Hook。hooks/use{Purpose}.ts
Review checklist
检查清单
- FastStore installed (biome.json, faststore.json, package.json, tsconfig.json, turbo.json)?
- Sales App module installed (src/, package.json, tsconfig.json in sales-app directory)?
- Discovery completed and use case identified?
- Execution plan approved by user?
- Extension point is valid (from the 8-point reference)?
- Hooks compatible with chosen extension point?
- Component returns JSX.Element, never null?
- Optional properties guarded (manualPrice, productRefId, attachments)?
- useCartItem().item checked for undefined?
- No auth credentials exposed in frontend code?
- IO Proxy uses relative path (/_v/...)?
- defineExtensions configured in index.tsx?
- CSS file path matches component name?
- Documentation generated at ?
docs/<ExtensionName>.md - Documentation covers overview, extension point, hooks, structure, and constraints?
- If API documentation was provided, TypeScript interfaces match the documented response shape?
- If 2+ API endpoints used, fetch logic extracted into custom hook(s) in ?
hooks/ - Build passes: ?
yarn fsp build {account} sales-app - Tested locally: ?
yarn fsp dev {account}
- 已安装FastStore(包含biome.json、faststore.json、package.json、tsconfig.json、turbo.json)?
- 已安装Sales App模块(sales-app目录下有src/、package.json、tsconfig.json)?
- 已完成需求发现并确定用例?
- 执行计划已获得用户确认?
- 扩展点有效(属于8个参考扩展点之一)?
- Hooks与所选扩展点兼容?
- 组件返回JSX.Element,从未返回null?
- 可选属性已校验(manualPrice、productRefId、attachments)?
- 已检查useCartItem().item是否为undefined?
- 前端代码中未暴露鉴权凭证?
- IO代理使用了相对路径(/_v/...)?
- index.tsx中配置了defineExtensions?
- CSS文件路径与组件名称匹配?
- 已在生成文档?
docs/<ExtensionName>.md - 文档涵盖了概述、扩展点、Hooks、结构和约束?
- 如果提供了API文档,TypeScript接口与文档中的响应结构匹配?
- 如果使用了2个及以上API端点,fetch逻辑已提取到hooks/中的自定义Hook?
- 构建通过:?
yarn fsp build {account} sales-app - 已在本地测试:?
yarn fsp dev {account}
Related skills
相关技能
- — storefront customization outside Sales App
faststore-storefront - — building VTEX IO proxy apps for secure API integration
vtex-io-app-contract
- — Sales App之外的店铺定制
faststore-storefront - — 构建用于安全API集成的VTEX IO代理应用
vtex-io-app-contract
Reference
参考链接
- Sales App setup: https://beta.fast.store/sales-app/setting-up
- FastStore getting started: https://beta.fast.store/getting-started
- VTEX Sales App documentation: https://help.vtex.com/en/tracks/instore-getting-started-and-setting-up
- VTEX IO app development: https://developers.vtex.com/docs/guides/vtex-io-documentation-developing-an-app