Cosa sono le app?
Le app ti consentono di creare e gestire le personalizzazioni di Twenty come codice. Invece di configurare tutto tramite l’interfaccia utente, definisci in codice il modello dati e le funzioni logiche — rendendo più veloce creare, mantenere e distribuire su più spazi di lavoro. Cosa puoi fare oggi:- Definisci oggetti e campi personalizzati come codice (modello dati gestito)
- Crea funzioni logiche con trigger personalizzati
- Distribuisci la stessa app su più spazi di lavoro
Prerequisiti
- Node.js 24+ e Yarn 4
- Uno spazio di lavoro Twenty e una chiave API (creane una su https://app.twenty.com/settings/api-webhooks)
Per iniziare
Crea una nuova app utilizzando lo scaffolder ufficiale, quindi autenticati e inizia a sviluppare:Struttura del progetto (generata dallo scaffolder)
Quando eseguinpx create-twenty-app@latest my-twenty-app, lo scaffolder:
- Copia un’applicazione base minimale in
my-twenty-app/ - Aggiunge una dipendenza locale
twenty-sdke la configurazione di Yarn 4 - Crea file di configurazione e script collegati alla CLI
twenty - Genera una configurazione applicativa predefinita e un ruolo funzione predefinito
- 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: Ignora i file generati comuni come
node_modules,.yarn,generated/(client tipizzato),dist/,build/, cartelle di coverage, file di log e file.env*. - yarn.lock, .yarnrc.yml, .yarn/: Bloccano e configurano la toolchain Yarn 4 utilizzata dal progetto.
- .nvmrc: Fissa la versione di Node.js prevista dal progetto.
- eslint.config.mjs e tsconfig.json: Forniscono linting e configurazione TypeScript per i sorgenti TypeScript della tua app.
- README.md: Un breve README nella radice dell’app con istruzioni di base.
- public/: Una cartella per archiviare risorse pubbliche (immagini, font, file statici) che saranno servite con la tua applicazione. I file collocati qui vengono caricati durante la sincronizzazione e sono accessibili in fase di esecuzione.
- src/: Il luogo principale in cui definisci la tua applicazione come codice
Rilevamento delle entità
L’SDK rileva le entità analizzando i tuoi file TypeScript alla ricerca di chiamateexport default define<Entity>({...}). Ogni tipo di entità ha una corrispondente funzione helper esportata da twenty-sdk:
| Funzione helper | Tipo di entità |
|---|---|
defineObject() | Definizioni di oggetti personalizzati |
defineLogicFunction() | Definizioni di funzioni logiche |
defineFrontComponent() | Definizioni dei componenti front-end |
defineRole() | Definizioni di ruoli |
defineField() | Estensioni di campo per oggetti esistenti |
La denominazione dei file è flessibile. Il rilevamento delle entità è basato sull’AST — l’SDK esegue la scansione dei file sorgente alla ricerca del pattern
export default define<Entity>({...}). Puoi organizzare file e cartelle come preferisci. Raggruppare per tipo di entità (ad es., logic-functions/, roles/) è solo una convenzione per l’organizzazione del codice, non un requisito.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.
Autenticazione
The first time you runyarn twenty auth:login, you’ll be prompted for:
- URL dell’API (predefinito a http://localhost:3000 o al profilo dello spazio di lavoro corrente)
- Chiave API
~/.twenty/config.json. Puoi mantenere più profili e passare da uno all’altro.
Gestione delle aree di lavoro
yarn twenty auth:switch, all subsequent commands will use that workspace by default. Puoi comunque sovrascriverla temporaneamente con --workspace <name>.
Usa le risorse dell’SDK (tipi e configurazione)
Il pacchetto twenty-sdk fornisce blocchi tipizzati e funzioni helper da usare nella tua app. Di seguito gli elementi principali con cui interagirai più spesso.Funzioni helper
L’SDK fornisce funzioni helper per definire le entità della tua app. Come descritto in Rilevamento delle entità, devi usareexport default define<Entity>({...}) affinché le tue entità vengano rilevate:
| Funzione | Scopo |
|---|---|
defineApplication() | Configura i metadati dell’applicazione (obbligatorio, uno per app) |
defineObject() | Definisci oggetti personalizzati con campi |
defineLogicFunction() | Definisci funzioni logiche con handler |
defineFrontComponent() | Definisci componenti front-end per un’interfaccia utente personalizzata |
defineRole() | Configura i permessi dei ruoli e l’accesso agli oggetti |
defineField() | Estendi gli oggetti esistenti con campi aggiuntivi |
Definizione degli oggetti
Gli oggetti personalizzati descrivono sia lo schema sia il comportamento per i record nel tuo spazio di lavoro. UsadefineObject() per definire oggetti con convalida integrata:
- Usa
defineObject()per una convalida integrata e un migliore supporto IDE. - Il
universalIdentifierdeve essere univoco e stabile tra i deployment. - Ogni campo richiede un
name,type,labele il propriouniversalIdentifierstabile. - L’array
fieldsè facoltativo: puoi definire oggetti senza campi personalizzati. - You can scaffold new objects using
yarn twenty entity:add, which guides you through naming, fields, and relationships.
I campi base vengono creati automaticamente. Quando definisci un oggetto personalizzato, Twenty aggiunge automaticamente i campi standard come
name, createdAt, updatedAt, createdBy, position e deletedAt. Non è necessario definirli nel tuo array fields — aggiungi solo i tuoi campi personalizzati.Configurazione dell’applicazione (application-config.ts)
Ogni app ha un singolo fileapplication-config.ts che descrive:
- Identità dell’app: identificatori, nome visualizzato e descrizione.
- Come vengono eseguite le sue funzioni: quale ruolo usano per i permessi.
- Variabili (opzionali): coppie chiave–valore esposte alle funzioni come variabili d’ambiente.
defineApplication() per definire la configurazione della tua applicazione:
- I campi
universalIdentifiersono ID deterministici sotto il tuo controllo; generali una volta e mantienili stabili tra le sincronizzazioni. applicationVariablesdiventano variabili d’ambiente per le tue funzioni (ad esempio,DEFAULT_RECIPIENT_NAMEè disponibile comeprocess.env.DEFAULT_RECIPIENT_NAME).defaultRoleUniversalIdentifierdeve corrispondere al file del ruolo (vedi sotto).
Ruoli e permessi
Le applicazioni possono definire ruoli che incapsulano i permessi sugli oggetti e sulle azioni del tuo spazio di lavoro. Il campodefaultRoleUniversalIdentifier in application-config.ts indica il ruolo predefinito utilizzato dalle funzioni logiche della tua app.
- La chiave API di runtime iniettata come
TWENTY_API_KEYè derivata da questo ruolo funzione predefinito. - Il client tipizzato sarà limitato ai permessi concessi a quel ruolo.
- Segui il principio del privilegio minimo: crea un ruolo dedicato con solo i permessi necessari alle tue funzioni, quindi fai riferimento al suo identificatore universale.
Ruolo funzione predefinito (*.role.ts)
Quando generi una nuova app con lo scaffolder, la CLI crea anche un file di ruolo predefinito. UsadefineRole() per definire ruoli con convalida integrata:
universalIdentifier di questo ruolo viene quindi referenziato in application-config.ts come defaultRoleUniversalIdentifier. In altre parole:
- *.role.ts definisce ciò che il ruolo funzione predefinito può fare.
- application-config.ts punta a quel ruolo in modo che le tue funzioni ne ereditino i permessi.
- Parti dal ruolo generato dallo scaffolder, quindi restringilo progressivamente seguendo il principio del privilegio minimo.
- Sostituisci
objectPermissionsefieldPermissionscon gli oggetti/campi di cui le tue funzioni hanno bisogno. permissionFlagscontrollano l’accesso alle funzionalità a livello di piattaforma. Mantienili al minimo; aggiungi solo ciò che ti serve.- Vedi un esempio funzionante nell’app Hello World:
packages/twenty-apps/hello-world/src/roles/function-role.ts.
Configurazione e punto di ingresso della funzione logica
Ogni file di funzione usadefineLogicFunction() per esportare una configurazione con un handler e trigger opzionali.
- route: Espone la funzione su un percorso e metodo HTTP sotto l’endpoint
/s/:
es.path: '/post-card/create',-> chiamata su<APP_URL>/s/post-card/create
- cron: Esegue la tua funzione secondo una pianificazione utilizzando un’espressione CRON.
- databaseEvent: Viene eseguito sugli eventi del ciclo di vita degli oggetti dello spazio di lavoro. Quando l’operazione dell’evento è
updated, è possibile specificare campi specifici da monitorare nell’arrayupdatedFields. Se lasciato non definito o vuoto, qualsiasi aggiornamento attiverà la funzione.
es. person.updated
Note:
- L’array
triggersè facoltativo. Le funzioni senza trigger possono essere utilizzate come funzioni di utilità richiamate da altre funzioni. - Puoi combinare più tipi di trigger in un’unica funzione.
Payload del trigger di route
Quando un trigger di route invoca la tua funzione logica, questa riceve un oggettoRoutePayload che segue il formato AWS HTTP API v2. Importa il tipo da twenty-sdk:
RoutePayload ha la seguente struttura:
| Proprietà | Tipo | Descrizione |
|---|---|---|
headers | Record<string, string | undefined> | Intestazioni HTTP (solo quelle elencate in forwardedRequestHeaders) |
queryStringParameters | Record<string, string | undefined> | Parametri della query string (valori multipli uniti da virgole) |
pathParameters | Record<string, string | undefined> | Parametri di percorso estratti dal pattern della route (ad es., /users/:id → { id: '123' }) |
corpo | object | null | Corpo della richiesta analizzato (JSON) |
isBase64Encoded | booleano | Indica se il corpo è codificato in base64 |
requestContext.http.method | string | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) |
requestContext.http.path | string | Percorso della richiesta non elaborato |
Inoltro delle intestazioni HTTP
Per impostazione predefinita, le intestazioni HTTP delle richieste in ingresso non vengono passate alla tua funzione logica per motivi di sicurezza. Per accedere a intestazioni specifiche, elencale esplicitamente nell’arrayforwardedRequestHeaders:
I nomi delle intestazioni vengono normalizzati in minuscolo. Accedile usando chiavi in minuscolo (ad esempio,
event.headers['content-type']).- Scaffolded: Run
yarn twenty entity:addand choose the option to add a new logic function. Questo genera un file iniziale con un handler e una configurazione. - Manuale: Crea un nuovo file
*.logic-function.tse usadefineLogicFunction(), seguendo lo stesso schema.
Componenti front-end
I componenti front-end ti consentono di creare componenti React personalizzati che vengono renderizzati all’interno dell’interfaccia di Twenty. UsadefineFrontComponent() per definire componenti con convalida integrata:
- I componenti front-end sono componenti React che eseguono il rendering in contesti isolati all’interno di Twenty.
- Usa il suffisso di file
*.front-component.tsxper il rilevamento automatico. - Il campo
componentfa riferimento al tuo componente 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. - Manuale: Crea un nuovo file
*.front-component.tsxe usadefineFrontComponent().
Client tipizzato generato
Runyarn twenty app:generate to create a local typed client in generated/ based on your workspace schema. Usalo nelle tue funzioni:
yarn twenty app:generate. Eseguilo nuovamente dopo aver modificato i tuoi oggetti oppure quando effettui l’onboarding su un nuovo spazio di lavoro.
Credenziali di runtime nelle funzioni logiche
Quando la tua funzione viene eseguita su Twenty, la piattaforma inietta le credenziali come variabili d’ambiente prima dell’esecuzione del tuo codice:TWENTY_API_URL: URL di base dell’API Twenty a cui punta la tua app.TWENTY_API_KEY: Chiave a breve durata con ambito al ruolo funzione predefinito della tua applicazione.
- Non è necessario passare URL o chiave API al client generato. Legge
TWENTY_API_URLeTWENTY_API_KEYda process.env in fase di esecuzione. - I permessi della chiave API sono determinati dal ruolo referenziato nel tuo
application-config.tstramitedefaultRoleUniversalIdentifier. Questo è il ruolo predefinito utilizzato dalle funzioni logiche della tua applicazione. - Le applicazioni possono definire ruoli per seguire il principio del privilegio minimo. Concedi solo i permessi necessari alle tue funzioni, quindi punta
defaultRoleUniversalIdentifierall’identificatore universale di quel ruolo.
Esempio Hello World
Esplora un esempio minimale end-to-end che dimostra oggetti, funzioni logiche, componenti front-end e trigger multipli qui:Configurazione manuale (senza lo scaffolder)
Sebbene consigliamo di utilizzarecreate-twenty-app per la migliore esperienza iniziale, puoi anche configurare un progetto manualmente. Non installare la CLI globalmente. 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.
Risoluzione dei problemi
- Authentication errors: run
yarn twenty auth:loginand ensure your API key has the required permissions. - Impossibile connettersi al server: verifica l’URL dell’API e che il server Twenty sia raggiungibile.
- 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.