vtex-io-app-contract
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseApp Contract & Builder Boundaries
应用契约与Builder边界
When this skill applies
本技能适用场景
Use this skill when the main decision is about what a VTEX IO app is, what capabilities it declares, and which integration boundaries it publishes through .
manifest.json- Creating a new VTEX IO app and defining its initial contract
- Adding or removing builders to match app capabilities
- Choosing between and
dependenciespeerDependencies - Deciding whether a capability belongs in the current app or should move to another app
- Troubleshooting link or publish failures caused by manifest-level contract issues
Do not use this skill for:
- service runtime behavior such as , memory, workers, or route exposure
service.json - HTTP handler implementation, middleware composition, or event processing
- GraphQL schema, resolver, or data-fetching implementation
- storefront, admin, or render-runtime frontend behavior
- policy modeling and security boundary enforcement
当你需要决策VTEX IO应用的定位、声明的能力、以及通过对外发布的集成边界时,可使用本技能:
manifest.json- 创建新的VTEX IO应用并定义其初始契约
- 添加或移除builder以匹配应用能力
- 选择使用还是
dependenciespeerDependencies - 决策某项能力是否应该归属当前应用,还是迁移到其他应用
- 排查manifest层面契约问题导致的link或发布失败
请勿将本技能用于以下场景:
- 服务运行时行为配置,比如、内存、worker或路由暴露
service.json - HTTP handler实现、中间件组合或事件处理
- GraphQL schema、resolver或数据获取实现
- 店铺前端、管理后台、render-runtime前端行为
- 权限建模与安全边界执行
Decision rules
决策规则
- Treat as the app contract. It declares identity, builders, dependencies, peer dependencies, and high-level capabilities that other apps or the platform rely on.
manifest.json - Add a builder only when the app truly owns that capability. Builders are not placeholders for future work.
- Keep the contract narrow. If a manifest starts to represent unrelated concerns, split those concerns into separate apps instead of creating a catch-all app.
- Use only for apps that can be safely auto-installed as part of the current app contract. Use
dependenciesfor apps that must already exist in the environment, remain externally managed, or declarepeerDependencies.billingOptions - Keep naming and versioning publishable: ,
vendor, andnamemust form a stable identity that can be linked, published, and consumed safely.version - Keep aligned with the commercial contract of the app. If the app has billing implications, declare them explicitly in the manifest rather than leaving pricing behavior implicit.
billingOptions - Apps that declare cannot be consumed through
billingOptions. If the current app requires a billable app, model that relationship withdependenciesand require manual installation by the account or edition owner.peerDependencies - Edition apps are compositions of app contracts, not exceptions to them. Keep each underlying app contract explicit, narrow, and semver-safe so composition stays predictable across host environments.
- can also declare app-level permissions and configuration surfaces, but detailed policy modeling belongs in security-focused skills and detailed
manifest.jsondesign belongs in app-settings skills.settingsSchema
This is not an exhaustive list of builders; see the official Builders docs for the full catalog.
Builder ownership reference:
| Builder | Own this builder when the app contract includes |
|---|---|
| backend runtime capability owned by this app |
| GraphQL schema exposure owned by this app |
| React bundles owned by this app |
| Admin UI surfaces owned by this app |
| Store Framework block registration owned by this app |
| localized message bundles owned by this app |
| storefront pixel injection owned by this app |
| Master Data schema assets owned by this app |
Contract boundary heuristic:
- If the capability is shipped, versioned, and maintained with this app, declare its builder here.
- If the capability is only consumed from another app, declare a dependency instead of duplicating the builder.
- If the capability introduces a separate runtime, security model, or release cadence, consider splitting it into another app.
- 将视作应用契约,它声明了应用标识、builder、依赖、peer依赖,以及其他应用或平台依赖的上层能力
manifest.json - 仅当应用实际拥有对应能力时才添加builder,builder不能作为未来功能的占位符
- 保持契约范围收敛:如果manifest开始承载无关的职责,将这些职责拆分到独立应用,而不是创建一个包揽所有功能的应用
- 仅对可以作为当前应用契约的一部分、能够安全自动安装的应用使用;对于必须提前存在于环境中、由外部管理、或者声明了
dependencies的应用,使用billingOptionspeerDependencies - 保持命名和版本可发布:、
vendor、name必须构成稳定的标识,能够被安全地link、发布和消费version - 保持与应用的商业契约对齐:如果应用涉及计费,必须在manifest中显式声明,而不是让定价行为隐式存在
billingOptions - 声明了的应用不能通过
billingOptions被依赖:如果当前应用需要一款付费应用,使用dependencies来声明该关系,并要求账号或版本所有者手动安装peerDependencies - 版本应用是应用契约的组合,而非契约的例外:保持每个底层应用契约显式、范围收敛、符合semver规范,这样组合后的应用在不同宿主环境中行为都是可预测的
- 也可以声明应用级别的权限和配置项,但详细的权限建模属于安全相关技能的范畴,详细的
manifest.json设计属于应用配置相关技能的范畴settingsSchema
本列表并未涵盖所有builder,完整目录请查阅官方Builder文档。
builder所有权参考:
| Builder | 当应用契约包含以下内容时可使用该builder |
|---|---|
| 本应用拥有的后端运行时能力 |
| 本应用拥有的GraphQL schema暴露能力 |
| 本应用拥有的React包 |
| 本应用拥有的Admin UI界面 |
| 本应用拥有的Store Framework块注册能力 |
| 本应用拥有的国际化文案包 |
| 本应用拥有的店铺前端pixel注入能力 |
| 本应用拥有的Master Data schema资源 |
契约边界判断规则:
- 如果某项能力是随当前应用一起发布、版本管理和维护的,在这里声明对应的builder
- 如果某项能力只是从其他应用消费的,声明依赖即可,不要重复声明builder
- 如果某项能力引入了独立的运行时、安全模型或发布节奏,考虑将其拆分到另一个应用
Hard constraints
硬性约束
Constraint: Every shipped capability must be declared in the manifest contract
约束:所有发布的能力都必须在manifest契约中声明
If the app ships a processable VTEX IO capability, MUST declare the corresponding builder. Do not rely on folder presence alone, and do not assume VTEX IO infers capabilities from the repository structure.
Symmetrically, do not declare builders for capabilities that are not actually shipped by this app.
manifest.jsonWhy this matters
VTEX IO compiles and links apps based on declared builders, not on intent. If the builder is missing, the platform ignores that capability and the app contract becomes misleading. The app may link partially while the expected feature is absent.
Detection
If you see a maintained , , , , , , , or directory, STOP and verify that the matching builder exists in . If the builder exists but the capability does not, STOP and remove the builder or move the capability back into scope.
/node/react/graphql/admin/store/messages/pixel/masterdatamanifest.jsonCorrect
json
{
"vendor": "acme",
"name": "reviews-platform",
"version": "0.4.0",
"builders": {
"node": "7.x",
"graphql": "1.x",
"messages": "1.x"
}
}Wrong
json
{
"vendor": "acme",
"name": "reviews-platform",
"version": "0.4.0",
"builders": {
"messages": "1.x"
}
}The app ships backend and GraphQL capabilities but declares only , so the runtime contract is incomplete and the platform ignores the missing builders.
messages如果应用发布了可处理的VTEX IO能力, 必须 声明对应的builder。不要仅依赖文件夹存在,也不要假设VTEX IO会从仓库结构推断能力。
反过来,也不要声明应用实际未发布的能力对应的builder。
manifest.json为什么这很重要
VTEX IO基于声明的builder而非意图来编译和link应用,如果缺少对应的builder,平台会忽略相关能力,应用契约也会产生误导。应用可能只会部分link成功,而预期的功能会缺失。
检查方式
如果你看到有维护中的、、、、、、或目录,停下检查中是否存在对应的builder。如果声明了builder但实际没有对应能力,停下移除builder,或者将对应能力放回当前应用范围。
/node/react/graphql/admin/store/messages/pixel/masterdatamanifest.json正确示例
json
{
"vendor": "acme",
"name": "reviews-platform",
"version": "0.4.0",
"builders": {
"node": "7.x",
"graphql": "1.x",
"messages": "1.x"
}
}错误示例
json
{
"vendor": "acme",
"name": "reviews-platform",
"version": "0.4.0",
"builders": {
"messages": "1.x"
}
}该应用发布了后端和GraphQL能力,但仅声明了,因此运行时契约不完整,平台会忽略缺失的builder。
messagesConstraint: App identity and versioning must stay publishable and semver-safe
约束:应用标识和版本必须可发布,且符合semver规范
The , , and fields MUST identify a valid VTEX IO app contract. Use kebab-case for the app name, keep the vendor consistent with ownership, and use full semantic versioning.
vendornameversionWhy this matters
Consumers, workspaces, and release flows rely on app identity stability. Invalid names or incomplete versions break linking and publishing, while identity drift creates unsafe upgrades and hard-to-debug dependency mismatches.
Detection
If you see uppercase characters, underscores, non-semver versions, or vendor/name changes mixed into unrelated work, STOP and validate whether the change is intentional and release-safe.
Correct
json
{
"vendor": "acme",
"name": "order-status-dashboard",
"version": "2.1.0"
}Wrong
json
{
"vendor": "AcmeTeam",
"name": "Order_Status_Dashboard",
"version": "2.1"
}This identity is not safely publishable because the name is not kebab-case and the version is not valid semver.
vendornameversion为什么这很重要
消费者、工作区和发布流程依赖稳定的应用标识。无效的名称或不完整的版本会破坏link和发布流程,而标识变更会导致不安全的升级和难以排查的依赖不匹配问题。
检查方式
如果你看到大写字符、下划线、不符合semver的版本,或者与无关变更混合在一起的vendor/名称变更,停下确认该变更是否是故意的、是否符合发布安全要求。
正确示例
json
{
"vendor": "acme",
"name": "order-status-dashboard",
"version": "2.1.0"
}错误示例
json
{
"vendor": "AcmeTeam",
"name": "Order_Status_Dashboard",
"version": "2.1"
}该标识无法安全发布,因为名称不符合kebab-case格式,版本也不是有效的semver版本。
Constraint: Dependencies and peerDependencies must express installation intent correctly
约束:dependencies和peerDependencies必须准确表达安装意图
Use only for apps that this app should install as part of its contract and that can be auto-installed safely. Use for apps that must already be present in the environment, should remain externally managed, or declare .
dependenciespeerDependenciesbillingOptionsWhy this matters
This is the core contract boundary between your app and the rest of the VTEX IO workspace. Misclassifying a relationship causes broken installations, hidden coupling, and environment-specific behavior that only appears after link or publish. In particular, builder-hub rejects dependencies on apps that declare .
billingOptionsDetection
If the app requires another app to function in every environment, STOP and confirm whether it belongs in or . If the target app declares , STOP and move it to . If the app only integrates with a platform capability, host app, edition-managed app, or paid app that the account is expected to manage manually, STOP and keep it out of .
dependenciespeerDependenciesbillingOptionspeerDependenciesdependenciesCorrect
json
{
"dependencies": {
"vtex.search-graphql": "0.x"
},
"peerDependencies": {
"vtex.store": "2.x",
"vtex.paid-app-example": "1.x"
}
}Wrong
json
{
"dependencies": {
"vtex.store": "2.x",
"vtex.paid-app-example": "1.x"
},
"peerDependencies": {}
}This contract hard-installs a host app that should usually be externally managed and also attempts to auto-install a billable app, which builder-hub rejects.
仅对作为当前应用契约的一部分、可以安全自动安装的应用使用;对于必须提前存在于环境中、由外部管理、或者声明了的应用,使用。
dependenciesbillingOptionspeerDependencies为什么这很重要
这是你的应用与VTEX IO工作区其他部分的核心契约边界。错误分类依赖关系会导致安装失败、隐式耦合,以及只有在link或发布后才会出现的环境特定行为。尤其是builder-hub会拒绝对声明了的应用的依赖。
billingOptions检查方式
如果应用需要依赖另一个应用才能在所有环境中运行,停下确认它应该属于还是。如果目标应用声明了,停下将其移动到。如果应用仅与平台能力、宿主应用、版本管理的应用、或者需要账号手动管理的付费应用集成,停下不要将其放入。
dependenciespeerDependenciesbillingOptionspeerDependenciesdependencies正确示例
json
{
"dependencies": {
"vtex.search-graphql": "0.x"
},
"peerDependencies": {
"vtex.store": "2.x",
"vtex.paid-app-example": "1.x"
}
}错误示例
json
{
"dependencies": {
"vtex.store": "2.x",
"vtex.paid-app-example": "1.x"
},
"peerDependencies": {}
}该契约强制安装了通常应该由外部管理的宿主应用,还尝试自动安装付费应用,会被builder-hub拒绝。
Preferred pattern
推荐模式
Start by deciding the smallest useful contract for the app, then declare only the identity and builders required for that contract.
Recommended manifest for a focused service-plus-GraphQL app:
json
{
"vendor": "acme",
"name": "reviews-platform",
"version": "0.1.0",
"title": "Reviews Platform",
"description": "VTEX IO app that owns review APIs and review GraphQL exposure",
"builders": {
"node": "7.x",
"graphql": "1.x",
"messages": "1.x"
},
"billingOptions": {
"type": "free"
},
"dependencies": {
"vtex.search-graphql": "0.x"
},
"peerDependencies": {
"vtex.store": "2.x"
}
}Recommended contract split:
text
reviews-platform/
├── manifest.json # identity, builders, dependencies, peerDependencies
├── node/ # backend capability owned by this app
├── graphql/ # GraphQL capability owned by this app
└── messages/ # app-owned translations
reviews-storefront/
├── manifest.json # separate release surface for storefront concerns
├── react/
└── store/Use this split when the backend/API contract and the storefront contract have different ownership, release cadence, or integration boundaries.
首先确定应用最小的可用契约,然后仅声明该契约所需的标识和builder。
聚焦于服务+GraphQL能力的应用的推荐manifest配置:
json
{
"vendor": "acme",
"name": "reviews-platform",
"version": "0.1.0",
"title": "Reviews Platform",
"description": "VTEX IO app that owns review APIs and review GraphQL exposure",
"builders": {
"node": "7.x",
"graphql": "1.x",
"messages": "1.x"
},
"billingOptions": {
"type": "free"
},
"dependencies": {
"vtex.search-graphql": "0.x"
},
"peerDependencies": {
"vtex.store": "2.x"
}
}推荐的契约拆分方式:
text
reviews-platform/
├── manifest.json # 标识、builder、dependencies、peerDependencies
├── node/ # 本应用拥有的后端能力
├── graphql/ # 本应用拥有的GraphQL能力
└── messages/ # 应用自有翻译文案
reviews-storefront/
├── manifest.json # 店铺前端相关的独立发布入口
├── react/
└── store/当后端/API契约和店铺前端契约归属不同、发布节奏不同、或者集成边界不同时,使用这种拆分方式。
Common failure modes
常见失败场景
- Declaring builders for aspirational capabilities that the app does not yet own, which makes the contract broader than the real implementation.
- Using one large manifest to represent backend runtime, frontend rendering, settings, policies, and integration concerns that should be separated into multiple skills or apps.
- Putting host-level apps in when they should remain
dependencies.peerDependencies - Pinning exact dependency versions instead of major-version ranges such as ,
0.x, or1.x.3.x - Treating as a dumping ground for runtime or security details that belong in more specific skills.
manifest.json - Modeling here instead of using this skill only to decide whether app-level configuration belongs in the contract at all.
settingsSchema
- 为应用尚未拥有的预期能力声明builder,导致契约范围大于实际实现
- 使用一个大的manifest承载本应拆分到多个技能或应用的后端运行时、前端渲染、配置、权限、集成相关的职责
- 将宿主级应用放在中,而它们本应属于
dependenciespeerDependencies - 固定依赖的精确版本,而不是使用主版本范围比如、
0.x或1.x3.x - 将当作运行时或安全细节的回收站,这些内容本应属于更具体的技能范畴
manifest.json - 在这里设计,而本技能仅用于决策应用级配置是否应该属于契约的一部分
settingsSchema
Review checklist
审核检查清单
- Does the manifest describe only capabilities this app actually owns and ships?
- Does every shipped capability have a matching builder declaration?
- Is the app identity publishable: valid , kebab-case
vendor, and full semvername?version - If the app has billing behavior, is explicit and aligned with the app contract?
billingOptions - Are and
dependenciesseparated by installation intent?peerDependencies - Would splitting the contract into two apps reduce unrelated concerns or release coupling?
- Are runtime, route, GraphQL implementation, frontend, and security details kept out of this skill?
- manifest是否仅描述了应用实际拥有和发布的能力?
- 所有发布的能力都有对应的builder声明吗?
- 应用标识可发布吗:有效、
vendor符合kebab-case、name是完整的semver版本?version - 如果应用有计费逻辑,是否显式声明且与应用契约对齐?
billingOptions - 和
dependencies是否按照安装意图正确区分?peerDependencies - 将契约拆分为两个应用是否能减少无关职责或发布耦合?
- 运行时、路由、GraphQL实现、前端、安全相关的细节是否没有出现在本技能范围内?
Reference
参考资料
- Manifest - Complete reference for fields
manifest.json - Builders - Builder catalog and capability mapping
- Dependencies - Dependency and peer dependency behavior in VTEX IO
- Billing Options - How app billing behavior is declared in the manifest
- Creating the New App - App initialization flow and manifest basics
- Manifest - 字段完整参考
manifest.json - Builders - builder目录与能力映射
- Dependencies - VTEX IO中依赖与peer依赖的行为说明
- Billing Options - 如何在manifest中声明应用计费行为
- 创建新应用 - 应用初始化流程与manifest基础说明