### Install Twenty SDK and Client SDK
Source: https://docs.twenty.com/developers/extend/apps/getting-started/local-server
Installs the necessary Twenty SDK and client SDK packages for manual setup without the scaffolder.
```bash
yarn add twenty-sdk twenty-client-sdk
```
--------------------------------
### Install and Start PostgreSQL on macOS
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Installs PostgreSQL version 16 using Homebrew, adds it to your PATH, and starts the service. It then creates the 'default' and 'test' databases.
```bash
brew install postgresql@16
export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"
brew services start postgresql@16
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
--------------------------------
### Download Twenty .env Example File
Source: https://docs.twenty.com/developers/self-host/capabilities/docker-compose
Fetches the example environment file for Twenty. This file should be copied to .env and configured.
```bash
curl -o .env https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/.env.example
```
--------------------------------
### Start Frontend and Backend Development Servers
Source: https://docs.twenty.com/developers/contribute/commands
Use these commands to start the development servers for the frontend and backend applications.
```bash
npx nx start twenty-front # Frontend dev server (http://localhost:3001)
npx nx start twenty-server # Backend server (http://localhost:3000)
```
--------------------------------
### Basic Iterator Setup: Emailing Search Results
Source: https://docs.twenty.com/user-guide/workflows/capabilities/use-iterator
This example demonstrates the basic setup for using an Iterator to process records found by a Search Records action. It includes searching for people in a specific company, filtering to ensure results exist, and then iterating to send a personalized email to each person.
```workflow
1. Add **Search Records** action
2. Object: **People**
3. Filter: Company equals "Acme Inc"
4. This returns an array of people
1. Add **Filter** action
2. Condition: `{{searchRecords.length}}` is greater than 0
3. This prevents Iterator errors on empty results
1. Add **Iterator** action
2. Array input: Select `{{searchRecords}}`
3. This creates a loop
1. Add **Send Email** action (inside iterator)
2. To: `{{iterator.currentItem.email}}`
3. Subject: Hello `{{iterator.currentItem.firstName}}`!
4. Body: Personalized message using current item fields
```
--------------------------------
### Start Redis Service using Homebrew (Mac OS)
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Start the Redis server after installing it with Homebrew on Mac OS. This command ensures Redis is running in the background.
```bash
brew services start redis
```
--------------------------------
### Copy Environment Example Files
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Copy the example environment files to create your local configuration files for both the frontend and server packages.
```bash
cp ./packages/twenty-front/.env.example ./packages/twenty-front/.env
cp ./packages/twenty-server/.env.example ./packages/twenty-server/.env
```
--------------------------------
### Start Development Server
Source: https://docs.twenty.com/developers/extend/apps/getting-started/quick-start
Starts the development server which watches for changes in the `src/` directory and syncs them to the server. Press Ctrl+C to stop.
```bash
cd my-twenty-app
yarn twenty dev
```
--------------------------------
### Install Project Dependencies
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Install all necessary project dependencies for the Twenty server and to seed the database. Note that npm or pnpm will not work.
```bash
yarn
```
--------------------------------
### Start Development Mode
Source: https://docs.twenty.com/developers/extend/apps/getting-started
Navigate into your project directory and run this command to start the development server. It watches for changes in the 'src/' directory and syncs them live to the Twenty server.
```bash
cd my-twenty-app
yarn twenty dev
```
--------------------------------
### Install App from Command Line
Source: https://docs.twenty.com/developers/extend/apps/operations/publishing
Install a Twenty application directly from the command line. The server enforces semver versioning, rejecting downgrades or re-installs of the same version.
```bash
yarn twenty app:install
```
--------------------------------
### Example SERVER_URL for Domain Access with SSL
Source: https://docs.twenty.com/developers/self-host/capabilities/docker-compose
Example of a SERVER_URL for accessing the application via a domain name with SSL enabled.
```env
SERVER_URL=https://mytwentyapp.com
```
--------------------------------
### Start All Twenty Services
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Start all Twenty services (server, worker, and frontend) simultaneously with a single command. This is a convenient way to launch the entire project.
```bash
npx nx start
```
--------------------------------
### Install WSL on Windows
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Use this command in PowerShell as Administrator to install the Windows Subsystem for Linux.
```powershell
wsl --install
```
--------------------------------
### Test Setup File for Twenty Server
Source: https://docs.twenty.com/developers/extend/apps/operations/testing
Set up integration tests by verifying the Twenty server is reachable and writing a temporary configuration file for the SDK. This setup runs before all tests.
```typescript
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { beforeAll } from 'vitest';
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
beforeAll(async () => {
// Verify the server is running
const response = await fetch(`${TWENTY_API_URL}/healthz`);
if (!response.ok) {
throw new Error(
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
'Start the server before running integration tests.',
);
}
// Write a temporary config for the SDK
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
fs.writeFileSync(
path.join(TEST_CONFIG_DIR, 'config.json'),
JSON.stringify({
remotes: {
local: {
apiUrl: process.env.TWENTY_API_URL,
apiKey: process.env.TWENTY_API_KEY,
},
},
defaultRemote: 'local',
}, null, 2),
);
});
```
--------------------------------
### Install/Upgrade Deployed Version
Source: https://docs.twenty.com/developers/extend/apps/operations/sync-and-recovery
Use `yarn twenty app:install` to install the version currently deployed to the workspace.
```bash
yarn twenty app:install
```
--------------------------------
### Install Specific Twenty Version with Docker Compose Script
Source: https://docs.twenty.com/developers/self-host/capabilities/docker-compose
Installs a specific version or branch of Twenty using the installation script. Replace x.y.z with the version and branch-name with the desired branch.
```bash
VERSION=vx.y.z BRANCH=branch-name bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
```
--------------------------------
### Install and Use Recommended Node.js Version with NVM
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Installs the recommended Node.js version using nvm, uses it, and enables Corepack for package managers.
```bash
nvm install
nvm use
corepack enable
```
--------------------------------
### Install Latest Twenty with Docker Compose Script
Source: https://docs.twenty.com/developers/self-host/capabilities/docker-compose
Installs the latest stable version of Twenty using a one-line bash script. Ensure Docker and Docker Compose are installed.
```bash
bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
```
--------------------------------
### Install Git and Configure User on Ubuntu (WSL)
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Installs Git and configures global user name and email for Git on an Ubuntu WSL environment.
```bash
sudo apt-get install git
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"
```
--------------------------------
### Start a Local Twenty Server
Source: https://docs.twenty.com/developers/extend/apps/getting-started
This command starts a local Twenty server using Docker, which is necessary for syncing your app's code. Ensure Docker is running before executing.
```bash
yarn twenty docker:start
```
--------------------------------
### Example SERVER_URL for Direct Access
Source: https://docs.twenty.com/developers/self-host/capabilities/docker-compose
Example of a SERVER_URL for direct access without SSL, showing a specific IP address and port.
```env
SERVER_URL=http://123.45.67.89:3000
```
--------------------------------
### Start PostgreSQL with Docker on Linux/WSL
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Initiates a PostgreSQL instance using Docker. This command is run from the 'packages/twenty-docker' directory.
```bash
make -C packages/twenty-docker postgres-on-docker
```
--------------------------------
### Start Parallel Test Instance
Source: https://docs.twenty.com/developers/extend/apps/getting-started/local-server
Starts a second, isolated instance of the Twenty server for testing purposes. It defaults to port 2021.
```bash
yarn twenty docker:start --test
```
--------------------------------
### Start Individual Twenty Services
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Start the Twenty server, worker, and frontend services independently. Use these commands if you need to manage services separately.
```bash
npx nx start twenty-server
npx nx worker twenty-server
npx nx start twenty-front
```
--------------------------------
### Install Vitest and Vite TS Paths
Source: https://docs.twenty.com/developers/extend/apps/operations/testing
Install Vitest and vite-tsconfig-paths as development dependencies for setting up integration tests.
```bash
yarn add -D vitest vite-tsconfig-paths
```
--------------------------------
### Install Redis on Docker (Linux, Mac OS, Windows)
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Use this command to provision Redis locally if you have Docker installed. This is a cross-platform option.
```bash
make -C packages/twenty-docker redis-on-docker
```
--------------------------------
### Install Redis using Homebrew (Mac OS)
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Install Redis locally on Mac OS using the Homebrew package manager. This is the preferred method for Mac users.
```bash
brew install redis
```
--------------------------------
### Display Formatted Date in a Front Component
Source: https://docs.twenty.com/developers/extend/apps/operations/testing
Example of defining a front component that uses the date-fns package to format the current date. Ensure date-fns is installed via npm or yarn.
```typescript
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
return
Today is {format(new Date(), 'MMMM do, yyyy')}
;
};
export default defineFrontComponent({
universalIdentifier: '...',
name: 'date-widget',
component: DateWidget,
});
```
--------------------------------
### Fetch Data with Axios in a Logic Function
Source: https://docs.twenty.com/developers/extend/apps/operations/testing
Example of defining a logic function that uses the axios npm package to fetch data from an external API. Ensure axios is installed via npm or yarn.
```typescript
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise => {
const { data } = await axios.get('https://api.example.com/data');
return { data };
};
export default defineLogicFunction({
universalIdentifier: '...',
name: 'fetch-data',
description: 'Fetches data from an external API',
timeoutSeconds: 10,
handler,
});
```
--------------------------------
### Type Annotations with CoreSchema
Source: https://docs.twenty.com/developers/extend/apps/logic/logic-functions
Utilize CoreSchema to get TypeScript types that match your workspace objects, which is helpful for typing component state or function parameters. This example demonstrates typing a company state variable.
```typescript
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
import { useState } from 'react';
const [company, setCompany] = useState<
Pick | undefined
>(undefined);
const client = new CoreApiClient();
const result = await client.query({
company: {
__args: { filter: { position: { eq: 1 } } },
id: true,
name: true,
},
});
setCompany(result.company);
```
--------------------------------
### Cache Expensive API Call with KV Store
Source: https://docs.twenty.com/developers/extend/apps/logic/key-value-store
Cache an expensive API call to avoid repeated costs. This example caches an exchange rate for one hour. It uses `get` to retrieve cached data and `set` to store new data.
```typescript
import {
defineLogicFunction
} from 'twenty-sdk/define';
import { get, set } from './handlers/kv-store';
const ONE_HOUR_MS = 60 * 60 * 1000;
type CachedRate = {
rate: number;
fetchedAt: number;
};
const handler = async (params: {
from: string;
to: string;
}) => {
const cacheKey = `exchange-rate:${params.from}:${params.to}`;
const cached = await get(cacheKey);
if (cached && Date.now() - cached.fetchedAt < ONE_HOUR_MS) {
return {
rate: cached.rate,
cached: true
};
}
const response = await fetch(
`https://api.example.com/rate?from=${params.from}&to=${params.to}`,
);
const { rate } = (await response.json()) as {
rate: number;
};
await set(cacheKey, {
rate,
fetchedAt: Date.now()
});
return {
rate,
cached: false
};
};
export default defineLogicFunction({
universalIdentifier: 'd9b2f4e6-1c83-4a07-9e52-6b1d3c8a0f47',
name: 'get-exchange-rate',
timeoutSeconds: 10,
handler,
});
```
--------------------------------
### Install Curl and NVM on Ubuntu (WSL)
Source: https://docs.twenty.com/developers/contribute/capabilities/local-setup
Installs Curl and the Node Version Manager (nvm) script to manage Node.js installations.
```bash
sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
```
--------------------------------
### Integration Test for App Installation
Source: https://docs.twenty.com/developers/extend/apps/operations/testing
This integration test verifies the build, deploy, install, and uninstall process of a Twenty application. It ensures the app is correctly registered and discoverable in the workspace after installation.
```typescript
import {
APPLICATION_UNIVERSAL_IDENTIFIER,
} from 'src/application-config';
import {
appBuild,
appDeploy,
appInstall,
appUninstall,
} from 'twenty-sdk/cli';
import {
MetadataApiClient,
} from 'twenty-client-sdk/metadata';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
const APP_PATH = process.cwd();
describe('App installation', () => {
beforeAll(async () => {
const buildResult = await appBuild({
appPath: APP_PATH,
tarball: true,
onProgress: (message: string) => console.log(`[build] ${message}`),
});
if (!buildResult.success) {
throw new Error(`Build failed: ${buildResult.error?.message}`);
}
const deployResult = await appDeploy({
tarballPath: buildResult.data.tarballPath!,
onProgress: (message: string) => console.log(`[deploy] ${message}`),
});
if (!deployResult.success) {
throw new Error(`Deploy failed: ${deployResult.error?.message}`);
}
const installResult = await appInstall({ appPath: APP_PATH });
if (!installResult.success) {
throw new Error(`Install failed: ${installResult.error?.message}`);
}
});
afterAll(async () => {
await appUninstall({ appPath: APP_PATH });
});
it('should find the installed app in the workspace', async () => {
const metadataClient = new MetadataApiClient();
const result = await metadataClient.query({
findManyApplications: {
id: true,
name: true,
universalIdentifier: true,
},
});
const installedApp = result.findManyApplications.find(
(app: { universalIdentifier: string }) =>
app.universalIdentifier === APPLICATION_UNIVERSAL_IDENTIFIER,
);
expect(installedApp).toBeDefined();
});
});
```
--------------------------------
### Manually Execute Pre-Install Function via CLI
Source: https://docs.twenty.com/developers/extend/apps/config/install-hooks
Demonstrates how to manually trigger the pre-install function using the Twenty CLI during development. This is useful when the automatic install flow is skipped in dev mode.
```bash
yarn twenty dev:function:exec --preInstall
```
--------------------------------
### Start Background Worker
Source: https://docs.twenty.com/developers/contribute/commands
Command to start the background worker process for the backend server.
```bash
npx nx run twenty-server:worker # Background worker
```
--------------------------------
### Twenty App Lifecycle Overview
Source: https://docs.twenty.com/developers/extend/apps/getting-started/concepts
This diagram illustrates the different stages of an app's lifecycle, from development to publishing. It shows the commands used for each stage and the flow of the installation process.
```text
┌─────────────────────────────────────────────────────────┐
│ Development │
│ npx create-twenty-app → yarn twenty dev (live sync) │
├─────────────────────────────────────────────────────────┤
│ Build & Deploy │
│ yarn twenty dev:build → yarn twenty app:publish │
├─────────────────────────────────────────────────────────┤
│ Install flow │
│ upload → [pre-install] → metadata migration → │
│ generate SDK → [post-install] │
├─────────────────────────────────────────────────────────┤
│ Publish │
│ npm publish → appears in Twenty marketplace │
└─────────────────────────────────────────────────────────┘
```
--------------------------------
### Execute Post-Install Hook via CLI
Source: https://docs.twenty.com/developers/extend/apps/config/install-hooks
Manually execute the post-install function at any time using the Twenty CLI. This is useful for testing or re-running setup logic.
```bash
yarn twenty dev:function:exec --postInstall
```
--------------------------------
### Build Frontend Application
Source: https://docs.twenty.com/developers/contribute/commands
Builds the frontend application for production.
```bash
npx nx build twenty-front
```
--------------------------------
### Start Twenty Server Worker
Source: https://docs.twenty.com/developers/self-host/capabilities/troubleshooting
Run this command to start the background worker for the Twenty server, which is often required for emails to be sent.
```sh
npx nx worker twenty-server
```
--------------------------------
### Create Multi-Step Onboarding Tasks
Source: https://docs.twenty.com/user-guide/workflows/how-tos/crm-automations/closed-won-automations
Define an array of tasks with titles, due dates, and assignees. Use an Iterator to create each task.
```javascript
export const main = async (params) => {
const tasks = [
{ title: "Welcome call", daysFromNow: 1, assignee: "CS" },
{ title: "Send onboarding materials", daysFromNow: 2, assignee: "CS" },
{ title: "Technical setup", daysFromNow: 5, assignee: "Support" },
{ title: "30-day check-in", daysFromNow: 30, assignee: "CS" }
];
return { tasks };
};
```
--------------------------------
### Build Backend Application
Source: https://docs.twenty.com/developers/contribute/commands
Builds the backend application for production.
```bash
npx nx build twenty-server
```
--------------------------------
### Build twenty-emails Package
Source: https://docs.twenty.com/developers/self-host/capabilities/troubleshooting
Execute this command to build the 'twenty-emails' package before initializing the database, resolving 'Cannot find module' errors.
```sh
npx nx run twenty-emails:build
```
--------------------------------
### Install a Package with Yarn
Source: https://docs.twenty.com/developers/extend/apps/operations/testing
Install an npm package like axios using yarn. This package can then be imported and used in your logic functions or front components.
```bash
yarn add axios
```
--------------------------------
### Post-install: Seed Default PostCard Record
Source: https://docs.twenty.com/developers/extend/apps/config/install-hooks
Seeds a default 'Welcome to Postcard' record after installation. This hook runs only on fresh installs and is asynchronous by default.
```typescript
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise => {
if (previousVersion) return; // fresh installs only
const client = createClient();
await client.postCard.create({
data: { title: 'Welcome to Postcard', content: 'Your first card!' },
});
};
export default definePostInstallLogicFunction({
universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
name: 'post-install',
description: 'Seeds a welcome post card after install.',
timeoutSeconds: 300,
shouldRunOnVersionUpgrade: false,
handler,
});
```
--------------------------------
### Define Post-Install Logic Function
Source: https://docs.twenty.com/developers/extend/apps/config/install-hooks
Runs after the workspace metadata migration is applied. Use this for seeding default data, creating initial records, or configuring workspace settings. The handler receives an `InstallPayload` with version information.
```typescript
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
};
export default definePostInstallLogicFunction({
universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
name: 'post-install',
description: 'Runs after installation to set up the application.',
timeoutSeconds: 300,
shouldRunOnVersionUpgrade: false,
shouldRunSynchronously: false,
handler,
});
```
--------------------------------
### Build Twenty App
Source: https://docs.twenty.com/developers/extend/apps/operations/publishing
Run this command to compile your app and generate a distribution-ready manifest.json. Add --tarball to also produce a .tgz package for manual distribution.
```bash
yarn twenty dev:build
```
--------------------------------
### Email Body Example
Source: https://docs.twenty.com/user-guide/workflows/how-tos/crm-automations/notify-teammates-of-note-to-review
An example of an email body template for notifying a reviewer. It includes placeholders for the reviewer's name and a direct link to the note.
```text
Hi {{searchRecord.firstWorkspaceMember.name.firstName}},
You've been assigned to review a note.
View the note here:
https://yourSubDomain.twenty.com/object/note/{{recordIsUpdated.id}}
Best,
Twenty
```
--------------------------------
### Typeform Payload Example
Source: https://docs.twenty.com/user-guide/workflows/how-tos/connect-to-other-tools/bring-typeform-submissions-in-twenty
This is a simplified example of the JSON payload sent by Typeform for a form submission. It shows the nested structure and the format of the answers array.
```json
{
"event_type": "form_response",
"form_response": {
"form_id": "abc123",
"submitted_at": "2025-01-15T10:30:00Z",
"answers": [
{
"text": "Jane",
"type": "text",
"field": { "id": "field1", "type": "short_text", "title": "First Name" }
},
{
"text": "Smith",
"type": "text",
"field": { "id": "field2", "type": "short_text", "title": "Last Name" }
},
{
"text": "Acme Corp",
"type": "text",
"field": { "id": "field3", "type": "short_text", "title": "Company" }
},
{
"email": "jane@acme.com",
"type": "email",
"field": { "id": "field4", "type": "email", "title": "Email" }
},
{
"type": "choice",
"field": { "id": "field5", "type": "dropdown", "title": "Team Size" },
"choice": { "label": "10-50" }
}
]
}
}
```
--------------------------------
### Styling Front Components with Twenty UI and Inline Styles
Source: https://docs.twenty.com/developers/extend/apps/layout/front-components
Demonstrates using Twenty UI components like Button, Tag, and Status, along with inline styles for layout and spacing. Import necessary components from `twenty-sdk/ui`.
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
return (
);
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-567890123456',
name: 'styled-widget',
component: StyledWidget,
});
```
--------------------------------
### Enable Database Configuration
Source: https://docs.twenty.com/developers/self-host/capabilities/setup
Set this environment variable to true to enable configuration management through the Admin Panel. This is the default behavior.
```bash
IS_CONFIG_VARIABLES_IN_DB_ENABLED=true # default
```
--------------------------------
### Webhook Payload Format Example
Source: https://docs.twenty.com/developers/extend/webhooks
This is an example of the JSON payload sent with each webhook event. It includes the event type, the data of the affected record, and a timestamp.
```json
{
"event": "person.created",
"data": {
"id": "abc12345",
"firstName": "Alice",
"lastName": "Doe",
"email": "alice@example.com",
"createdAt": "2025-02-10T15:30:45Z",
"createdBy": "user_123"
},
"timestamp": "2025-02-10T15:30:50Z"
}
```