Que sont les applications ?
Les applications vous permettent de créer et de gérer des personnalisations Twenty sous forme de code. Au lieu de tout configurer via l’interface utilisateur, vous définissez votre modèle de données et vos fonctions logiques dans le code — ce qui accélère la création, la maintenance et le déploiement sur plusieurs espaces de travail. Ce que vous pouvez faire aujourd’hui:- Définir des objets et des champs personnalisés sous forme de code (modèle de données géré)
- Créer des fonctions logiques avec des déclencheurs personnalisés
- Déployer la même application sur plusieurs espaces de travail
- Mises en page et composants d’interface utilisateur personnalisés
Prérequis
- Node.js 24+ et Yarn 4
- Un espace de travail Twenty et une clé API (créez-en une sur https://app.twenty.com/settings/api-webhooks)
Prise en main
Créez une nouvelle application avec l’outil d’amorçage officiel, puis authentifiez-vous et commencez à développer :Structure du projet (générée)
Lorsque vous exécuteznpx create-twenty-app@latest my-twenty-app, l’outil de scaffolding :
- Copie une application de base minimale dans
my-twenty-app/ - Ajoute une dépendance locale à
twenty-sdket la configuration Yarn 4 - Crée des fichiers de configuration et des scripts reliés à la CLI
twenty - Génère une configuration d’application par défaut et un rôle de fonction par défaut
Convention plutôt que configuration
Les applications adoptent une approche convention plutôt que configuration où les entités sont détectées par leur suffixe de fichier. Cela permet une organisation flexible dans le dossiersrc/app/ :
| Suffixe de fichier | Type d’entité |
|---|---|
*.object.ts | Définitions d’objets personnalisés |
*.function.ts | Définitions de fonctions sans serveur |
*.front-component.tsx | Définitions des composants frontaux |
*.role.ts | Définitions de rôles |
Structures de dossiers prises en charge
Vous pouvez organiser vos entités selon l’un des schémas suivants : Traditionnelle (par type) :- package.json : Déclare le nom de l’application, la version, les moteurs (Node 24+, Yarn 4), et ajoute
twenty-sdkainsi que des scripts commeapp:dev,app:generate,entity:add,function:logs,function:execute,app:uninstalletauth:loginqui délèguent à la CLI localetwenty. - .gitignore : Ignore les artefacts courants tels que
node_modules,.yarn,generated/(client typé),dist/,build/, les dossiers de couverture, les fichiers journaux et les fichiers.env*. - yarn.lock, .yarnrc.yml, .yarn/ : Verrouillent et configurent la chaîne d’outils Yarn 4 utilisée par le projet.
- .nvmrc : Fige la version de Node.js attendue par le projet.
- eslint.config.mjs et tsconfig.json : Fournissent la configuration de linting et TypeScript pour les sources TypeScript de votre application.
- README.md : Un bref README à la racine de l’application avec des instructions de base.
- public/: Un dossier pour stocker des ressources publiques (images, polices, fichiers statiques) qui seront servies avec votre application. Les fichiers placés ici sont téléversés lors de la synchronisation et accessibles à l’exécution.
- src/ : L’endroit principal où vous définissez votre application sous forme de code :
application.config.ts: Configuration globale de votre application (métadonnées et liaisons d’exécution). Voir « Configuration de l’application » ci-dessous.*.role.ts: Définitions de rôles utilisées par vos fonctions logiques. Voir « Rôle de fonction par défaut » ci-dessous.*.object.ts: Définitions d’objets personnalisés.*.function.ts: Définitions de fonctions logiques.*.front-component.tsx: Définitions des composants front-end.
yarn app:generatecréera un dossiergenerated/(client Twenty typé + types de l’espace de travail).yarn entity:addajoutera des fichiers de définition d’entité soussrc/pour vos objets, fonctions, composants front-end ou rôles personnalisés.
Authentification
La première fois que vous exécutezyarn auth:login, il vous sera demandé :
- URL de l’API (par défaut http://localhost:3000 ou votre profil d’espace de travail actuel)
- Clé API
~/.twenty/config.json. Vous pouvez gérer plusieurs profils et basculer entre eux.
Gestion des espaces de travail
auth:switch, toutes les commandes suivantes utiliseront cet espace de travail par défaut. Vous pouvez toujours le surcharger temporairement avec --workspace <name>.
Utiliser les ressources du SDK (types et configuration)
Le paquet twenty-sdk fournit des blocs de construction typés et des fonctions utilitaires que vous utilisez dans votre application. Voici les éléments clés que vous manipulerez le plus souvent.Fonctions utilitaires
Le SDK fournit quatre fonctions utilitaires avec validation intégrée pour définir les entités de votre application :| Fonction | Objectif |
|---|---|
defineApplication() | Configurer les métadonnées de l’application |
defineObject() | Définir des objets personnalisés avec des champs |
defineFunction() | Définir des fonctions logiques avec des gestionnaires |
defineRole() | Configurer les autorisations de rôle et l’accès aux objets |
Définir des objets
Les objets personnalisés décrivent à la fois le schéma et le comportement des enregistrements dans votre espace de travail. UtilisezdefineObject() pour définir des objets avec validation intégrée :
- Utilisez
defineObject()pour une validation intégrée et une meilleure prise en charge par l’IDE. - Le
universalIdentifierdoit être unique et stable entre les déploiements. - Chaque champ nécessite un
name, untype, unlabelet son propreuniversalIdentifierstable. - Le tableau
fieldsest facultatif — vous pouvez définir des objets sans champs personnalisés. - Vous pouvez générer de nouveaux objets avec
yarn entity:add, qui vous guide à travers le nommage, les champs et les relations.
Les champs de base sont créés automatiquement. Lorsque vous définissez un objet personnalisé, Twenty ajoute automatiquement des champs standard tels que
name, createdAt, updatedAt, createdBy, position et deletedAt. Vous n’avez pas besoin de les définir dans votre tableau fields — ajoutez uniquement vos champs personnalisés.Configuration de l’application (application.config.ts)
Chaque application dispose d’un seul fichierapplication.config.ts qui décrit :
- Identité de l’application : identifiants, nom d’affichage et description.
- Exécution des fonctions : le rôle utilisé pour les autorisations.
- Variables (facultatif) : paires clé–valeur exposées à vos fonctions en tant que variables d’environnement.
defineApplication() pour définir la configuration de votre application :
- Les champs
universalIdentifiersont des identifiants déterministes que vous possédez ; générez-les une fois et conservez-les stables entre les synchronisations. applicationVariablesdeviennent des variables d’environnement pour vos fonctions (par exemple,DEFAULT_RECIPIENT_NAMEest disponible sousprocess.env.DEFAULT_RECIPIENT_NAME).defaultRoleUniversalIdentifierdoit correspondre au rôle que vous définissez dans votre fichier*.role.ts(voir ci-dessous).
Rôles et autorisations
Les applications peuvent définir des rôles qui encapsulent des autorisations sur les objets et actions de votre espace de travail. Le champdefaultRoleUniversalIdentifier dans application.config.ts désigne le rôle par défaut utilisé par les fonctions logiques de votre application.
- La clé API d’exécution injectée sous
TWENTY_API_KEYest dérivée de ce rôle de fonction par défaut. - Le client typé sera limité aux autorisations accordées à ce rôle.
- Appliquez le principe du moindre privilège : créez un rôle dédié avec uniquement les autorisations nécessaires à vos fonctions, puis référencez son identifiant universel.
Rôle de fonction par défaut (*.role.ts)
Lorsque vous générez une nouvelle application, la CLI crée également un fichier de rôle par défaut. UtilisezdefineRole() pour définir des rôles avec validation intégrée :
universalIdentifier de ce rôle est ensuite référencé dans application.config.ts en tant que defaultRoleUniversalIdentifier. En d’autres termes :
- *.role.ts définit ce que le rôle de fonction par défaut peut faire.
- application.config.ts pointe vers ce rôle afin que vos fonctions héritent de ses autorisations.
- Partez du rôle généré, puis restreignez-le progressivement en suivant le principe du moindre privilège.
- Remplacez
objectPermissionsetfieldPermissionspar les objets/champs dont vos fonctions ont besoin. permissionFlagscontrôlent l’accès aux capacités au niveau de la plateforme. Gardez-les au minimum ; n’ajoutez que ce dont vous avez besoin.- Voir un exemple fonctionnel dans l’application Hello World :
packages/twenty-apps/hello-world/src/roles/function-role.ts.
Configuration et point d’entrée des fonctions logiques
Chaque fichier de fonction utilisedefineFunction() pour exporter une configuration avec un gestionnaire et des déclencheurs facultatifs. Utilisez le suffixe de fichier *.function.ts pour la détection automatique.
- route : Expose votre fonction sur un chemin et une méthode HTTP sous l’endpoint
/s/:
p. ex.path: '/post-card/create',-> appel sur<APP_URL>/s/post-card/create
- cron : Exécute votre fonction selon une planification à l’aide d’une expression CRON.
- databaseEvent: S’exécute lors des événements du cycle de vie des objets de l’espace de travail. Lorsque l’opération de l’événement est
updated, des champs spécifiques à surveiller peuvent être spécifiés dans le tableauupdatedFields. S’il est laissé indéfini ou vide, toute mise à jour déclenchera la fonction.
p. ex. person.updated
Notes :
- Le tableau
triggersest facultatif. Les fonctions sans déclencheurs peuvent servir de fonctions utilitaires appelées par d’autres fonctions. - Vous pouvez combiner plusieurs types de déclencheurs dans une seule fonction.
Charge utile du déclencheur de route
Lorsqu’un déclencheur de route appelle votre fonction logique, elle reçoit un objetRoutePayload qui suit le format AWS HTTP API v2. Importez le type depuis twenty-sdk :
RoutePayload a la structure suivante :
| Nom de la propriété | Type | Description |
|---|---|---|
headers | Record<string, string | undefined> | En-têtes HTTP (uniquement ceux répertoriés dans forwardedRequestHeaders) |
queryStringParameters | Record<string, string | undefined> | Paramètres de la chaîne de requête (plusieurs valeurs séparées par des virgules) |
pathParameters | Record<string, string | undefined> | Paramètres de chemin extraits du modèle de route (p. ex., /users/:id → { id: '123' }) |
corps du message | object | null | Corps de la requête analysé (JSON) |
isBase64Encoded | booléen | Indique si le corps est encodé en base64 |
requestContext.http.method | string | Méthode HTTP (GET, POST, PUT, PATCH, DELETE) |
requestContext.http.path | string | Chemin de la requête brut |
Transfert des en-têtes HTTP
Par défaut, les en-têtes HTTP des requêtes entrantes ne sont pas transmis à votre fonction logique pour des raisons de sécurité. Pour accéder à des en-têtes spécifiques, listez-les explicitement dans le tableauforwardedRequestHeaders :
Les noms d’en-têtes sont normalisés en minuscules. Accédez-y en utilisant des clés en minuscules (par exemple,
event.headers['content-type']).- Générée : Exécutez
yarn entity:addet choisissez l’option pour ajouter une nouvelle fonction. Cela génère un fichier de démarrage avec un gestionnaire et une configuration. - Manuelle : Créez un nouveau fichier
*.function.tset utilisezdefineFunction(), en suivant le même modèle.
Client typé généré
Exécutez yarn app:generate pour créer un client typé local dans generated/ basé sur le schéma de votre espace de travail. Utilisez-le dans vos fonctions :yarn app:generate. Relancez après avoir modifié vos objets ou lors de l’intégration à un nouvel espace de travail.
Identifiants d’exécution dans les fonctions logiques
Lorsque votre fonction s’exécute sur Twenty, la plateforme injecte des identifiants sous forme de variables d’environnement avant l’exécution de votre code :TWENTY_API_URL: URL de base de l’API Twenty ciblée par votre application.TWENTY_API_KEY: Clé de courte durée limitée au rôle de fonction par défaut de votre application.
- Vous n’avez pas besoin de passer l’URL ou la clé API au client généré. Il lit
TWENTY_API_URLetTWENTY_API_KEYdepuis process.env à l’exécution. - Les autorisations de la clé API sont déterminées par le rôle référencé dans votre
application.config.tsviadefaultRoleUniversalIdentifier. Il s’agit du rôle par défaut utilisé par les fonctions logiques de votre application. - Les applications peuvent définir des rôles pour appliquer le principe du moindre privilège. N’accordez que les autorisations dont vos fonctions ont besoin, puis faites pointer
defaultRoleUniversalIdentifiervers l’identifiant universel de ce rôle.
Exemple Hello World
Découvrez un exemple minimal de bout en bout qui démontre des objets, des fonctions et plusieurs déclencheurs ici :Configuration manuelle (sans l’outil de scaffolding)
Même si nous recommandons d’utilisercreate-twenty-app pour une expérience de démarrage optimale, vous pouvez également configurer un projet manuellement. N’installez pas la CLI globalement. Ajoutez plutôt twenty-sdk comme dépendance locale et reliez des scripts dans votre package.json :
yarn app:dev, yarn app:generate, etc.
Résolution des problèmes
- Erreurs d’authentification : exécutez
yarn auth:loginet assurez-vous que votre clé API dispose des autorisations requises. - Impossible de se connecter au serveur : vérifiez l’URL de l’API et que le serveur Twenty est accessible.
- Types ou client manquants/obsolètes : exécutez
yarn app:generate. - Le mode dev ne se synchronise pas : assurez-vous que
yarn app:devest en cours d’exécution et que les modifications ne sont pas ignorées par votre environnement.