什么是应用?
应用使你能够以代码的形式构建和管理 Twenty 自定义项。 无需通过 UI 配置所有内容,你可以在代码中定义数据模型和逻辑函数——从而更快地构建、维护,并推广到多个工作空间。 你现在可以做什么:- 以代码定义自定义对象和字段(受管理的数据模型)
- 构建带有自定义触发器的逻辑函数
- 将同一个应用部署到多个工作空间
先决条件
- Node.js 24+ 和 Yarn 4
- 一个 Twenty 工作空间和一个 API 密钥(在 https://app.twenty.com/settings/api-webhooks 创建)
开始使用
使用官方脚手架创建一个新应用,然后进行身份验证并开始开发:项目结构(脚手架生成)
当你运行npx create-twenty-app@latest my-twenty-app 时,脚手架将:
- 将一个最小的基础应用复制到
my-twenty-app/中 - 添加本地
twenty-sdk依赖和 Yarn 4 配置 - 创建与
twentyCLI 关联的配置文件和脚本 - 生成默认的应用配置和默认的函数角色
- package.json: Declares the app name, version, engines (Node 24+, Yarn 4), and adds
twenty-sdkplus atwentyscript that delegates to the localtwentyCLI. Runyarn twenty helpto list all available commands. - .gitignore:忽略常见产物,如
node_modules、.yarn、generated/(类型化客户端)、dist/、build/、覆盖率文件夹、日志文件以及.env*文件。 - yarn.lock、.yarnrc.yml、.yarn/:锁定并配置项目使用的 Yarn 4 工具链。
- .nvmrc:固定项目期望的 Node.js 版本。
- eslint.config.mjs 和 tsconfig.json:为应用的 TypeScript 源码提供 Lint 与 TypeScript 配置。
- README.md:应用根目录中的简短 README,包含基本说明。
- public/: 一个用于存储公共资源(图像、字体、静态文件)的文件夹,这些资源将随你的应用程序一起提供。 放置在此处的文件会在同步期间上传,并可在运行时访问。
- src/:你以代码形式定义应用的主要位置
实体检测
该 SDK 通过在你的 TypeScript 文件中解析export default define<Entity>({...}) 调用来检测实体。 每种实体类型都有一个从 twenty-sdk 导出的对应辅助函数:
| 辅助函数 | 实体类型 |
|---|---|
defineObject() | 自定义对象定义 |
defineLogicFunction() | 逻辑函数定义 |
defineFrontComponent() | 前端组件定义 |
defineRole() | 角色定义 |
defineField() | 现有对象的字段扩展 |
文件命名是灵活的。 实体检测基于 AST — SDK 会扫描你的源文件以查找
export default define<Entity>({...}) 模式。 你可以按照自己的喜好组织文件和文件夹。 按实体类型分组(例如 logic-functions/、roles/)只是代码组织的一种约定,并非必需。yarn twenty app:generatewill create agenerated/folder (typed Twenty client + workspace types).yarn twenty entity:addwill add entity definition files undersrc/for your custom objects, functions, front components, or roles.
身份验证
The first time you runyarn twenty auth:login, you’ll be prompted for:
- API URL(默认为 http://localhost:3000 或你当前的工作空间配置)
- API 密钥
~/.twenty/config.json 中。 你可以维护多个配置文件并在它们之间切换。
管理工作空间
yarn twenty auth:switch, all subsequent commands will use that workspace by default. 你仍可通过 --workspace <name> 临时覆盖。
使用 SDK 资源(类型与配置)
twenty-sdk 提供你在应用中使用的类型化构件和辅助函数。 以下是你最常接触的关键部分。辅助函数
该 SDK 提供辅助函数用于定义你的应用实体。 如 实体检测 中所述,你必须使用export default define<Entity>({...}) 才能让你的实体被检测到:
| 函数 | 目的 |
|---|---|
defineApplication() | 配置应用元数据(必需,每个应用一个) |
defineObject() | 定义带字段的自定义对象 |
defineLogicFunction() | 定义带处理程序的逻辑函数 |
defineFrontComponent() | 为自定义 UI 定义前端组件 |
defineRole() | 配置角色权限和对象访问 |
defineField() | 为现有对象扩展额外字段 |
定义对象
自定义对象同时描述工作空间中记录的架构与行为。 使用defineObject() 以内置校验定义对象:
- 使用
defineObject()以获得内置校验和更好的 IDE 支持。 universalIdentifier必须在各次部署间保持唯一且稳定。- 每个字段都需要
name、type、label以及其自身稳定的universalIdentifier。 fields数组是可选的——你可以定义没有自定义字段的对象。- You can scaffold new objects using
yarn twenty entity:add, which guides you through naming, fields, and relationships.
基础字段会自动创建。 当你定义自定义对象时,Twenty 会自动添加
name、createdAt、updatedAt、createdBy、position、deletedAt 等标准字段。 你无需在 fields 数组中定义这些字段——只需添加你的自定义字段。应用配置(application-config.ts)
每个应用都有一个application-config.ts 文件,用于描述:
- 应用的身份:标识符、显示名称和描述。
- 函数如何运行:它们用于权限的角色。
- (可选)变量:以环境变量形式提供给函数的键值对。
defineApplication() 定义你的应用配置:
universalIdentifier字段是你拥有的确定性 ID;生成一次并在多次同步中保持稳定。applicationVariables会变成函数可用的环境变量(例如,DEFAULT_RECIPIENT_NAME可作为process.env.DEFAULT_RECIPIENT_NAME使用)。defaultRoleUniversalIdentifier必须与角色文件一致(见下文)。
角色和权限
应用可以定义角色,以封装对工作空间对象与操作的权限。application-config.ts 中的 defaultRoleUniversalIdentifier 字段指定你的应用逻辑函数所使用的默认角色。
- 作为
TWENTY_API_KEY注入的运行时 API 密钥源自该默认函数角色。 - 类型化客户端将受限于该角色授予的权限。
- 遵循最小权限原则:仅授予函数所需权限来创建一个专用角色,然后引用其通用标识符。
默认函数角色(*.role.ts)
当你脚手架生成新应用时,CLI 也会创建一个默认角色文件。 使用defineRole() 定义带内置校验的角色:
universalIdentifier 会在 application-config.ts 中被引用为 defaultRoleUniversalIdentifier。 换句话说:
- *.role.ts 定义默认函数角色可以执行的操作。
- application-config.ts 指向该角色,使你的函数继承其权限。
- 从脚手架生成的角色开始,然后按照最小权限原则逐步收紧权限。
- 将
objectPermissions和fieldPermissions替换为你的函数所需的对象/字段。 permissionFlags控制对平台级能力的访问。 尽量保持最小化;仅添加所需项。- 在 Hello World 应用中查看可运行示例:
packages/twenty-apps/hello-world/src/roles/function-role.ts。
逻辑函数的配置与入口点
每个函数文件都使用defineLogicFunction() 导出包含处理程序和可选触发器的配置。
- route:在**
/s/端点**下通过 HTTP 路径与方法公开你的函数:
例如path: '/post-card/create',-> 调用<APP_URL>/s/post-card/create
- cron:使用 CRON 表达式按计划运行你的函数。
- databaseEvent:在工作空间对象生命周期事件上运行。 当事件操作为
updated时,可以在updatedFields数组中指定要监听的特定字段。 如果未定义或为空,任何更新都会触发该函数。
例如 person.updated
备注:
triggers数组是可选的。 没有触发器的函数可作为实用函数,被其他函数调用。- 你可以在单个函数中混用多种触发器类型。
路由触发器负载
当路由触发器调用你的逻辑函数时,它会接收一个遵循 AWS HTTP API v2 格式的RoutePayload 对象。 从 twenty-sdk 导入该类型:
RoutePayload 类型具有以下结构:
| 属性 | 类型 | 描述 |
|---|---|---|
headers | Record<string, string | undefined> | HTTP 请求头(仅限 forwardedRequestHeaders 中列出的那些) |
queryStringParameters | Record<string, string | undefined> | 查询字符串参数(多个值以逗号连接) |
pathParameters | Record<string, string | undefined> | 从路由模式中提取的路径参数(例如,/users/:id → { id: '123' }) |
请求体 | object | null | 已解析的请求体(JSON) |
isBase64Encoded | 布尔值 | 请求体是否为 base64 编码 |
requestContext.http.method | string | HTTP 方法(GET、POST、PUT、PATCH、DELETE) |
requestContext.http.path | string | 原始请求路径 |
转发 HTTP 请求头
出于安全原因,默认不会将传入请求的 HTTP 请求头传递给你的逻辑函数。 如需访问特定请求头,请在forwardedRequestHeaders 数组中显式列出:
请求头名称会被规范化为小写。 请使用小写键访问它们(例如,
event.headers['content-type'])。- Scaffolded: Run
yarn twenty entity:addand choose the option to add a new logic function. 这将生成一个包含处理程序和配置的入门文件。 - 手动:创建一个新的
*.logic-function.ts文件,并使用defineLogicFunction(),遵循相同的模式。
前端组件
前端组件使你可以构建在 Twenty 的 UI 中渲染的自定义 React 组件。 使用defineFrontComponent() 以内置校验定义组件:
- 前端组件是在 Twenty 中的隔离上下文中渲染的 React 组件。
- 使用
*.front-component.tsx文件后缀以便自动检测。 component字段引用你的 React 组件。- Components are built and synced automatically during
yarn twenty app:dev.
- Scaffolded: Run
yarn twenty entity:addand choose the option to add a new front component. - 手动:创建一个新的
*.front-component.tsx文件,并使用defineFrontComponent()。
生成的类型化客户端
Runyarn twenty app:generate to create a local typed client in generated/ based on your workspace schema. 在你的函数中使用它:
yarn twenty app:generate. 在更改对象之后或接入新工作空间时,请重新运行。
逻辑函数中的运行时凭据
当你的函数在 Twenty 上运行时,平台会在代码执行前将凭据作为环境变量注入:TWENTY_API_URL:你的应用所针对的 Twenty API 的基础 URL。TWENTY_API_KEY:作用域限定于你的应用默认函数角色的短期密钥。
- 你无需向生成的客户端传递 URL 或 API 密钥。 它会在运行时从 process.env 读取
TWENTY_API_URL和TWENTY_API_KEY。 - API 密钥的权限由
application-config.ts中通过defaultRoleUniversalIdentifier引用的角色决定。 这是你的应用逻辑函数使用的默认角色。 - 应用可以定义角色以遵循最小权限原则。 仅授予函数所需的权限,然后将
defaultRoleUniversalIdentifier指向该角色的通用标识符。
Hello World 示例
在此处查看一个最小的端到端示例,展示对象、逻辑函数、前端组件和多种触发器:手动设置(不使用脚手架)
虽然我们建议使用create-twenty-app 以获得最佳的上手体验,但你也可以手动设置项目。 不要全局安装 CLI。 Instead, add twenty-sdk as a local dependency and wire a single script in your package.json:
twenty script:
yarn twenty <command>, e.g. yarn twenty app:dev, yarn twenty app:generate, yarn twenty help, etc.
故障排除
- Authentication errors: run
yarn twenty auth:loginand ensure your API key has the required permissions. - 无法连接到服务器:请验证 API URL,并确保 Twenty 服务器可达。
- Types or client missing/outdated: run
yarn twenty app:generate. - Dev mode not syncing: ensure
yarn twenty app:devis running and that changes are not ignored by your environment.