### 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" } ```