From 8985dfbc5d5ffc44f2d8917c7a3288d28429e061 Mon Sep 17 00:00:00 2001 From: martmull Date: Mon, 30 Mar 2026 17:03:23 +0200 Subject: [PATCH] Improve apps (#19120) fixes https://discord.com/channels/1130383047699738754/1488094970241089586 --- packages/create-twenty-app/README.md | 2 +- .../src/create-app.command.ts | 66 +++++++++++++++---- .../developers/extend/apps/building.mdx | 2 +- .../extend/apps/getting-started.mdx | 31 +++------ .../developers/extend/apps/publishing.mdx | 4 ++ .../developers/extend/capabilities/apps.mdx | 2 +- .../SettingsAvailableApplicationDetails.tsx | 16 +++++ packages/twenty-sdk/README.md | 2 +- packages/twenty-sdk/src/cli/cli.ts | 3 + .../twenty-sdk/src/cli/commands/remote.ts | 2 +- .../twenty-sdk/src/cli/commands/server.ts | 4 -- .../twenty-sdk/src/cli/operations/index.ts | 1 + .../src/cli/operations/server-start.ts | 4 ++ .../src/cli/utilities/api/api-client.ts | 2 +- .../steps/check-server-orchestrator-step.ts | 17 ++++- .../marketplace-catalog-index.constant.ts | 29 -------- ...rketplace-curated-applications.constant.ts | 4 ++ .../marketplace-catalog-sync.service.ts | 59 ++++++++--------- .../marketplace.service.ts | 33 ++++++++++ .../display/icon/components/TablerIcons.ts | 1 + packages/twenty-ui/src/display/index.ts | 1 + 21 files changed, 181 insertions(+), 104 deletions(-) delete mode 100644 packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-catalog-index.constant.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-curated-applications.constant.ts diff --git a/packages/create-twenty-app/README.md b/packages/create-twenty-app/README.md index a87160a7639..e0b063da465 100644 --- a/packages/create-twenty-app/README.md +++ b/packages/create-twenty-app/README.md @@ -110,7 +110,7 @@ npx create-twenty-app@latest my-app -m ## Local server -The scaffolder can start a local Twenty dev server for you (all-in-one Docker image with PostgreSQL, Redis, server, and worker). You can also manage it manually: +The scaffolder can start a local Twenty dev server for you (all-in-one Docker image with PostgreSQL, Redis, server, and worker on port 2020). These commands only apply to the Docker-based dev server — they do not manage a Twenty instance started from source (e.g. `npx nx start twenty-server` on port 3000). You can also manage it manually: ```bash yarn twenty server start # Start (pulls image if needed) diff --git a/packages/create-twenty-app/src/create-app.command.ts b/packages/create-twenty-app/src/create-app.command.ts index 5ec77be3af5..5f46301c311 100644 --- a/packages/create-twenty-app/src/create-app.command.ts +++ b/packages/create-twenty-app/src/create-app.command.ts @@ -10,6 +10,7 @@ import * as path from 'path'; import { basename } from 'path'; import { authLoginOAuth, + detectLocalServer, serverStart, type ServerStartResult, } from 'twenty-sdk/cli'; @@ -62,15 +63,19 @@ export class CreateAppCommand { let serverResult: ServerStartResult | undefined; if (!options.skipLocalInstance) { - const startResult = await serverStart({ - onProgress: (message: string) => console.log(chalk.gray(message)), - }); + const shouldStartServer = await this.shouldStartServer(); - if (startResult.success) { - serverResult = startResult.data; - await this.connectToLocal(serverResult.url); - } else { - console.log(chalk.yellow(`\n${startResult.error.message}`)); + if (shouldStartServer) { + const startResult = await serverStart({ + onProgress: (message: string) => console.log(chalk.gray(message)), + }); + + if (startResult.success) { + serverResult = startResult.data; + await this.promptConnectToLocal(serverResult.url); + } else { + console.log(chalk.yellow(`\n${startResult.error.message}`)); + } } } @@ -201,7 +206,46 @@ export class CreateAppCommand { ); } - private async connectToLocal(serverUrl: string): Promise { + private async shouldStartServer(): Promise { + const existingServerUrl = await detectLocalServer(); + + if (existingServerUrl) { + return true; + } + + const { startDocker } = await inquirer.prompt([ + { + type: 'confirm', + name: 'startDocker', + message: + 'No running Twenty instance found. Would you like to start one using Docker?', + default: true, + }, + ]); + + return startDocker; + } + + private async promptConnectToLocal(serverUrl: string): Promise { + const { shouldAuthenticate } = await inquirer.prompt([ + { + type: 'confirm', + name: 'shouldAuthenticate', + message: `Would you like to authenticate to the local Twenty instance (${serverUrl})?`, + default: true, + }, + ]); + + if (!shouldAuthenticate) { + console.log( + chalk.gray( + 'Authentication skipped. Run `yarn twenty remote add` manually.', + ), + ); + + return; + } + try { const result = await authLoginOAuth({ apiUrl: serverUrl, @@ -211,14 +255,14 @@ export class CreateAppCommand { if (!result.success) { console.log( chalk.yellow( - 'Authentication skipped. Run `yarn twenty remote add` manually.', + 'Authentication failed. Run `yarn twenty remote add` manually.', ), ); } } catch { console.log( chalk.yellow( - 'Authentication skipped. Run `yarn twenty remote add` manually.', + 'Authentication failed. Run `yarn twenty remote add` manually.', ), ); } diff --git a/packages/twenty-docs/developers/extend/apps/building.mdx b/packages/twenty-docs/developers/extend/apps/building.mdx index fd021470ce7..37bfa854cb9 100644 --- a/packages/twenty-docs/developers/extend/apps/building.mdx +++ b/packages/twenty-docs/developers/extend/apps/building.mdx @@ -362,7 +362,7 @@ If you plan to [publish your app](/developers/extend/apps/publishing), these opt | `category` | App category for marketplace filtering | | `logoUrl` | Path to your app logo (relative to `./assets/`) | | `screenshots` | Array of screenshot paths (relative to `./assets/`) | -| `aboutDescription` | Longer markdown description for the "About" tab | +| `aboutDescription` | Longer markdown description for the "About" tab. If omitted, the marketplace uses the package's `README.md` from npm | | `websiteUrl` | Link to your website | | `termsUrl` | Link to terms of service | | `emailSupport` | Support email address | diff --git a/packages/twenty-docs/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/developers/extend/apps/getting-started.mdx index 46d71760a51..ac6152bff62 100644 --- a/packages/twenty-docs/developers/extend/apps/getting-started.mdx +++ b/packages/twenty-docs/developers/extend/apps/getting-started.mdx @@ -9,17 +9,18 @@ Apps are currently in alpha testing. The feature is functional but still evolvin Apps let you extend Twenty with custom objects, fields, logic functions, AI skills, and UI components — all managed as code. -**What you can do today:** -- Define custom objects and fields as code (managed data model) -- Build logic functions with custom triggers (HTTP routes, cron, database events) -- Define skills for AI agents -- Build front components that render inside Twenty's UI -- Deploy the same app across multiple workspaces +**What you can build:** +- Custom objects, fields, views, and navigation items to shape your data model +- Logic functions triggered by HTTP routes, cron schedules, or database events +- Front components that render directly inside Twenty's UI +- Skills that extend Twenty's AI agents +- Deploy an app across multiple workspaces ## Prerequisites -- Node.js 24+ and Yarn 4 -- Docker (for the local Twenty dev server) +- Node.js 24+ +- Yarn 4 +- Docker (or a running local Twenty instance) ## Getting Started @@ -28,21 +29,9 @@ Create a new app using the official scaffolder, then authenticate and start deve ```bash filename="Terminal" # Scaffold a new app (includes all examples by default) npx create-twenty-app@latest my-twenty-app -cd my-twenty-app - -# Start dev mode: automatically syncs local changes to your workspace -yarn twenty dev ``` -The scaffolder supports two modes for controlling which example files are included: - -```bash filename="Terminal" -# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill, agent) -npx create-twenty-app@latest my-app - -# Minimal: only core files (application-config.ts and default-role.ts) -npx create-twenty-app@latest my-app --minimal -``` +> Use `--minimal` option to scaffold a minimal installation From here you can: diff --git a/packages/twenty-docs/developers/extend/apps/publishing.mdx b/packages/twenty-docs/developers/extend/apps/publishing.mdx index fa76d658ba0..a7e1f42c312 100644 --- a/packages/twenty-docs/developers/extend/apps/publishing.mdx +++ b/packages/twenty-docs/developers/extend/apps/publishing.mdx @@ -102,6 +102,10 @@ yarn twenty catalog-sync -r production The metadata shown in the marketplace comes from your `defineApplication()` call in your app source code — 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 The scaffolded project includes a GitHub Actions workflow that publishes on every release: diff --git a/packages/twenty-docs/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/developers/extend/capabilities/apps.mdx index f027d9e6a75..3b6de5319a0 100644 --- a/packages/twenty-docs/developers/extend/capabilities/apps.mdx +++ b/packages/twenty-docs/developers/extend/capabilities/apps.mdx @@ -37,7 +37,7 @@ yarn twenty dev ### Local Server Management -The SDK includes commands to manage a local Twenty dev server (all-in-one Docker image with PostgreSQL, Redis, server, and worker): +The SDK includes commands to manage a local Twenty dev server (all-in-one Docker image with PostgreSQL, Redis, server, and worker on port 2020). These commands only apply to the Docker-based dev server — they do not manage a Twenty instance started from source (e.g. `npx nx start twenty-server` on port 3000): ```bash filename="Terminal" # Start the local server (pulls the image if needed) diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx index 49dba49382d..4700e4b0b56 100644 --- a/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx +++ b/packages/twenty-front/src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx @@ -17,6 +17,7 @@ import { IconAlertTriangle, IconBook, IconBox, + IconBrandNpm, IconCheck, IconCommand, IconDownload, @@ -221,6 +222,11 @@ export const SettingsAvailableApplicationDetails = () => { const sourceType = detail?.sourceType; const isNpmApp = sourceType === ApplicationRegistrationSourceType.NPM; const registrationId = detail?.id; + const sourcePackage = detail?.sourcePackage; + const sourcePackageUrl = + isNpmApp && detail?.sourcePackage + ? `https://www.npmjs.com/package/${detail.sourcePackage}` + : undefined; const isUnlisted = isDefined(detail) && !detail.isListed; const installedApp = applicationData?.findOneApplication; @@ -519,6 +525,16 @@ export const SettingsAvailableApplicationDetails = () => { {t`Report and issue`} )} + {sourcePackageUrl && ( + + + {t`Npm package`} + + )} )} diff --git a/packages/twenty-sdk/README.md b/packages/twenty-sdk/README.md index 90ea6f032ed..8fe193cc6e6 100644 --- a/packages/twenty-sdk/README.md +++ b/packages/twenty-sdk/README.md @@ -81,7 +81,7 @@ In a project created with `create-twenty-app` (recommended), use `yarn twenty + error instanceof Error && error.name === 'ExitPromptError'; + try { program.parse(); } catch (error) { diff --git a/packages/twenty-sdk/src/cli/commands/remote.ts b/packages/twenty-sdk/src/cli/commands/remote.ts index 52fd47962d6..26468289826 100644 --- a/packages/twenty-sdk/src/cli/commands/remote.ts +++ b/packages/twenty-sdk/src/cli/commands/remote.ts @@ -108,7 +108,7 @@ export const registerRemoteCommands = (program: Command): void => { if (!detectedUrl) { console.error( chalk.red( - 'No local Twenty server found on ports 2020 or 3000.\n' + + 'No local Twenty server found.\n' + 'Start one with: yarn twenty server start', ), ); diff --git a/packages/twenty-sdk/src/cli/commands/server.ts b/packages/twenty-sdk/src/cli/commands/server.ts index 6d8bcc19caa..c95424a0789 100644 --- a/packages/twenty-sdk/src/cli/commands/server.ts +++ b/packages/twenty-sdk/src/cli/commands/server.ts @@ -37,10 +37,6 @@ export const registerServerCommands = (program: Command): void => { console.error(chalk.red(result.error.message)); process.exit(1); } - - console.log( - chalk.green(`\nLocal remote configured → ${result.data.url}`), - ); }); server diff --git a/packages/twenty-sdk/src/cli/operations/index.ts b/packages/twenty-sdk/src/cli/operations/index.ts index 1c123e2390f..5e0fa60cd41 100644 --- a/packages/twenty-sdk/src/cli/operations/index.ts +++ b/packages/twenty-sdk/src/cli/operations/index.ts @@ -25,6 +25,7 @@ export type { FunctionExecuteOptions } from './execute'; // Server export { serverStart } from './server-start'; export type { ServerStartOptions, ServerStartResult } from './server-start'; +export { detectLocalServer } from '@/cli/utilities/server/detect-local-server'; // Shared types and error codes export { diff --git a/packages/twenty-sdk/src/cli/operations/server-start.ts b/packages/twenty-sdk/src/cli/operations/server-start.ts index bf2d4adfbc4..9c96cb57248 100644 --- a/packages/twenty-sdk/src/cli/operations/server-start.ts +++ b/packages/twenty-sdk/src/cli/operations/server-start.ts @@ -126,6 +126,8 @@ const innerServerStart = async ( } else { onProgress?.('Starting Twenty container...'); + const serverUrl = `http://localhost:${port}`; + const runResult = spawnSync( 'docker', [ @@ -133,6 +135,8 @@ const innerServerStart = async ( '-d', '--name', CONTAINER_NAME, + '-e', + `SERVER_URL=${serverUrl}`, '-p', `${port}:3000`, '-v', diff --git a/packages/twenty-sdk/src/cli/utilities/api/api-client.ts b/packages/twenty-sdk/src/cli/utilities/api/api-client.ts index 06cd6790925..77d3581f622 100644 --- a/packages/twenty-sdk/src/cli/utilities/api/api-client.ts +++ b/packages/twenty-sdk/src/cli/utilities/api/api-client.ts @@ -51,7 +51,7 @@ export class ApiClient { if (error.response?.status === 401) { console.error( chalk.red( - 'Authentication failed. Run `twenty remote add` to authenticate.', + 'Authentication failed. Run `yarn twenty remote add` to authenticate.', ), ); } else if (error.response?.status === 403) { diff --git a/packages/twenty-sdk/src/cli/utilities/dev/orchestrator/steps/check-server-orchestrator-step.ts b/packages/twenty-sdk/src/cli/utilities/dev/orchestrator/steps/check-server-orchestrator-step.ts index 1f13acf1250..2ff6a63674c 100644 --- a/packages/twenty-sdk/src/cli/utilities/dev/orchestrator/steps/check-server-orchestrator-step.ts +++ b/packages/twenty-sdk/src/cli/utilities/dev/orchestrator/steps/check-server-orchestrator-step.ts @@ -1,5 +1,7 @@ import { type ApiService } from '@/cli/utilities/api/api-service'; +import { ConfigService } from '@/cli/utilities/config/config-service'; import { type OrchestratorState } from '@/cli/utilities/dev/orchestrator/dev-mode-orchestrator-state'; +import { detectLocalServer } from '@/cli/utilities/server/detect-local-server'; export type CheckServerOrchestratorStepOutput = { isReady: boolean; @@ -25,11 +27,24 @@ export class CheckServerOrchestratorStep { this.notify = notify; } + private hasRetried = false; + async execute(): Promise { const step = this.state.steps.checkServer; const validateAuth = await this.apiService.validateAuth(); if (!validateAuth.serverUp) { + const detectedUrl = await detectLocalServer(); + + if (detectedUrl && !this.hasRetried) { + this.hasRetried = true; + const configService = new ConfigService(); + + await configService.setConfig({ apiUrl: detectedUrl }); + + return this.execute(); + } + if (!step.output.errorLogged) { step.output = { isReady: false, errorLogged: true }; step.status = 'error'; @@ -58,7 +73,7 @@ export class CheckServerOrchestratorStep { this.state.applyStepEvents([ { message: - 'Authentication failed. Run `twenty remote add ` to authenticate.', + 'Authentication failed. Run `yarn twenty remote add` to authenticate.', status: 'error', }, ]); diff --git a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-catalog-index.constant.ts b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-catalog-index.constant.ts deleted file mode 100644 index 24f425cc981..00000000000 --- a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-catalog-index.constant.ts +++ /dev/null @@ -1,29 +0,0 @@ -export type CuratedAppEntry = { - universalIdentifier: string; - sourcePackage: string; - isFeatured: boolean; - name: string; - description: string; - author: string; - logoUrl?: string; - websiteUrl?: string; - termsUrl?: string; - latestAvailableVersion?: string; -}; - -const MOCK_LOGO_SVG = ``; -const ENCODED_MOCK_LOGO = `data:image/svg+xml,${encodeURIComponent(MOCK_LOGO_SVG)}`; - -export const MARKETPLACE_CATALOG_INDEX: CuratedAppEntry[] = [ - { - universalIdentifier: 'a1b2c3d4-0000-0000-0000-000000000001', - sourcePackage: '@twentyhq/app-data-enrichment', - isFeatured: true, - name: 'Data Enrichment', - description: 'Enrich your data easily. Choose your provider.', - author: 'Twenty', - logoUrl: ENCODED_MOCK_LOGO, - websiteUrl: 'https://twenty.com', - latestAvailableVersion: '1.0.0', - }, -]; diff --git a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-curated-applications.constant.ts b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-curated-applications.constant.ts new file mode 100644 index 00000000000..7f4a34b34a5 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/constants/marketplace-curated-applications.constant.ts @@ -0,0 +1,4 @@ +export const MARKETPLACE_CURATED_APPLICATIONS: { + universalIdentifier: string; + position?: number; +}[] = []; diff --git a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace-catalog-sync.service.ts b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace-catalog-sync.service.ts index 386fbdff5b6..fa19337c8b1 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace-catalog-sync.service.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace-catalog-sync.service.ts @@ -2,11 +2,11 @@ import { Injectable, Logger } from '@nestjs/common'; import { ApplicationRegistrationService } from 'src/engine/core-modules/application/application-registration/application-registration.service'; import { ApplicationRegistrationSourceType } from 'src/engine/core-modules/application/application-registration/enums/application-registration-source-type.enum'; -import { MARKETPLACE_CATALOG_INDEX } from 'src/engine/core-modules/application/application-marketplace/constants/marketplace-catalog-index.constant'; import { MarketplaceService } from 'src/engine/core-modules/application/application-marketplace/marketplace.service'; import { buildRegistryCdnUrl } from 'src/engine/core-modules/application/application-marketplace/utils/build-registry-cdn-url.util'; import { resolveManifestAssetUrls } from 'src/engine/core-modules/application/application-marketplace/utils/resolve-manifest-asset-urls.util'; import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { MARKETPLACE_CURATED_APPLICATIONS } from 'src/engine/core-modules/application/application-marketplace/constants/marketplace-curated-applications.constant'; @Injectable() export class MarketplaceCatalogSyncService { @@ -19,59 +19,54 @@ export class MarketplaceCatalogSyncService { ) {} async syncCatalog(): Promise { - await this.syncCuratedApps(); await this.syncRegistryApps(); this.logger.log('Marketplace catalog sync completed'); } - private async syncCuratedApps(): Promise { - for (const entry of MARKETPLACE_CATALOG_INDEX) { - try { - await this.applicationRegistrationService.upsertFromCatalog({ - universalIdentifier: entry.universalIdentifier, - name: entry.name, - sourceType: ApplicationRegistrationSourceType.NPM, - sourcePackage: entry.sourcePackage, - latestAvailableVersion: entry.latestAvailableVersion ?? null, - isListed: true, - isFeatured: entry.isFeatured, - manifest: null, - ownerWorkspaceId: null, - }); - } catch (error) { - this.logger.error( - `Failed to sync curated app "${entry.name}": ${error instanceof Error ? error.message : String(error)}`, - ); - } - } - } - private async syncRegistryApps(): Promise { const packages = await this.marketplaceService.fetchAppsFromRegistry(); const curatedIdentifiers = new Set( - MARKETPLACE_CATALOG_INDEX.map((entry) => entry.universalIdentifier), + MARKETPLACE_CURATED_APPLICATIONS.map( + (entry) => entry.universalIdentifier, + ), ); for (const pkg of packages) { try { - const manifest = + const fetchedManifest = await this.marketplaceService.fetchManifestFromRegistryCdn( pkg.name, pkg.version, ); - if (!manifest) { + if (!fetchedManifest) { this.logger.debug(`Skipping ${pkg.name}: no manifest found on CDN`); continue; } - const universalIdentifier = manifest.application.universalIdentifier; + const universalIdentifier = + fetchedManifest.application.universalIdentifier; - if (curatedIdentifiers.has(universalIdentifier)) { - continue; - } + const isFeatured = curatedIdentifiers.has(universalIdentifier); + + const aboutDescription = + fetchedManifest.application.aboutDescription ?? + (await this.marketplaceService.fetchReadmeFromRegistryCdn( + pkg.name, + pkg.version, + )); + + const manifest = aboutDescription + ? { + ...fetchedManifest, + application: { + ...fetchedManifest.application, + aboutDescription, + }, + } + : fetchedManifest; const cdnBaseUrl = this.twentyConfigService.get('APP_REGISTRY_CDN_URL'); @@ -93,7 +88,7 @@ export class MarketplaceCatalogSyncService { sourcePackage: pkg.name, latestAvailableVersion: pkg.version ?? null, isListed: true, - isFeatured: false, + isFeatured, manifest: manifestWithResolvedUrls, ownerWorkspaceId: null, }); diff --git a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace.service.ts b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace.service.ts index 5dd7f24a0eb..595c7795ab5 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application-marketplace/marketplace.service.ts @@ -73,6 +73,39 @@ export class MarketplaceService { } } + async fetchReadmeFromRegistryCdn( + packageName: string, + version: string, + ): Promise { + const cdnBaseUrl = this.twentyConfigService.get('APP_REGISTRY_CDN_URL'); + const url = buildRegistryCdnUrl({ + cdnBaseUrl, + packageName, + version, + filePath: 'README.md', + }); + + try { + const { data } = await axios.get(url, { + headers: { 'User-Agent': 'Twenty-Marketplace' }, + timeout: 5_000, + responseType: 'text', + }); + + if (!data || data.trim().length === 0) { + return null; + } + + return data; + } catch { + this.logger.debug( + `Could not fetch README from CDN for ${packageName}@${version}`, + ); + + return null; + } + } + async fetchAppsFromRegistry(): Promise { const registryUrl = this.twentyConfigService.get('APP_REGISTRY_URL'); diff --git a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts index 229b827fef8..78a38013264 100644 --- a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts +++ b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts @@ -48,6 +48,7 @@ export { IconBrandGraphql, IconBrandLinkedin, IconBrandOpenai, + IconBrandNpm, IconBrandX, IconBriefcase, IconBroadcast, diff --git a/packages/twenty-ui/src/display/index.ts b/packages/twenty-ui/src/display/index.ts index 924bdd0da9c..f44130b5517 100644 --- a/packages/twenty-ui/src/display/index.ts +++ b/packages/twenty-ui/src/display/index.ts @@ -126,6 +126,7 @@ export { IconBrandGraphql, IconBrandLinkedin, IconBrandOpenai, + IconBrandNpm, IconBrandX, IconBriefcase, IconBroadcast,