012d819557
## Summary Consolidates three separate PRs (#18260, #18261, #18262) into a single unified branch with all review feedback addressed: ### New features - **ApplicationRegistration entity** — server-level registration for OAuth apps with encrypted server variables - **OAuth 2.0 server** — authorization code, client credentials, refresh token grants with PKCE support - **OAuth discovery endpoint** — `.well-known/oauth-authorization-server` metadata - **Frontend UI** — app registration details page with credential management, redirect URI editing, and server variable configuration - **CLI integration** — `twenty dev` auto-registers apps and stores OAuth credentials locally - **Authorize consent screen** — OAuth consent page at `/authorize` showing requested scopes ### Review feedback addressed **Renames (PR #18260):** - `appRegistration` → `applicationRegistration` (entity, tables, files, imports, GraphQL types) - `appRegistrationVariable` → `applicationRegistrationVariable` - `clientId` → `oAuthClientId`, `clientSecretHash` → `oAuthClientSecretHash`, `redirectUris` → `oAuthRedirectUris`, `scopes` → `oAuthScopes` **Security fixes (PR #18261):** - Fixed redirect URI validation bypass when `oAuthRedirectUris` is an empty array - Fixed workspace isolation in `clientCredentialsGrant` — now uses `find()` with explicit handling for multiple installations - Added error logging in refresh token `catch` block instead of silently swallowing **Code quality (PR #18262):** - Split `VersionDistributionEntry` into its own file (one export per file) - Split GraphQL queries and mutations into individual files with a shared fragment - Removed unused `OAuth` entry from `AuthProviderEnum` - Added loading state to `handleRotateSecret` - Removed 27 narration-style comments from test files - Added proper guards (`PublicEndpointGuard`, `NoPermissionGuard`) to controllers and resolvers ## Test plan - [ ] Verify `twenty dev` registers an app and stores OAuth credentials - [ ] Test OAuth authorization code flow end-to-end (authorize → token → API call) - [ ] Test client credentials grant - [ ] Verify redirect URI validation rejects requests when no URIs are registered - [ ] Verify app registration detail page renders correctly - [ ] Test secret rotation with loading state - [ ] Verify server variable editing and saving - [ ] Run `npx nx database:reset twenty-server` to validate migration Closes #18260, #18261, #18262 Made with [Cursor](https://cursor.com) --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Create Twenty App is the official scaffolding CLI for building apps on top of Twenty CRM. It sets up a ready‑to‑run project that works seamlessly with the twenty-sdk.
- Zero‑config project bootstrap
- Preconfigured scripts for auth, dev mode (watch & sync), uninstall, and function management
- Strong TypeScript support and typed client generation
Documentation
See Twenty application documentation https://docs.twenty.com/developers/extend/capabilities/apps
Prerequisites
- Node.js 24+ (recommended) and Yarn 4
- A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)
Quick start
npx create-twenty-app@latest my-twenty-app
cd my-twenty-app
# Get help and list all available commands
yarn twenty help
# Authenticate using your API key (you'll be prompted)
yarn twenty auth:login
# Add a new entity to your application (guided)
yarn twenty entity:add
# Start dev mode: watches, builds, and syncs local changes to your workspace
# (also auto-generates typed API clients — CoreApiClient and MetadataApiClient — in node_modules/twenty-sdk/generated)
yarn twenty app:dev
# Watch your application's function logs
yarn twenty function:logs
# Execute a function with a JSON payload
yarn twenty function:execute -n my-function -p '{"key": "value"}'
# Execute the pre-install function
yarn twenty function:execute --preInstall
# Execute the post-install function
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
yarn twenty app:uninstall
Scaffolding modes
Control which example files are included when creating a new app:
| Flag | Behavior |
|---|---|
-e, --exhaustive |
(default) Creates all example files without prompting |
-m, --minimal |
Creates only core files (application-config.ts and default-role.ts) |
-i, --interactive |
Prompts you to select which examples to include |
# Default: all examples included
npx create-twenty-app@latest my-app
# Minimal: only core files
npx create-twenty-app@latest my-app -m
# Interactive: choose which examples to include
npx create-twenty-app@latest my-app -i
In interactive mode, you can pick from:
- Example object — a custom CRM object definition (
objects/example-object.ts) - Example field — a custom field on the example object (
fields/example-field.ts) - Example logic function — a server-side handler with HTTP trigger (
logic-functions/hello-world.ts) - Example front component — a React UI component (
front-components/hello-world.tsx) - Example view — a saved view for the example object (
views/example-view.ts) - Example navigation menu item — a sidebar link (
navigation-menu-items/example-navigation-menu-item.ts) - Example skill — an AI agent skill definition (
skills/example-skill.ts)
What gets scaffolded
Core files (always created):
application-config.ts— Application metadata configurationroles/default-role.ts— Default role for logic functionslogic-functions/pre-install.ts— Pre-install logic function (runs before app installation)logic-functions/post-install.ts— Post-install logic function (runs after app installation)- TypeScript configuration, ESLint, package.json, .gitignore
- A prewired
twentyscript that delegates to thetwentyCLI from twenty-sdk
Example files (controlled by scaffolding mode):
objects/example-object.ts— Example custom object with a text fieldfields/example-field.ts— Example standalone field extending the example objectlogic-functions/hello-world.ts— Example logic function with HTTP triggerfront-components/hello-world.tsx— Example front componentviews/example-view.ts— Example saved view for the example objectnavigation-menu-items/example-navigation-menu-item.ts— Example sidebar navigation linkskills/example-skill.ts— Example AI agent skill definition
Next steps
- Run
yarn twenty helpto see all available commands. - Use
yarn twenty auth:loginto authenticate with your Twenty workspace. - Explore the generated project and add your first entity with
yarn twenty entity:add(logic functions, front components, objects, roles, views, navigation menu items, skills). - Use
yarn twenty app:devwhile you iterate — it watches, builds, and syncs changes to your workspace in real time. - Two typed API clients are auto‑generated by
yarn twenty app:devand stored innode_modules/twenty-sdk/generated:CoreApiClient(for workspace data via/graphql) andMetadataApiClient(for workspace configuration and file uploads via/metadata).
Publish your application
Applications are currently stored in twenty/packages/twenty-apps.
You can share your application with all Twenty users:
# pull the Twenty project
git clone https://github.com/twentyhq/twenty.git
cd twenty
# create a new branch
git checkout -b feature/my-awesome-app
- Copy your app folder into
twenty/packages/twenty-apps. - Commit your changes and open a pull request on https://github.com/twentyhq/twenty
git commit -m "Add new application"
git push
Our team reviews contributions for quality, security, and reusability before merging.
Troubleshooting
- Auth prompts not appearing: run
yarn twenty auth:loginagain and verify the API key permissions. - Types not generated: ensure
yarn twenty app:devis running — it auto‑generates the typed client.