Overview
Once your app is built and tested locally, you have two paths for distributing it:- Deploy a tarball — upload your app directly to a specific Twenty server for internal or private use.
- Publish to npm — list your app in the Twenty marketplace for any workspace to discover and install.
Building your app
Run the build command to compile your app and generate a distribution-readymanifest.json:
.twenty/output/. Add --tarball to also produce a .tgz package for manual distribution or the deploy command.
Deploying to a server (tarball)
For apps you don’t want publicly available — proprietary tools, enterprise-only integrations, or experimental builds — you can deploy a tarball directly to a Twenty server.Prerequisites
Before deploying, you need a configured remote pointing to the target server. Remotes store the server URL and authentication credentials locally in~/.twenty/config.json.
Add a remote:
Deploying
Build and upload your app to the server in one step:Sharing a deployed app
Tarball apps are not listed in the public marketplace, so other workspaces on the same server won’t discover them by browsing. Once your workspace is on the Enterprise plan, you can share a deployed app like this:- Go to Settings > Applications > Registrations and open your app
- In the Distribution tab, click Copy share link
- Share this link with users on other workspaces — it takes them directly to the app’s install page
Version management
When updating an already deployed tarball app, the server requires theversion in package.json to be strictly higher (per semver ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you’ll see a VERSION_ALREADY_EXISTS error from the CLI.
To release an update:
- Bump the
versionfield in yourpackage.json(e.g.1.2.3→1.2.4,1.3.0, or2.0.0) - Run
yarn twenty deploy(oryarn twenty deploy --remote production) - Workspaces that have the app installed will see the upgrade available in their settings
Pre-release tags work as expected: bumping
1.0.0-rc.1 → 1.0.0-rc.2 is allowed, and a final release like 1.0.0 is correctly recognized as higher than 1.0.0-rc.5. The version in package.json must itself be a valid semver string.Automated CI/CD (scaffolded workflows)
Apps generated withcreate-twenty-app ship with two GitHub Actions workflows out of the box, under .github/workflows/. They are ready to run as soon as you push the repo to GitHub — no extra setup is needed for CI, and CD only requires a single secret.
CI — ci.yml
Runs integration tests on every push to main and every pull request.
What it does:
- Checks out your app’s source.
- Spawns an isolated Twenty test instance using the
twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@maincomposite action (the CI equivalent ofyarn twenty server start --test). - Enables Corepack, sets up Node.js from your
.nvmrc, and installs dependencies withyarn install --immutable. - Runs
yarn test, passingTWENTY_API_URLandTWENTY_API_KEYfrom the spawned instance so your tests can talk to a real server.
TWENTY_VERSION(env, defaults tolatest) — pin the Twenty server version used in CI by editing this inci.yml.- Concurrency is grouped by
github.refand cancels in-progress runs on new pushes.
CD — cd.yml
Deploys your app to a configured Twenty server on every push to main, and optionally from a pull request when the deploy label is applied.
What it does:
- Checks out the PR head (for labeled PRs) or the pushed commit.
- Runs
twentyhq/twenty/.github/actions/deploy-twenty-app@main— the CI equivalent ofyarn twenty deploy. - Runs
twentyhq/twenty/.github/actions/install-twenty-app@mainso the newly deployed version is installed into the target workspace.
| Setting | Where | Purpose |
|---|---|---|
TWENTY_DEPLOY_URL | env in cd.yml (defaults to http://localhost:3000) | The Twenty server to deploy to. Change this to your real server URL before first use. |
TWENTY_DEPLOY_API_KEY | GitHub repo Settings → Secrets and variables → Actions | API key with deploy permission on the target server. |
The default
TWENTY_DEPLOY_URL of http://localhost:3000 is a placeholder — it will not reach anything from a GitHub-hosted runner. Update it to your server’s public URL (or use a self-hosted runner with network access) before enabling CD.deploy label to a pull request. The if: guard in cd.yml will run the job for that PR using the PR’s head commit, letting you validate a change on the target server before merging.
Pinning the reusable actions
Both workflows reference reusable actions at@main, so action updates in the twentyhq/twenty repo are picked up automatically. If you want deterministic builds, replace @main with a commit SHA or release tag on each uses: line.
Publishing to npm
Publishing to npm makes your app discoverable in the Twenty marketplace. Any Twenty workspace can browse, install, and upgrade marketplace apps directly from the UI.Requirements
- An npm account
- The
twenty-appkeyword in yourpackage.jsonkeywordsarray (add it manually — it is not included by default in thecreate-twenty-apptemplate)
Marketplace metadata
ThedefineApplication() config supports optional fields that control how your app appears in the marketplace. Use logoUrl and screenshots to reference images from the public/ folder:
src/application-config.ts
author, category, aboutDescription, websiteUrl, termsUrl, etc.).
Publish
beta or next):
How marketplace discovery works
The Twenty server syncs its marketplace catalog from the npm registry every hour. You can trigger the sync immediately instead of waiting:defineApplication() config — fields like displayName, description, author, category, logoUrl, screenshots, aboutDescription, websiteUrl, and termsUrl.
If your app does not define an
aboutDescription in defineApplication(), the marketplace will automatically use your package’s README.md from npm as the about page content. This means you can maintain a single README for both npm and the Twenty marketplace. If you want a different description in the marketplace, explicitly set aboutDescription.CI publishing
Use this GitHub Actions workflow to publish automatically on every release (uses OIDC):yarn install, yarn twenty build, then npm publish from .twenty/output.
npm provenance is optional but recommended. Publishing with
--provenance adds a trust badge to your npm listing, letting users verify the package was built from a specific commit in a public CI pipeline. See the npm provenance docs for setup instructions.Installing apps
Once an app is published (npm) or deployed (tarball), workspaces can install it through the UI. Go to the Settings > Applications page in Twenty, where both marketplace and tarball-deployed apps can be browsed and installed. You can also install apps from the command line:The server enforces semver versioning on install, mirroring the rules on deploy:
- Installing the same version that is already installed in your workspace is rejected with an
APP_ALREADY_INSTALLEDerror. - Installing a lower version than the one currently installed is rejected with a
CANNOT_DOWNGRADE_APPLICATIONerror.
yarn twenty install.