Vai al contenuto principale
Le app sono attualmente in fase alfa. La funzionalità è funzionante ma ancora in evoluzione.

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

Per iniziare

Crea una nuova app utilizzando lo scaffolder ufficiale, quindi autenticati e inizia a sviluppare:
# Scaffold a new app
npx create-twenty-app@latest my-twenty-app
cd my-twenty-app

# If you don't use yarn@4
corepack enable
yarn install

# Authenticate using your API key (you'll be prompted)
yarn twenty auth:login

# Start dev mode: automatically syncs local changes to your workspace
yarn twenty app:dev
Da qui puoi:
# Add a new entity to your application (guided)
yarn twenty entity:add

# Generate a typed Twenty client and workspace entity types
yarn twenty app:generate

# Watch your application's function logs
yarn twenty function:logs

# Execute a function by name
yarn twenty function:execute -n my-function -p '{"name": "test"}'

# Uninstall the application from the current workspace
yarn twenty app:uninstall

# Display commands' help
yarn twenty help
Vedi anche: le pagine di riferimento della CLI per create-twenty-app e twenty-sdk CLI.

Struttura del progetto (generata dallo scaffolder)

Quando esegui npx create-twenty-app@latest my-twenty-app, lo scaffolder:
  • Copia un’applicazione base minimale in my-twenty-app/
  • Aggiunge una dipendenza locale twenty-sdk e 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
Un’app appena generata dallo scaffolder si presenta così:
my-twenty-app/
  package.json
  yarn.lock
  .gitignore
  .nvmrc
  .yarnrc.yml
  .yarn/
    install-state.gz
  eslint.config.mjs
  tsconfig.json
  README.md
  public/                           # Cartella delle risorse pubbliche (immagini, font, ecc.)
  src/
  ├── application-config.ts           # Obbligatorio - configurazione principale dell'applicazione
  ├── roles/
  │   └── default-role.ts               # Ruolo predefinito per le funzioni logiche
  ├── logic-functions/
  │   └── hello-world.ts                # Funzione logica di esempio
  └── front-components/
      └── hello-world.tsx               # Componente front-end di esempio
A livello generale:
  • package.json: Declares the app name, version, engines (Node 24+, Yarn 4), and adds twenty-sdk plus a twenty script that delegates to the local twenty CLI. Run yarn twenty help to 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 chiamate export default define<Entity>({...}). Ogni tipo di entità ha una corrispondente funzione helper esportata da twenty-sdk:
Funzione helperTipo 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.
Esempio di entità rilevata:
// This file can be named anything and placed anywhere in src/
import { defineObject, FieldType } from 'twenty-sdk';

export default defineObject({
  universalIdentifier: '...',
  nameSingular: 'postCard',
  // ... rest of config
});
Comandi successivi aggiungeranno altri file e cartelle:
  • yarn twenty app:generate will create a generated/ folder (typed Twenty client + workspace types).
  • yarn twenty entity:add will add entity definition files under src/ for your custom objects, functions, front components, or roles.

Autenticazione

The first time you run yarn 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
Le tue credenziali sono archiviate per utente in ~/.twenty/config.json. Puoi mantenere più profili e passare da uno all’altro.

Gestione delle aree di lavoro

# Login interactively (recommended)
yarn twenty auth:login

# Login to a specific workspace profile
yarn twenty auth:login --workspace my-custom-workspace

# List all configured workspaces
yarn twenty auth:list

# Switch the default workspace (interactive)
yarn twenty auth:switch

# Switch to a specific workspace
yarn twenty auth:switch production

# Check current authentication status
yarn twenty auth:status
Once you’ve switched workspaces with 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 usare export default define<Entity>({...}) affinché le tue entità vengano rilevate:
FunzioneScopo
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
Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell’IDE e la sicurezza dei tipi.

Definizione degli oggetti

Gli oggetti personalizzati descrivono sia lo schema sia il comportamento per i record nel tuo spazio di lavoro. Usa defineObject() per definire oggetti con convalida integrata:
// src/app/postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';

enum PostCardStatus {
  DRAFT = 'DRAFT',
  SENT = 'SENT',
  DELIVERED = 'DELIVERED',
  RETURNED = 'RETURNED',
}

export default defineObject({
  universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
  nameSingular: 'postCard',
  namePlural: 'postCards',
  labelSingular: 'Post Card',
  labelPlural: 'Post Cards',
  description: 'A post card object',
  icon: 'IconMail',
  fields: [
    {
      universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
      name: 'content',
      type: FieldType.TEXT,
      label: 'Content',
      description: "Postcard's content",
      icon: 'IconAbc',
    },
    {
      universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
      name: 'recipientName',
      type: FieldType.FULL_NAME,
      label: 'Recipient name',
      icon: 'IconUser',
    },
    {
      universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
      name: 'recipientAddress',
      type: FieldType.ADDRESS,
      label: 'Recipient address',
      icon: 'IconHome',
    },
    {
      universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
      name: 'status',
      type: FieldType.SELECT,
      label: 'Status',
      icon: 'IconSend',
      defaultValue: `'${PostCardStatus.DRAFT}'`,
      options: [
        { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
        { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
        { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
        { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
      ],
    },
    {
      universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
      name: 'deliveredAt',
      type: FieldType.DATE_TIME,
      label: 'Delivered at',
      icon: 'IconCheck',
      isNullable: true,
      defaultValue: null,
    },
  ],
});
Punti chiave:
  • Usa defineObject() per una convalida integrata e un migliore supporto IDE.
  • Il universalIdentifier deve essere univoco e stabile tra i deployment.
  • Ogni campo richiede un name, type, label e il proprio universalIdentifier stabile.
  • 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 file application-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.
Usa defineApplication() per definire la configurazione della tua applicazione:
// src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';

export default defineApplication({
  universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
  displayName: 'My Twenty App',
  description: 'My first Twenty app',
  icon: 'IconWorld',
  applicationVariables: {
    DEFAULT_RECIPIENT_NAME: {
      universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de',
      description: 'Default recipient name for postcards',
      value: 'Jane Doe',
      isSecret: false,
    },
  },
  defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
});
Note:
  • I campi universalIdentifier sono ID deterministici sotto il tuo controllo; generali una volta e mantienili stabili tra le sincronizzazioni.
  • applicationVariables diventano variabili d’ambiente per le tue funzioni (ad esempio, DEFAULT_RECIPIENT_NAME è disponibile come process.env.DEFAULT_RECIPIENT_NAME).
  • defaultRoleUniversalIdentifier deve 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 campo defaultRoleUniversalIdentifier 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. Usa defineRole() per definire ruoli con convalida integrata:
// src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';

export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
  'b648f87b-1d26-4961-b974-0908fd991061';

export default defineRole({
  universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
  label: 'Default function role',
  description: 'Default role for function Twenty client',
  canReadAllObjectRecords: false,
  canUpdateAllObjectRecords: false,
  canSoftDeleteAllObjectRecords: false,
  canDestroyAllObjectRecords: false,
  canUpdateAllSettings: false,
  canBeAssignedToAgents: false,
  canBeAssignedToUsers: false,
  canBeAssignedToApiKeys: false,
  objectPermissions: [
    {
      objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
      canReadObjectRecords: true,
      canUpdateObjectRecords: true,
      canSoftDeleteObjectRecords: false,
      canDestroyObjectRecords: false,
    },
  ],
  fieldPermissions: [
    {
      objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
      fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff',
      canReadFieldValue: false,
      canUpdateFieldValue: false,
    },
  ],
  permissionFlags: [PermissionFlag.APPLICATIONS],
});
L’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.
Note:
  • Parti dal ruolo generato dallo scaffolder, quindi restringilo progressivamente seguendo il principio del privilegio minimo.
  • Sostituisci objectPermissions e fieldPermissions con gli oggetti/campi di cui le tue funzioni hanno bisogno.
  • permissionFlags controllano 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 usa defineLogicFunction() per esportare una configurazione con un handler e trigger opzionali.
// src/app/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '~/generated';

const handler = async (params: RoutePayload) => {
  const client = new Twenty(); // generated typed client
  const name = 'name' in params.queryStringParameters
    ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
    : 'Hello world';

  const result = await client.mutation({
    createPostCard: {
      __args: { data: { name } },
      id: true,
      name: true,
    },
  });
  return result;
};

export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'create-new-post-card',
  timeoutSeconds: 2,
  handler,
  triggers: [
    // Public HTTP route trigger '/s/post-card/create'
    {
      universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
      type: 'route',
      path: '/post-card/create',
      httpMethod: 'GET',
      isAuthRequired: false,
    },
    // Cron trigger (CRON pattern)
    // {
    //   universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
    //   type: 'cron',
    //   pattern: '0 0 1 1 *',
    // },
    // Database event trigger
    // {
    //   universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
    //   type: 'databaseEvent',
    //   eventName: 'person.updated',
    //   updatedFields: ['name'],
    // },
  ],
});
Tipi di trigger comuni:
  • 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’array updatedFields. 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

Modifica non retrocompatibile (v1.16, gennaio 2026): Il formato del payload del trigger di route è cambiato. Prima della v1.16, i parametri di query, i parametri di percorso e il corpo venivano inviati direttamente come payload. A partire dalla v1.16, sono annidati all’interno di un oggetto RoutePayload strutturato.Prima della v1.16:
const handler = async (params) => {
  const { param1, param2 } = params; // Direct access
};
Dopo la v1.16:
const handler = async (event: RoutePayload) => {
  const { param1, param2 } = event.body; // Access via .body
  const { queryParam } = event.queryStringParameters;
  const { id } = event.pathParameters;
};
Per migrare le funzioni esistenti: Aggiorna l’handler per estrarre i dati da event.body, event.queryStringParameters o event.pathParameters invece che direttamente dall’oggetto params.
Quando un trigger di route invoca la tua funzione logica, questa riceve un oggetto RoutePayload che segue il formato AWS HTTP API v2. Importa il tipo da twenty-sdk:
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';

const handler = async (event: RoutePayload) => {
  // Access request data
  const { headers, queryStringParameters, pathParameters, body } = event;

  // HTTP method and path are available in requestContext
  const { method, path } = event.requestContext.http;

  return { message: 'Success' };
};
Il tipo RoutePayload ha la seguente struttura:
ProprietàTipoDescrizione
headersRecord<string, string | undefined>Intestazioni HTTP (solo quelle elencate in forwardedRequestHeaders)
queryStringParametersRecord<string, string | undefined>Parametri della query string (valori multipli uniti da virgole)
pathParametersRecord<string, string | undefined>Parametri di percorso estratti dal pattern della route (ad es., /users/:id{ id: '123' })
corpoobject | nullCorpo della richiesta analizzato (JSON)
isBase64EncodedbooleanoIndica se il corpo è codificato in base64
requestContext.http.methodstringMetodo HTTP (GET, POST, PUT, PATCH, DELETE)
requestContext.http.pathstringPercorso 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’array forwardedRequestHeaders:
export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'webhook-handler',
  handler,
  triggers: [
    {
      universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
      type: 'route',
      path: '/webhook',
      httpMethod: 'POST',
      isAuthRequired: false,
      forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
    },
  ],
});
Nel tuo handler, puoi quindi accedere a queste intestazioni:
const handler = async (event: RoutePayload) => {
  const signature = event.headers['x-webhook-signature'];
  const contentType = event.headers['content-type'];

  // Validate webhook signature...
  return { received: true };
};
I nomi delle intestazioni vengono normalizzati in minuscolo. Accedile usando chiavi in minuscolo (ad esempio, event.headers['content-type']).
Puoi creare nuove funzioni in due modi:
  • Scaffolded: Run yarn twenty entity:add and 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.ts e usa defineLogicFunction(), 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. Usa defineFrontComponent() per definire componenti con convalida integrata:
// src/my-widget.front-component.tsx
import { defineFrontComponent } from 'twenty-sdk';

const MyWidget = () => {
  return (
    <div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
      <h1>My Custom Widget</h1>
      <p>This is a custom front component for Twenty.</p>
    </div>
  );
};

export default defineFrontComponent({
  universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
  name: 'my-widget',
  description: 'A custom widget component',
  component: MyWidget,
});
Punti chiave:
  • 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.tsx per il rilevamento automatico.
  • Il campo component fa riferimento al tuo componente React.
  • Components are built and synced automatically during yarn twenty app:dev.
Puoi creare nuovi componenti front-end in due modi:
  • Scaffolded: Run yarn twenty entity:add and choose the option to add a new front component.
  • Manuale: Crea un nuovo file *.front-component.tsx e usa defineFrontComponent().

Client tipizzato generato

Run yarn twenty app:generate to create a local typed client in generated/ based on your workspace schema. Usalo nelle tue funzioni:
import Twenty from '~/generated';

const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
The client is re-generated by 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.
Note:
  • Non è necessario passare URL o chiave API al client generato. Legge TWENTY_API_URL e TWENTY_API_KEY da process.env in fase di esecuzione.
  • I permessi della chiave API sono determinati dal ruolo referenziato nel tuo application-config.ts tramite defaultRoleUniversalIdentifier. 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 defaultRoleUniversalIdentifier all’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 utilizzare create-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:
yarn add -D twenty-sdk
Then add a twenty script:
{
  "scripts": {
    "twenty": "twenty"
  }
}
Now you can run all commands via 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:login and 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:dev is running and that changes are not ignored by your environment.
Canale di supporto su Discord: https://discord.com/channels/1130383047699738754/1130386664812982322