¿Qué son las aplicaciones?
Las aplicaciones te permiten crear y administrar personalizaciones de Twenty como código. En lugar de configurar todo a través de la interfaz de usuario, defines tu modelo de datos y funciones de lógica en código, lo que hace más rápido crear, mantener y desplegar en múltiples espacios de trabajo. Lo que puedes hacer hoy:- Define objetos y campos personalizados como código (modelo de datos gestionado)
- Crea funciones de lógica con desencadenadores personalizados
- Despliega la misma aplicación en múltiples espacios de trabajo
- Diseños y componentes de la interfaz de usuario personalizados
Prerrequisitos
- Node.js 24+ y Yarn 4
- Un espacio de trabajo de Twenty y una clave de API (créala en https://app.twenty.com/settings/api-webhooks)
Primeros pasos
Crea una aplicación nueva usando el generador oficial, luego autentícate y comienza a desarrollar:Estructura del proyecto (generada)
Cuando ejecutasnpx create-twenty-app@latest my-twenty-app, el generador:
- Copia una aplicación base mínima en
my-twenty-app/ - Añade una dependencia local de
twenty-sdky la configuración de Yarn 4 - Crea archivos de configuración y scripts vinculados a la CLI
twenty - Genera una configuración de aplicación predeterminada y un rol de función predeterminado
Convención sobre configuración
Las aplicaciones usan un enfoque de convención sobre configuración en el que las entidades se detectan por su sufijo de archivo. Esto permite una organización flexible dentro de la carpetasrc/app/:
| Sufijo de archivo | Tipo de entidad |
|---|---|
*.object.ts | Definiciones de objetos personalizados |
*.function.ts | Definiciones de funciones sin servidor |
*.front-component.tsx | Definiciones de componentes de interfaz |
*.role.ts | Definiciones de roles |
Organizaciones de carpetas compatibles
Puedes organizar tus entidades con cualquiera de estos patrones: Tradicional (por tipo):- package.json: Declara el nombre de la aplicación, la versión, los entornos (Node 24+, Yarn 4) y agrega
twenty-sdkademás de scripts comoapp:dev,app:generate,entity:add,function:logs,function:execute,app:uninstallyauth:loginque delegan en la CLI localtwenty. - .gitignore: Ignora artefactos comunes como
node_modules,.yarn,generated/(cliente tipado),dist/,build/, carpetas de cobertura, archivos de registro y archivos.env*. - yarn.lock, .yarnrc.yml, .yarn/: Bloquean y configuran la cadena de herramientas Yarn 4 utilizada por el proyecto.
- .nvmrc: Fija la versión de Node.js esperada por el proyecto.
- eslint.config.mjs y tsconfig.json: Proporcionan linting y configuración de TypeScript para las fuentes de TypeScript de tu aplicación.
- README.md: Un README breve en la raíz de la aplicación con instrucciones básicas.
- public/: Una carpeta para almacenar recursos públicos (imágenes, fuentes, archivos estáticos) que se servirán con tu aplicación. Los archivos colocados aquí se cargan durante la sincronización y son accesibles en tiempo de ejecución.
- src/: El lugar principal donde defines tu aplicación como código:
application.config.ts: Configuración global de tu aplicación (metadatos y vinculación en tiempo de ejecución). Consulta “Configuración de la aplicación” más abajo.*.role.ts: Definiciones de roles usadas por tus funciones de lógica. Consulta “Rol de función predeterminado” más abajo.*.object.ts: Definiciones de objetos personalizados.*.function.ts: Definiciones de funciones de lógica.*.front-component.tsx: Definiciones de componentes de interfaz.
yarn app:generatecreará una carpetagenerated/(cliente tipado de Twenty + tipos del espacio de trabajo).yarn entity:addañadirá archivos de definición de entidades ensrc/para tus objetos, funciones, componentes de interfaz o roles personalizados.
Autenticación
La primera vez que ejecutesyarn auth:login, se te solicitará:
- URL de la API (por defecto http://localhost:3000 o el perfil de tu espacio de trabajo actual)
- Clave de API
~/.twenty/config.json. Puedes mantener varios perfiles y cambiar entre ellos.
Gestión de espacios de trabajo
auth:switch, todos los comandos posteriores usarán ese espacio de trabajo de forma predeterminada. Aún puedes anularlo temporalmente con --workspace <name>.
Usa los recursos del SDK (tipos y configuración)
El twenty-sdk proporciona bloques de construcción tipados y funciones auxiliares que utilizas dentro de tu aplicación. A continuación, las partes clave que usarás con más frecuencia.Funciones auxiliares
El SDK proporciona cuatro funciones auxiliares con validación incorporada para definir las entidades de tu aplicación:| Función | Propósito |
|---|---|
defineApplication() | Configura los metadatos de la aplicación |
defineObject() | Define objetos personalizados con campos |
defineFunction() | Define funciones de lógica con controladores |
defineRole() | Configura permisos de roles y acceso a objetos |
Definir objetos
Los objetos personalizados describen tanto el esquema como el comportamiento de los registros en tu espacio de trabajo. UsadefineObject() para definir objetos con validación incorporada:
- Usa
defineObject()para validación incorporada y mejor soporte del IDE. - El
universalIdentifierdebe ser único y estable entre implementaciones. - Cada campo requiere
name,type,labely su propiouniversalIdentifierestable. - La matriz
fieldses opcional: puedes definir objetos sin campos personalizados. - Puedes generar nuevos objetos usando
yarn entity:add, que te guía por el nombrado, los campos y las relaciones.
Los campos base se crean automáticamente. Cuando defines un objeto personalizado, Twenty añade automáticamente campos estándar como
name, createdAt, updatedAt, createdBy, position y deletedAt. No necesitas definir estos en tu matriz fields — solo agrega tus campos personalizados.Configuración de la aplicación (application.config.ts)
Cada aplicación tiene un único archivoapplication.config.ts que describe:
- Qué es la aplicación: identificadores, nombre para mostrar y descripción.
- Cómo se ejecutan sus funciones: qué rol usan para permisos.
- Variables (opcionales): pares clave–valor expuestos a tus funciones como variables de entorno.
defineApplication() to define your application configuration:
- Los campos
universalIdentifierson ID deterministas bajo tu control; genéralos una vez y mantenlos estables entre sincronizaciones. - Las
applicationVariablesse convierten en variables de entorno para tus funciones (por ejemplo,DEFAULT_RECIPIENT_NAMEestá disponible comoprocess.env.DEFAULT_RECIPIENT_NAME). roleUniversalIdentifiermust match the role you define in your*.role.tsfile (see below).
Roles y permisos
Las aplicaciones pueden definir roles que encapsulan permisos sobre los objetos y acciones de tu espacio de trabajo. The fieldroleUniversalIdentifier in application.config.ts designates the default role used by your app’s logic functions.
- La clave de API en tiempo de ejecución inyectada como
TWENTY_API_KEYse deriva de este rol de función predeterminado. - El cliente tipado estará restringido a los permisos otorgados a ese rol.
- Sigue el principio de mínimo privilegio: crea un rol dedicado con solo los permisos que necesitan tus funciones y luego referencia su identificador universal.
Rol de función predeterminado (*.role.ts)
Cuando generas una nueva aplicación, la CLI también crea un archivo de rol predeterminado. UsadefineRole() para definir roles con validación incorporada:
universalIdentifier of this role is then referenced in application.config.ts as roleUniversalIdentifier. En otras palabras:
- *.role.ts define lo que puede hacer el rol de función predeterminado.
- application.config.ts apunta a ese rol para que tus funciones hereden sus permisos.
- Parte del rol generado y luego restríngele progresivamente siguiendo el principio de mínimo privilegio.
- Reemplaza
objectPermissionsyfieldPermissionscon los objetos/campos que necesitan tus funciones. permissionFlagscontrola el acceso a capacidades a nivel de plataforma. Mantenlos al mínimo; agrega solo lo que necesites.- Consulta un ejemplo funcional en la aplicación Hello World:
packages/twenty-apps/hello-world/src/roles/function-role.ts.
Configuración y punto de entrada de funciones de lógica
Cada archivo de función usadefineFunction() para exportar una configuración con un controlador y desencadenadores opcionales. Usa el sufijo de archivo *.function.ts para la detección automática.
- route: Expone tu función en una ruta y método HTTP bajo el endpoint
/s/:
p. ej.path: '/post-card/create',-> llamar en<APP_URL>/s/post-card/create
- cron: Ejecuta tu función en un horario usando una expresión CRON.
- databaseEvent: Se ejecuta en eventos del ciclo de vida de objetos del espacio de trabajo. Cuando la operación del evento es
updated, se pueden especificar campos específicos que se deben escuchar en el arregloupdatedFields. Si se deja sin definir o vacío, cualquier actualización activará la función.
p. ej., person.updated
Notas:
- La matriz
triggerses opcional. Las funciones sin desencadenadores pueden usarse como funciones utilitarias llamadas por otras funciones. - Puedes combinar múltiples tipos de desencadenadores en una sola función.
Carga útil del disparador de ruta
Cuando un disparador de ruta invoca tu función de lógica, esta recibe un objetoRoutePayload que sigue el formato de AWS HTTP API v2. Importa el tipo desde twenty-sdk:
RoutePayload tiene la siguiente estructura:
| Propiedad | Tipo | Descripción |
|---|---|---|
headers | Record<string, string | undefined> | Encabezados HTTP (solo aquellos listados en forwardedRequestHeaders) |
queryStringParameters | Record<string, string | undefined> | Parámetros de consulta (valores múltiples unidos con comas) |
pathParameters | Record<string, string | undefined> | Parámetros de ruta extraídos del patrón de ruta (p. ej., /users/:id → { id: '123' }) |
cuerpo | object | null | Cuerpo de la solicitud analizado (JSON) |
isBase64Encoded | booleano | Indica si el cuerpo está codificado en base64 |
requestContext.http.method | string | Método HTTP (GET, POST, PUT, PATCH, DELETE) |
requestContext.http.path | string | Ruta de la solicitud sin procesar |
Reenvío de encabezados HTTP
De forma predeterminada, los encabezados HTTP de las solicitudes entrantes no se pasan a tu función de lógica por razones de seguridad. Para acceder a encabezados específicos, enuméralos explícitamente en el arregloforwardedRequestHeaders:
Los nombres de los encabezados se normalizan a minúsculas. Accede a ellos usando claves en minúsculas (por ejemplo,
event.headers['content-type']).- Generado: Ejecuta
yarn entity:addy elige la opción para añadir una nueva función. Esto genera un archivo inicial con un controlador y configuración. - Manual: Crea un nuevo archivo
*.function.tsy usadefineFunction(), siguiendo el mismo patrón.
Cliente tipado generado
Ejecuta yarn app:generate para crear un cliente tipado local en generated/ basado en el esquema de tu espacio de trabajo. Úsalo en tus funciones:yarn app:generate. Vuelve a ejecutarlo después de cambiar tus objetos o al incorporarte a un nuevo espacio de trabajo.
Credenciales en tiempo de ejecución en funciones de lógica
Cuando tu función se ejecuta en Twenty, la plataforma inyecta credenciales como variables de entorno antes de que tu código se ejecute:TWENTY_API_URL: URL base de la API de Twenty a la que apunta tu aplicación.TWENTY_API_KEY: Clave de corta duración con alcance al rol de función predeterminado de tu aplicación.
- No necesitas pasar la URL ni la clave de API al cliente generado. Lee
TWENTY_API_URLyTWENTY_API_KEYde process.env en tiempo de ejecución. - The API key’s permissions are determined by the role referenced in your
application.config.tsviaroleUniversalIdentifier. Este es el rol predeterminado que usan las funciones de lógica de tu aplicación. - Las aplicaciones pueden definir roles para seguir el principio de mínimo privilegio. Grant only the permissions your functions need, then point
roleUniversalIdentifierto that role’s universal identifier.
Ejemplo Hello World
Explora un ejemplo mínimo de extremo a extremo que demuestra objetos, funciones y múltiples desencadenadores aquí:Configuración manual (sin el generador)
Aunque recomendamos usarcreate-twenty-app para la mejor experiencia de inicio, también puedes configurar un proyecto manualmente. No instales la CLI globalmente. En su lugar, agrega twenty-sdk como dependencia local y conecta scripts en tu package.json:
yarn app:dev, yarn app:generate, etc.
Solución de problemas
- Errores de autenticación: ejecuta
yarn auth:loginy asegúrate de que tu clave de API tenga los permisos necesarios. - No se puede conectar al servidor: verifica la URL de la API y que el servidor de Twenty sea accesible.
- Tipos o cliente faltantes/obsoletos: ejecuta
yarn app:generate. - El modo de desarrollo no sincroniza: asegúrate de que
yarn app:devesté ejecutándose y de que los cambios no sean ignorados por tu entorno.