--- title: Getting Started description: Create your first Twenty app in minutes. --- Apps are currently in alpha. The feature works but is still evolving. Apps let you extend Twenty with custom objects, fields, logic functions, AI skills, and UI components — all managed as code. ## Prerequisites Before you begin, make sure the following is installed on your machine: - **Node.js 24+** — [Download here](https://nodejs.org/) - **Yarn 4** — Comes with Node.js via Corepack. Enable it by running `corepack enable` - **Docker** — [Download here](https://www.docker.com/products/docker-desktop/). Required to run a local Twenty instance. Not needed if you already have a Twenty server running. ## Step 1: Scaffold your app Open a terminal and run: ```bash filename="Terminal" npx create-twenty-app@latest my-twenty-app ``` You will be prompted to enter a name and a description for your app. Press **Enter** to accept the defaults. This creates a new folder called `my-twenty-app` with everything you need. The scaffolder supports these flags: - `--minimal` — scaffold only the essential files, no examples (default) - `--exhaustive` — scaffold all example entities - `--name ` — set the app name (skips the prompt) - `--display-name ` — set the display name (skips the prompt) - `--description ` — set the description (skips the prompt) - `--skip-local-instance` — skip the local server setup prompt ## Step 2: Set up a local Twenty instance The scaffolder will ask: > **Would you like to set up a local Twenty instance?** - **Type `yes`** (recommended) — This pulls the `twenty-app-dev` Docker image and starts a local Twenty server on port `2020`. Make sure Docker is running before you continue. - **Type `no`** — Choose this if you already have a Twenty server running locally.
Should start local instance?
## Step 3: Sign in to your workspace Next, a browser window will open with the Twenty login page. Sign in with the pre-seeded demo account: - **Email:** `tim@apple.dev` - **Password:** `tim@apple.dev`
Twenty login screen
## Step 4: Authorize the app After you sign in, you will see an authorization screen. This lets your app interact with your workspace. Click **Authorize** to continue.
Twenty CLI authorization screen
Once authorized, your terminal will confirm that everything is set up.
App scaffolded successfully
## Step 5: Start developing Go into your new app folder and start the development server: ```bash filename="Terminal" cd my-twenty-app yarn twenty dev ``` This watches your source files, rebuilds on every change, and syncs your app to the local Twenty server automatically. You should see a live status panel in your terminal. For more detailed output (build logs, sync requests, error traces), use the `--verbose` flag: ```bash filename="Terminal" yarn twenty dev --verbose ``` Dev mode is only available on Twenty instances running in development (`NODE_ENV=development`). Production instances reject dev sync requests. Use `yarn twenty deploy` to deploy to production servers — see [Publishing Apps](/developers/extend/apps/publishing) for details.
Dev mode terminal output
## Step 6: See your app in Twenty Open [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in your browser. Navigate to **Settings > Apps** and select the **Developer** tab. You should see your app listed under **Your Apps**:
Your Apps list showing My twenty app
Click on **My twenty app** to open its **application registration**. A registration is a server-level record that describes your app — its name, unique identifier, OAuth credentials, and source (local, npm, or tarball). It lives on the server, not inside any specific workspace. When you install an app into a workspace, Twenty creates a workspace-scoped **application** that points back to this registration. One registration can be installed across multiple workspaces on the same server.
Application registration details
Click **View installed app** to see the installed app. The **About** tab shows the current version and management options:
Installed app — About tab
Switch to the **Content** tab to see everything your app provides — objects, fields, logic functions, and agents:
Installed app — Content tab
You are all set! Edit any file in `src/` and the changes will be picked up automatically. Head over to [Building Apps](/developers/extend/apps/building) for a detailed guide on creating objects, logic functions, front components, skills, and more. --- ## Project structure The scaffolder generates the following file structure (shown with `--exhaustive` mode, which includes examples for every entity type): ```text filename="my-twenty-app/" my-twenty-app/ package.json yarn.lock .gitignore .nvmrc .yarnrc.yml .yarn/ install-state.gz .oxlintrc.json tsconfig.json tsconfig.spec.json # TypeScript config for tests vitest.config.ts # Vitest test runner configuration LLMS.md README.md .github/ └── workflows/ └── ci.yml # GitHub Actions CI workflow public/ # Public assets (images, fonts, etc.) src/ ├── application-config.ts # Required — main application configuration ├── __tests__/ │ ├── setup-test.ts # Test setup (server health check, config) │ └── app-install.integration-test.ts # Example integration test ├── roles/ │ └── default-role.ts # Default role for logic functions ├── objects/ │ └── example-object.ts # Example custom object definition ├── fields/ │ └── example-field.ts # Example standalone field definition ├── logic-functions/ │ ├── hello-world.ts # Example logic function │ ├── create-hello-world-company.ts # Example logic function using CoreApiClient │ ├── pre-install.ts # Runs before installation │ └── post-install.ts # Runs after installation ├── front-components/ │ └── hello-world.tsx # Example front component ├── page-layouts/ │ └── example-record-page-layout.ts # Example page layout with front component ├── views/ │ └── example-view.ts # Example saved view definition ├── navigation-menu-items/ │ └── example-navigation-menu-item.ts # Example sidebar navigation link ├── skills/ │ └── example-skill.ts # Example AI agent skill definition └── agents/ └── example-agent.ts # Example AI agent definition ``` By default (`--minimal`), only the core files are created: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`. Use `--exhaustive` to include all the example files shown above. ### Key files | File / Folder | Purpose | |---|---| | `package.json` | Declares your app name, version, and dependencies. Includes a `twenty` script so you can run `yarn twenty help` to see all commands. | | `src/application-config.ts` | **Required.** The main configuration file for your app. | | `src/roles/` | Defines roles that control what your logic functions can access. | | `src/logic-functions/` | Server-side functions triggered by routes, cron schedules, or database events. | | `src/front-components/` | React components that render inside Twenty's UI. | | `src/objects/` | Custom object definitions to extend your data model. | | `src/fields/` | Custom fields added to existing objects. | | `src/views/` | Saved view configurations. | | `src/navigation-menu-items/` | Custom links in the sidebar navigation. | | `src/skills/` | Skills that extend Twenty's AI agents. | | `src/agents/` | AI agents with custom prompts. | | `src/page-layouts/` | Custom page layouts for record views. | | `src/__tests__/` | Integration tests (setup + example test). | | `public/` | Static assets (images, fonts) served with your app. | ## Managing remotes A **remote** is a Twenty server that your app connects to. During setup, the scaffolder creates one for you automatically. You can add more remotes or switch between them at any time. ```bash filename="Terminal" # Add a new remote (opens a browser for OAuth login) yarn twenty remote add # Connect to a local Twenty server (auto-detects port 2020 or 3000) yarn twenty remote add --local # Add a remote non-interactively (useful for CI) yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote # List all configured remotes yarn twenty remote list # Switch the active remote yarn twenty remote switch ``` Your credentials are stored in `~/.twenty/config.json`. ## Local development server (`yarn twenty server`) The CLI can manage a local Twenty server running in Docker. This is the same server started automatically when you scaffold an app with `create-twenty-app`, but you can also manage it manually. ### Starting the server ```bash filename="Terminal" yarn twenty server start ``` This pulls the `twentycrm/twenty-app-dev:latest` Docker image (if not already present), creates a container named `twenty-app-dev`, and starts it on port **2020**. The CLI waits until the server passes its health check before returning. Two Docker volumes are created to persist data between restarts: - `twenty-app-dev-data` — PostgreSQL database - `twenty-app-dev-storage` — file storage If port 2020 is already in use, you can start on a different port: ```bash filename="Terminal" yarn twenty server start --port 3030 ``` The CLI automatically configures the container's internal `NODE_PORT` and `SERVER_URL` to match the chosen port, so logic functions, OAuth, and all other internal networking work correctly. Once started, the server is automatically registered as the `local` remote in your CLI config. ### Checking server status ```bash filename="Terminal" yarn twenty server status ``` Displays whether the server is running, its URL, and the default login credentials (`tim@apple.dev` / `tim@apple.dev`). ### Viewing server logs ```bash filename="Terminal" yarn twenty server logs ``` Streams the container logs. Use `--lines` to control how many recent lines to show: ```bash filename="Terminal" yarn twenty server logs --lines 100 ``` ### Stopping the server ```bash filename="Terminal" yarn twenty server stop ``` Stops the container. Your data is preserved in the Docker volumes — the next `start` picks up where you left off. ### Resetting the server ```bash filename="Terminal" yarn twenty server reset ``` Removes the container **and** deletes both Docker volumes, wiping all data. The next `start` creates a fresh instance. The server requires **Docker** to be running. If you see a "Docker not running" error, make sure Docker Desktop (or the Docker daemon) is started. ### Command reference | Command | Description | |---------|-------------| | `yarn twenty server start` | Start the local server (pulls image if needed) | | `yarn twenty server start --port 3030` | Start on a custom port | | `yarn twenty server stop` | Stop the server (preserves data) | | `yarn twenty server status` | Show server status, URL, and credentials | | `yarn twenty server logs` | Stream server logs | | `yarn twenty server logs --lines 100` | Show the last 100 log lines | | `yarn twenty server reset` | Delete all data and start fresh | ## CI with GitHub Actions The scaffolder generates a ready-to-use GitHub Actions workflow at `.github/workflows/ci.yml`. It runs your integration tests automatically on every push to `main` and on pull requests. The workflow: 1. Checks out your code 2. Spins up a temporary Twenty server using the `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` action 3. Installs dependencies with `yarn install --immutable` 4. Runs `yarn test` with `TWENTY_API_URL` and `TWENTY_API_KEY` injected from the action outputs ```yaml .github/workflows/ci.yml name: CI on: push: branches: - main pull_request: {} env: TWENTY_VERSION: latest jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Spawn Twenty instance id: twenty uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main with: twenty-version: ${{ env.TWENTY_VERSION }} github-token: ${{ secrets.GITHUB_TOKEN }} - name: Enable Corepack run: corepack enable - name: Setup Node.js uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: 'yarn' - name: Install dependencies run: yarn install --immutable - name: Run integration tests run: yarn test env: TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }} TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }} ``` You don't need to configure any secrets — the `spawn-twenty-docker-image` action starts an ephemeral Twenty server directly in the runner and outputs the connection details. The `GITHUB_TOKEN` secret is provided automatically by GitHub. To pin a specific Twenty version instead of `latest`, change the `TWENTY_VERSION` environment variable at the top of the workflow. ## Manual setup (without the scaffolder) If you prefer to set things up yourself instead of using `create-twenty-app`, you can do it in two steps. **1. Add `twenty-sdk` and `twenty-client-sdk` as dependencies:** ```bash filename="Terminal" yarn add twenty-sdk twenty-client-sdk ``` **2. Add a `twenty` script to your `package.json`:** ```json filename="package.json" { "scripts": { "twenty": "twenty" } } ``` You can now run `yarn twenty dev`, `yarn twenty help`, and all other commands. Do not install `twenty-sdk` globally. Always use it as a local project dependency so that each project can pin its own version. ## Troubleshooting If you run into issues: - Make sure **Docker is running** before starting the scaffolder with a local instance. - Make sure you are using **Node.js 24+** (`node -v` to check). - Make sure **Corepack is enabled** (`corepack enable`) so Yarn 4 is available. - Try deleting `node_modules` and running `yarn install` again if dependencies seem broken. Still stuck? Ask for help on the [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322).