vtex-io-app-structure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

App Architecture & Manifest Configuration

应用架构与Manifest配置

When this skill applies

本技能的适用场景

Use this skill when working with the foundational structure of a VTEX IO app — the
manifest.json
file, builder system, policy declarations, dependency management,
service.json
resource limits, and app lifecycle (link, publish, deploy).
  • Creating a new VTEX IO app from scratch
  • Adding a builder to an existing app
  • Configuring policies for API access
  • Troubleshooting deployment failures related to manifest misconfiguration
Do not use this skill for:
  • Backend service implementation details (use
    vtex-io-service-apps
    instead)
  • React component development (use
    vtex-io-react-apps
    instead)
  • GraphQL schema and resolver details (use
    vtex-io-graphql-api
    instead)
当你处理VTEX IO应用的基础结构时,可使用本技能——包括
manifest.json
文件、构建器系统、策略声明、依赖管理、
service.json
资源限制,以及应用生命周期(link、publish、deploy)相关操作。
  • 从零开始创建新的VTEX IO应用
  • 为现有应用添加构建器
  • 配置API访问策略
  • 排查与manifest配置错误相关的部署故障
请勿在以下场景使用本技能:
  • 后端服务实现细节(请使用
    vtex-io-service-apps
    技能)
  • React组件开发(请使用
    vtex-io-react-apps
    技能)
  • GraphQL模式与解析器细节(请使用
    vtex-io-graphql-api
    技能)

Decision rules

决策规则

  • Every VTEX IO app starts with
    manifest.json
    — it defines identity (
    vendor
    ,
    name
    ,
    version
    ), builders, dependencies, and policies.
  • Use the builder that matches the directory:
    node
    for
    /node
    ,
    react
    for
    /react
    ,
    graphql
    for
    /graphql
    ,
    admin
    for
    /admin
    ,
    pixel
    for
    /pixel
    ,
    messages
    for
    /messages
    ,
    store
    for
    /store
    ,
    masterdata
    for
    /masterdata
    ,
    styles
    for
    /styles
    .
  • Declare policies for every external host your app calls and every VTEX Admin resource it accesses.
  • Use
    service.json
    in
    /node
    to configure memory (max 512MB), timeout, autoscaling, and route definitions.
  • Use semver ranges (
    3.x
    ) for dependencies, not exact versions.
  • Use
    peerDependencies
    for apps that must be present but should not be auto-installed.
Builders reference:
BuilderDirectoryPurpose
node
/node
Backend services in TypeScript (middlewares, resolvers, event handlers)
react
/react
Frontend React components in TypeScript/TSX
graphql
/graphql
GraphQL schema definitions (
.graphql
files)
admin
/admin
Admin panel pages and navigation entries
pixel
/pixel
Pixel/tracking apps that inject scripts into the storefront
messages
/messages
Internationalization — localized string files per locale
store
/store
Store Framework theme blocks, interfaces, and routes
masterdata
/masterdata
Master Data v2 entity schemas and triggers
styles
/styles
CSS/Tachyons configuration for Store Framework themes
Policy types:
  1. Outbound-access policies: Grant access to explicit URLs (external APIs or VTEX endpoints).
  2. License Manager policies: Grant access to VTEX Admin resources using resource keys.
  3. App role-based policies: Grant access to routes or GraphQL queries exposed by other IO apps, using the format
    {vendor}.{app-name}:{policy-name}
    .
Architecture:
text
manifest.json
├── builders → determines which directories are processed
│   ├── node/ → compiled by node builder → backend service
│   ├── react/ → compiled by react builder → frontend bundles
│   ├── graphql/ → compiled by graphql builder → schema/resolvers
│   ├── store/ → compiled by store builder → theme blocks
│   ├── admin/ → compiled by admin builder → admin pages
│   ├── pixel/ → compiled by pixel builder → tracking scripts
│   └── messages/ → compiled by messages builder → i18n strings
├── policies → runtime permissions for API access
├── dependencies → other VTEX IO apps this app requires
└── peerDependencies → apps required but not auto-installed
  • 每个VTEX IO应用都以
    manifest.json
    为起点——它定义了应用标识(
    vendor
    name
    version
    )、构建器、依赖项和策略。
  • 使用与目录对应的构建器:
    node
    对应
    /node
    目录,
    react
    对应
    /react
    目录,
    graphql
    对应
    /graphql
    目录,
    admin
    对应
    /admin
    目录,
    pixel
    对应
    /pixel
    目录,
    messages
    对应
    /messages
    目录,
    store
    对应
    /store
    目录,
    masterdata
    对应
    /masterdata
    目录,
    styles
    对应
    /styles
    目录。
  • 为应用调用的每个外部主机以及访问的每个VTEX Admin资源声明策略。
  • /node
    目录中使用
    service.json
    配置内存(最大512MB)、超时时间、自动扩容和路由定义。
  • 依赖项使用语义化版本范围(如
    3.x
    ),而非精确版本。
  • 对于必须存在但无需自动安装的应用,使用
    peerDependencies
构建器参考:
构建器目录用途
node
/node
TypeScript编写的后端服务(中间件、解析器、事件处理器)
react
/react
TypeScript/TSX编写的前端React组件
graphql
/graphql
GraphQL模式定义(
.graphql
文件)
admin
/admin
管理面板页面与导航入口
pixel
/pixel
注入到店铺前端的像素/追踪应用脚本
messages
/messages
国际化——各语言环境的本地化字符串文件
store
/store
Store Framework主题区块、接口与路由
masterdata
/masterdata
Master Data v2实体模式与触发器
styles
/styles
Store Framework主题的CSS/Tachyons配置
策略类型:
  1. 出站访问策略:授予对指定URL(外部API或VTEX端点)的访问权限。
  2. 许可证管理器策略:使用资源密钥授予对VTEX Admin资源的访问权限。
  3. 应用基于角色的策略:授予对其他IO应用暴露的路由或GraphQL查询的访问权限,格式为
    {vendor}.{app-name}:{policy-name}
架构:
text
manifest.json
├── builders → 决定哪些目录会被处理
│   ├── node/ → 由node构建器编译 → 后端服务
│   ├── react/ → 由react构建器编译 → 前端包
│   ├── graphql/ → 由graphql构建器编译 → 模式/解析器
│   ├── store/ → 由store构建器编译 → 主题区块
│   ├── admin/ → 由admin构建器编译 → 管理页面
│   ├── pixel/ → 由pixel构建器编译 → 追踪脚本
│   └── messages/ → 由messages构建器编译 → 国际化字符串
├── policies → API访问的运行时权限
├── dependencies → 本应用依赖的其他VTEX IO应用
└── peerDependencies → 必需但不自动安装的应用

Hard constraints

硬性约束

Constraint: Declare All Required Builders

约束:声明所有必需的构建器

Every directory in your app that contains processable code MUST have a corresponding builder declared in
manifest.json
. If you have a
/node
directory, the
node
builder MUST be declared. If you have a
/react
directory, the
react
builder MUST be declared.
Why this matters
Without the builder declaration, the VTEX IO platform ignores the directory entirely. Your backend code will not compile, your React components will not render, and your GraphQL schemas will not be registered. The app will link successfully but the functionality will silently be absent.
Detection
If you see backend TypeScript code in a
/node
directory but the manifest does not declare
"node": "7.x"
in
builders
, STOP and add the builder. Same applies to
/react
without
"react": "3.x"
,
/graphql
without
"graphql": "1.x"
, etc.
Correct
json
{
  "name": "my-service-app",
  "vendor": "myvendor",
  "version": "1.0.0",
  "title": "My Service App",
  "description": "A backend service app with GraphQL",
  "builders": {
    "node": "7.x",
    "graphql": "1.x",
    "docs": "0.x"
  },
  "dependencies": {},
  "policies": []
}
Wrong
json
{
  "name": "my-service-app",
  "vendor": "myvendor",
  "version": "1.0.0",
  "title": "My Service App",
  "description": "A backend service app with GraphQL",
  "builders": {
    "docs": "0.x"
  },
  "dependencies": {},
  "policies": []
}
Missing "node" and "graphql" builders — the /node and /graphql directories will be completely ignored. Backend code won't compile, GraphQL schema won't be registered. The app links without errors but nothing works.

应用中每个包含可处理代码的目录,必须在
manifest.json
中声明对应的构建器。如果你的应用有
/node
目录,就必须声明
node
构建器;如果有
/react
目录,就必须声明
react
构建器。
为什么这很重要
如果没有声明构建器,VTEX IO平台会完全忽略该目录。你的后端代码将无法编译,React组件无法渲染,GraphQL模式也不会被注册。应用可以成功link,但功能会缺失且无任何提示。
检测方法
如果你在
/node
目录中看到后端TypeScript代码,但manifest的
builders
中未声明
"node": "7.x"
,请立即添加该构建器。同理,
/react
目录对应
"react": "3.x"
/graphql
目录对应
"graphql": "1.x"
等。
正确示例
json
{
  "name": "my-service-app",
  "vendor": "myvendor",
  "version": "1.0.0",
  "title": "My Service App",
  "description": "A backend service app with GraphQL",
  "builders": {
    "node": "7.x",
    "graphql": "1.x",
    "docs": "0.x"
  },
  "dependencies": {},
  "policies": []
}
错误示例
json
{
  "name": "my-service-app",
  "vendor": "myvendor",
  "version": "1.0.0",
  "title": "My Service App",
  "description": "A backend service app with GraphQL",
  "builders": {
    "docs": "0.x"
  },
  "dependencies": {},
  "policies": []
}
缺少"node"和"graphql"构建器——
/node
/graphql
目录会被完全忽略。后端代码无法编译,GraphQL模式不会被注册。应用可以成功link,但所有功能都无法正常工作。

Constraint: Declare Policies for All External Access

约束:为所有外部访问声明策略

Every external API call or VTEX resource access MUST have a corresponding policy in
manifest.json
. This includes outbound HTTP calls to external hosts, VTEX Admin resource access, and consumption of other apps' GraphQL APIs.
Why this matters
VTEX IO sandboxes apps for security. Without the proper policy, any outbound HTTP request will be blocked at the infrastructure level, returning a
403 Forbidden
error. This is not a code issue — it is a platform-level restriction.
Detection
If you see code making API calls (via clients or HTTP) to a host, STOP and verify that an
outbound-access
policy exists for that host in the manifest. If you see
licenseManager.canAccessResource(...)
, verify a License Manager policy exists.
Correct
json
{
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "outbound-access",
      "attrs": {
        "host": "portal.vtexcommercestable.com.br",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    },
    {
      "name": "colossus-fire-event"
    },
    {
      "name": "colossus-write-logs"
    }
  ]
}
Wrong
json
{
  "policies": []
}
Empty policies array while the app makes calls to api.vtex.com and uses Master Data. All outbound requests will fail at runtime with 403 Forbidden errors that are difficult to debug.

每个外部API调用或VTEX资源访问,都必须在
manifest.json
中声明对应的策略。这包括对外部主机的出站HTTP调用、VTEX Admin资源访问,以及对其他应用GraphQL API的调用。
为什么这很重要
VTEX IO平台会对应用进行沙箱隔离以保障安全。没有正确的策略,任何出站HTTP请求都会在基础设施层面被拦截,返回
403 Forbidden
错误。这不是代码问题,而是平台级别的限制。
检测方法
如果你看到代码中通过客户端或HTTP调用某个主机,请立即检查manifest中是否存在针对该主机的
outbound-access
策略。如果代码中使用了
licenseManager.canAccessResource(...)
,请检查是否存在对应的许可证管理器策略。
正确示例
json
{
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "outbound-access",
      "attrs": {
        "host": "portal.vtexcommercestable.com.br",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    },
    {
      "name": "colossus-fire-event"
    },
    {
      "name": "colossus-write-logs"
    }
  ]
}
错误示例
json
{
  "policies": []
}
策略数组为空,但应用需要调用api.vtex.com并使用Master Data。所有出站请求在运行时都会返回403 Forbidden错误,且难以排查原因。

Constraint: Follow App Naming Conventions

约束:遵循应用命名规范

App names MUST be in kebab-case (lowercase letters separated by hyphens). The vendor MUST match the VTEX account name. Version MUST follow Semantic Versioning 2.0.0.
Why this matters
Apps with invalid names cannot be published to the VTEX App Store. Names with special characters or uppercase letters will be rejected by the builder-hub. Vendor mismatch prevents the account from managing the app.
Detection
If you see an app name with uppercase letters, underscores, special characters, or numbers at the beginning, STOP and fix the name.
Correct
json
{
  "name": "order-status-dashboard",
  "vendor": "mycompany",
  "version": "2.1.3"
}
Wrong
json
{
  "name": "Order_Status_Dashboard",
  "vendor": "mycompany",
  "version": "2.1"
}
Uppercase letters and underscores in the name will be rejected. Version "2.1" is not valid semver — must be "2.1.0".
应用名称必须使用kebab-case格式(小写字母,用连字符分隔)。vendor必须与VTEX账户名称一致。版本必须遵循语义化版本2.0.0规范。
为什么这很重要
名称无效的应用无法发布到VTEX应用商店。包含特殊字符或大写字母的名称会被builder-hub拒绝。vendor不匹配会导致账户无法管理该应用。
检测方法
如果你看到应用名称包含大写字母、下划线、特殊字符,或以数字开头,请立即修改名称。
正确示例
json
{
  "name": "order-status-dashboard",
  "vendor": "mycompany",
  "version": "2.1.3"
}
错误示例
json
{
  "name": "Order_Status_Dashboard",
  "vendor": "mycompany",
  "version": "2.1"
}
名称中的大写字母和下划线会被拒绝。版本"2.1"不符合语义化版本规范,必须改为"2.1.0"。

Preferred pattern

推荐实践

Initialize with the VTEX IO CLI:
bash
vtex init
Select the appropriate template:
service-example
,
graphql-example
,
react-app-template
, or
store-theme
.
Recommended manifest configuration:
json
{
  "name": "product-review-service",
  "vendor": "mycompany",
  "version": "0.1.0",
  "title": "Product Review Service",
  "description": "Backend service for managing product reviews with GraphQL API",
  "builders": {
    "node": "7.x",
    "graphql": "1.x",
    "docs": "0.x"
  },
  "dependencies": {
    "vtex.search-graphql": "0.x"
  },
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    },
    {
      "name": "colossus-fire-event"
    },
    {
      "name": "colossus-write-logs"
    }
  ]
}
Recommended
service.json
for backend apps:
json
{
  "memory": 256,
  "timeout": 30,
  "minReplicas": 2,
  "maxReplicas": 10,
  "workers": 4,
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    },
    "review-by-id": {
      "path": "/_v/api/reviews/:id",
      "public": false
    }
  }
}
Recommended directory structure:
text
my-app/
├── manifest.json
├── package.json
├── node/
│   ├── package.json
│   ├── tsconfig.json
│   ├── service.json
│   ├── index.ts          # Service entry point
│   ├── clients/
│   │   └── index.ts      # Client registry
│   ├── middlewares/
│   │   └── validate.ts   # HTTP middleware
│   └── resolvers/
│       └── reviews.ts    # GraphQL resolvers
├── graphql/
│   ├── schema.graphql    # Query/Mutation definitions
│   └── types/
│       └── Review.graphql
├── messages/
│   ├── en.json
│   ├── pt.json
│   └── es.json
└── docs/
    └── README.md
Full
manifest.json
for a comprehensive app using multiple builders:
json
{
  "name": "product-review-suite",
  "vendor": "mycompany",
  "version": "1.0.0",
  "title": "Product Review Suite",
  "description": "Complete product review system with backend, frontend, and admin panel",
  "mustUpdateAt": "2026-01-01",
  "builders": {
    "node": "7.x",
    "react": "3.x",
    "graphql": "1.x",
    "admin": "0.x",
    "messages": "1.x",
    "store": "0.x",
    "docs": "0.x"
  },
  "dependencies": {
    "vtex.styleguide": "9.x",
    "vtex.store-components": "3.x",
    "vtex.css-handles": "0.x"
  },
  "peerDependencies": {
    "vtex.store": "2.x"
  },
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    },
    {
      "name": "colossus-fire-event"
    },
    {
      "name": "colossus-write-logs"
    }
  ],
  "settingsSchema": {
    "title": "Product Review Suite Settings",
    "type": "object",
    "properties": {
      "enableModeration": {
        "title": "Enable review moderation",
        "type": "boolean"
      },
      "reviewsPerPage": {
        "title": "Reviews per page",
        "type": "number"
      }
    }
  }
}
使用VTEX IO CLI初始化应用:
bash
vtex init
选择合适的模板:
service-example
graphql-example
react-app-template
store-theme
推荐的manifest配置:
json
{
  "name": "product-review-service",
  "vendor": "mycompany",
  "version": "0.1.0",
  "title": "Product Review Service",
  "description": "Backend service for managing product reviews with GraphQL API",
  "builders": {
    "node": "7.x",
    "graphql": "1.x",
    "docs": "0.x"
  },
  "dependencies": {
    "vtex.search-graphql": "0.x"
  },
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    },
    {
      "name": "colossus-fire-event"
    },
    {
      "name": "colossus-write-logs"
    }
  ]
}
推荐的后端应用
service.json
配置:
json
{
  "memory": 256,
  "timeout": 30,
  "minReplicas": 2,
  "maxReplicas": 10,
  "workers": 4,
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    },
    "review-by-id": {
      "path": "/_v/api/reviews/:id",
      "public": false
    }
  }
}
推荐的目录结构:
text
my-app/
├── manifest.json
├── package.json
├── node/
│   ├── package.json
│   ├── tsconfig.json
│   ├── service.json
│   ├── index.ts          # 服务入口文件
│   ├── clients/
│   │   └── index.ts      # 客户端注册
│   ├── middlewares/
│   │   └── validate.ts   # HTTP中间件
│   └── resolvers/
│       └── reviews.ts    # GraphQL解析器
├── graphql/
│   ├── schema.graphql    # 查询/变更定义
│   └── types/
│       └── Review.graphql
├── messages/
│   ├── en.json
│   ├── pt.json
│   └── es.json
└── docs/
    └── README.md
使用多构建器的综合应用完整
manifest.json
示例:
json
{
  "name": "product-review-suite",
  "vendor": "mycompany",
  "version": "1.0.0",
  "title": "Product Review Suite",
  "description": "Complete product review system with backend, frontend, and admin panel",
  "mustUpdateAt": "2026-01-01",
  "builders": {
    "node": "7.x",
    "react": "3.x",
    "graphql": "1.x",
    "admin": "0.x",
    "messages": "1.x",
    "store": "0.x",
    "docs": "0.x"
  },
  "dependencies": {
    "vtex.styleguide": "9.x",
    "vtex.store-components": "3.x",
    "vtex.css-handles": "0.x"
  },
  "peerDependencies": {
    "vtex.store": "2.x"
  },
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    },
    {
      "name": "colossus-fire-event"
    },
    {
      "name": "colossus-write-logs"
    }
  ],
  "settingsSchema": {
    "title": "Product Review Suite Settings",
    "type": "object",
    "properties": {
      "enableModeration": {
        "title": "Enable review moderation",
        "type": "boolean"
      },
      "reviewsPerPage": {
        "title": "Reviews per page",
        "type": "number"
      }
    }
  }
}

Common failure modes

常见故障模式

  • Declaring unused builders: Adding builders "just in case" creates overhead during the build process. Unused builder directories can cause build warnings. Only declare builders your app actively uses.
  • Wildcard outbound policies: Using
    "host": "*"
    or
    "path": "/*"
    is a security risk, will be rejected during app review, and makes security audits difficult. Declare specific policies for each external service.
  • Hardcoding version in dependencies: Pinning exact versions like
    "vtex.store-components": "3.165.0"
    prevents receiving bug fixes. Use major version ranges with
    x
    wildcard:
    "vtex.store-components": "3.x"
    .
  • 声明未使用的构建器:“以防万一”添加构建器会增加构建过程的开销。未使用的构建器目录可能会导致构建警告。只声明应用实际使用的构建器。
  • 通配符出站策略:使用
    "host": "*"
    "path": "/*"
    存在安全风险,会在应用审核时被拒绝,且会增加安全审计的难度。应为每个外部服务声明具体的策略。
  • 在依赖项中硬编码版本:固定精确版本如
    "vtex.store-components": "3.165.0"
    会导致无法接收bug修复。使用带x通配符的主版本范围:
    "vtex.store-components": "3.x"

Review checklist

审核检查清单

  • Does every code directory (
    /node
    ,
    /react
    ,
    /graphql
    , etc.) have a matching builder in
    manifest.json
    ?
  • Are all external hosts and VTEX resources declared in
    policies
    ?
  • Is the app name kebab-case, vendor matching account, version valid semver?
  • Does
    service.json
    exist for apps with the
    node
    builder?
  • Are dependencies using major version ranges (
    3.x
    ) instead of exact versions?
  • Are placeholder values (vendor, app name, policies) replaced with real values?
  • 每个代码目录(
    /node
    /react
    /graphql
    等)是否在
    manifest.json
    中有对应的构建器?
  • 所有外部主机和VTEX资源是否都在
    policies
    中声明?
  • 应用名称是否为kebab-case格式,vendor是否与账户一致,版本是否符合语义化规范?
  • 使用
    node
    构建器的应用是否存在
    service.json
  • 依赖项是否使用主版本范围(如
    3.x
    )而非精确版本?
  • 占位符值(vendor、应用名称、策略等)是否已替换为真实值?

Reference

参考资料

  • Manifest — Complete reference for all manifest.json fields and their usage
  • Builders — Full list of available builders with descriptions and usage examples
  • Policies — How to declare outbound-access, License Manager, and role-based policies
  • Dependencies — Managing app dependencies and peer dependencies
  • Accessing External Resources — Policy types and patterns for external API access
  • Creating a New App — Step-by-step guide for app initialization