What Are Apps?
Apps let you build and manage Twenty customizations as code. Instead of configuring everything through the UI, you define your data model and serverless functions in code — making it faster to build, maintain, and roll out to multiple workspaces. What you can do today:- Define custom objects and fields as code (managed data model)
- Build serverless functions with custom triggers
- Deploy the same app across multiple workspaces
- Custom UI layouts and components
Předpoklady
- Node.js 24+ and Yarn 4
- A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)
Getting Started
Create a new app using the official scaffolder, then authenticate and start developing:Project structure (scaffolded)
When you runnpx create-twenty-app@latest my-twenty-app, the scaffolder:
- Copies a minimal base application into
my-twenty-app/ - Adds a local
twenty-sdkdependency and Yarn 4 configuration - Creates config files and scripts wired to the
twentyCLI - Generates a default application config and a default function role
- package.json: Declares the app name, version, engines (Node 24+, Yarn 4), and adds
twenty-sdkplus scripts likedev,sync,generate,create-entity,logs,uninstall, andauththat delegate to the localtwentyCLI. - .gitignore: Ignores common artifacts such as
node_modules,.yarn,generated/(typed client),dist/,build/, coverage folders, log files, and.env*files. - yarn.lock, .yarnrc.yml, .yarn/: Lock and configure the Yarn 4 toolchain used by the project.
- .nvmrc: Pins the Node.js version expected by the project.
- eslint.config.mjs and tsconfig.json: Provide linting and TypeScript configuration for your app’s TypeScript sources.
- README.md: A short README in the app root with basic instructions.
- src/: The main place where you define your application-as-code:
application.config.ts: Global configuration for your app (metadata and runtime wiring). See “Application config” below.role.config.ts: Default function role used by your serverless functions. See “Default function role” below.- Future entities, actions/functions, and any supporting code you add.
yarn generatewill create agenerated/folder (typed Twenty client + workspace types).yarn create-entitywill add entity definition files undersrc/for your custom objects.
Ověření
The first time you runyarn auth, you’ll be prompted for:
- API URL (defaults to http://localhost:3000 or your current workspace profile)
- API key
~/.twenty/config.json. You can maintain multiple profiles and switch using --workspace <name>.
Příklady:
Use the SDK resources (types & config)
The twenty-sdk provides typed building blocks you use inside your app. Below are the key pieces you’ll touch most often.Defining objects
Custom objects are regular TypeScript classes annotated with decorators fromtwenty-sdk. They live under src/objects/ in your app and describe both schema and behavior for records in your workspace.
Here is an example postCard object from the Hello World app:
- The
@Objectdecorator defines the object identity and labels used across the workspace; itsuniversalIdentifiermust be unique and stable across deployments. - Each
@Fielddecorator defines a field on the object with a type, label, and its own stableuniversalIdentifier. @Relationwires this object to other objects (standard or custom) and controls cascade behavior withonDelete.- You can scaffold new objects using
yarn create-entity, which guides you through naming, fields, and relationships, then generates object files similar to thepostCardexample.
Application config (application.config.ts)
Every app has a singleapplication.config.ts file that describes:
- Who the app is: identifiers, display name, and description.
- How its functions run: which role they use for permissions.
- (Optional) variables: key–value pairs exposed to your functions as environment variables.
universalIdentifierfields are deterministic IDs you own; generate them once and keep them stable across syncs.applicationVariablesbecome environment variables for your functions (for example,DEFAULT_RECIPIENT_NAMEis available asprocess.env.DEFAULT_RECIPIENT_NAME).functionRoleUniversalIdentifiermust match the role you define inrole.config.ts(see below).
Roles and permissions
Applications can define roles that encapsulate permissions on your workspace’s objects and actions. The fieldfunctionRoleUniversalIdentifier in application.config.ts designates the default role used by your app’s serverless functions.
- The runtime API key injected as
TWENTY_API_KEYis derived from this default function role. - The typed client will be restricted to the permissions granted to that role.
- Follow least‑privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
Default function role (role.config.ts)
When you scaffold a new app, the CLI also createssrc/role.config.ts. This file exports the default role your serverless functions will use at runtime:
universalIdentifier of this role is automatically wired into application.config.ts as functionRoleUniversalIdentifier. In other words:
- role.config.ts defines what the default function role can do.
- application.config.ts points to that role so your functions inherit its permissions.
- Start from the scaffolded role, then progressively restrict it following least‑privilege.
- Replace the
objectPermissionsandfieldPermissionswith the objects/fields your functions need. permissionFlagscontrol access to platform-level capabilities. Keep them minimal; add only what you need.- See a working example in the Hello World app:
packages/twenty-apps/hello-world/src/roles/function-role.ts.
Serverless function config and entrypoint
Each function exports a main handler and a config describing its triggers. You can mix multiple trigger types.- route: Exposes your function on an HTTP path and method under the
/s/endpoint:
e.g.path: '/post-card/create',-> call on<APP_URL>/s/post-card/create
- cron: Runs your function on a schedule using a CRON expression.
- databaseEvent: Runs on workspace object lifecycle events
e.g. person.created
You can create new functions in two ways:
- Scaffolded: Run
yarn create-entity --path <custom-path>and choose the option to add a new function. This generates a starter file under<custom-path>with amainhandler and aconfigblock similar to the example above. - Manual: Create a new file and export
mainandconfigyourself, following the same pattern.
Generated typed client
Run yarn generate to create a local typed client in generated/ based on your workspace schema. Use it in your functions:yarn generate. Re-run after changing your objects and yarn sync or when onboarding to a new workspace.
Runtime credentials in serverless functions
When your function runs on Twenty, the platform injects credentials as environment variables before your code executes:TWENTY_API_URL: Base URL of the Twenty API your app targets.TWENTY_API_KEY: Short‑lived key scoped to your application’s default function role.
- You do not need to pass URL or API key to the generated client. It reads
TWENTY_API_URLandTWENTY_API_KEYfrom process.env at runtime. - The API key’s permissions are determined by the role referenced in your
application.config.tsviafunctionRoleUniversalIdentifier. This is the default role used by serverless functions of your application. - Applications can define roles to follow least‑privilege. Grant only the permissions your functions need, then point
functionRoleUniversalIdentifierto that role’s universal identifier.
Hello World example
Explore a minimal, end-to-end example that demonstrates objects, functions, and multiple triggers here:Manual setup (without the scaffolder)
While we recommend usingcreate-twenty-app for the best getting-started experience, you can also set up a project manually. Do not install the CLI globally. Instead, add twenty-sdk as a local dependency and wire scripts in your package.json:
yarn dev, yarn sync, etc.
Řešení potíží
- Authentication errors: run
yarn authand ensure your API key has the required permissions. - Cannot connect to server: verify the API URL and that the Twenty server is reachable.
- Types or client missing/outdated: run
yarn generateand thenyarn dev. - Dev mode not syncing: ensure
yarn devis running and that changes are not ignored by your environment.