Skip to main content
Front components are React components that render directly inside Twenty’s UI. They run in an isolated Web Worker using Remote DOM — your code executes inside a sandboxed, opaque-origin iframe, yet its UI still renders natively in the page rather than being confined to that iframe.

Where front components can be used

Front components can render in three locations within Twenty:
  • Side panel — Non-headless front components open in the right-hand side panel. This is the default behavior when a front component is triggered from the command menu.
  • Widgets (dashboards and record pages) — Front components can be embedded as widgets inside page layouts. When configuring a dashboard or a record page layout, users can add a front component widget.
  • App settings — Defined with defineSettingsFrontComponent(), the front component renders as a section inside the app’s Settings tab, in place of the default variable configuration UI.
A front component on its own isn’t reachable from the UI — you need to surface it. The three ways to do that are:
  • Pair it with a command menu item — registers it in the command menu (Cmd+K) and, optionally, as a pinned quick-action.
  • Embed it as a widget in a page layout — places it on a record’s detail page or dashboard.
  • Define it with defineSettingsFrontComponent() — renders it as a section inside the app’s Settings tab, in place of the default variable configuration UI.

Basic example

The quickest way to see a front component in action is to pair it with a defineCommandMenuItem, so it appears as a quick-action button in the top-right corner of the page:
src/front-components/hello-world.tsx
src/command-menu-items/hello-world.command-menu-item.ts
After syncing with yarn twenty dev (or running a one-shot yarn twenty apply), the quick action appears in the top-right corner of the page:
Quick action button in the top-right corner
Click it to render the component inline.

Configuration fields

Placing a front component on a page

Beyond commands, you can embed a front component directly into a record page by adding it as a widget in a page layout. See Page Layouts for details.

Custom settings component

To replace the auto-generated variable configuration UI in your app’s Settings tab with your own component, define it with defineSettingsFrontComponent instead of defineFrontComponent. It takes the same configuration fields (except isHeadless, which is not accepted since a settings component always renders visible UI) and additionally marks the component as the app’s settings UI. The component renders as a section inside the Settings tab, not as a replacement for the whole tab. Twenty’s system-managed sections — auto-upgrade, App URL, and connections — always render above it and cannot be overridden by the app.
src/front-components/app-settings.tsx
Only one settings front component is allowed per app; declaring more than one fails the build. When present, the app’s Settings tab renders this component in place of the default variable configuration UI.

Headless vs non-headless

Front components come in two rendering modes controlled by the isHeadless option: Non-headless (default) — The component renders a visible UI. When triggered from the command menu it opens in the side panel. This is the default behavior when isHeadless is false or omitted. Headless (isHeadless: true) — The component mounts invisibly in the background. It does not open the side panel. Headless components are designed for actions that execute logic and then unmount themselves — for example, running an async task, navigating to a page, or showing a confirmation modal. They pair naturally with the SDK Command components described below.
src/front-components/sync-tracker.tsx
Because the component returns null, Twenty skips rendering a container for it — no empty space appears in the layout. The component still has access to all hooks and the host communication API.

SDK Command components

The twenty-sdk package provides four Command helper components designed for headless front components. Each component executes an action on mount, handles errors by showing a snackbar notification, and automatically unmounts the front component when done. Import them from twenty-sdk/front-component:
  • Command — Runs an async callback via the execute prop.
  • CommandLink — Navigates to an app path. Props: to, params, queryParams, options.
  • CommandModal — Opens a confirmation modal. If the user confirms, executes the execute callback. Props: title, subtitle, execute, confirmButtonText, confirmButtonAccent.
  • CommandOpenSidePanelPage — Opens a side panel page. Props depend on page — e.g. ViewRecord takes recordId + objectNameSingular (plus an optional tab id to open the record on a specific tab), other pages take pageTitle + pageIcon.
Here is a full example of a headless front component using Command to run an action from the command menu:
src/front-components/run-action.tsx
src/command-menu-items/run-action.command-menu-item.ts
And an example using CommandModal to ask for confirmation before executing:
src/front-components/delete-draft.tsx
And an example using CommandOpenSidePanelPage to open the current record in the side panel on a specific tab. tab is a page layout tab id (default layouts use ids like company-tab-emails or company-tab-timeline; custom layouts use the tab’s own id). If the id doesn’t exist in the record’s layout, the default tab opens instead:
src/front-components/open-company-emails.tsx

Calling a logic function

Front components run browser-side in a Web Worker sandboxed inside an opaque-origin iframe, while logic functions run server-side. There is no direct in-process call between the two — instead, a front component reaches a logic function over HTTP. A logic function declared with httpRouteTriggerSettings is reachable over HTTP at its route path. RestApiClient treats paths starting with /s/ as app routes, resolves them to the URL your functions are served from, and authenticates them with TWENTY_APP_ACCESS_TOKEN.
On Twenty Cloud, HTTP-triggered logic functions are served on a dedicated per-workspace domain at https://<your-workspace-subdomain>.withtwenty.com<path>. For external callers, copy the exact URL from the function’s HTTP trigger settings or the application’s Settings tab.
A headless front component can run the call on mount via the Command component, then unmount automatically:
src/front-components/sync-prs.tsx
The path passed to RestApiClient is the logic function’s httpRouteTriggerSettings.path, prefixed with /s. Keep isAuthRequired: true; the TWENTY_APP_ACCESS_TOKEN Twenty mints for your component authenticates the request:
src/logic-functions/fetch-prs.logic-function.ts
TWENTY_APP_ACCESS_TOKEN is injected automatically — see Application variables. Because secret application variables are never exposed to front components, keep API keys and other sensitive logic in the logic function, not in the front component.

Calling the Twenty REST API

To call app HTTP routes or read and write Twenty records from a front component, use RestApiClient from twenty-client-sdk/rest. It sends /s/... paths to your workspace’s functions base URL and every other path, including /rest/..., to TWENTY_API_URL. options accepts headers, query (a record of query-string params; nullish values are skipped), and an AbortSignal via signal. A non-FormData object body is JSON-serialized automatically. On a 401, the client refreshes the access token once through the host and retries the request. The base URL and token are resolved from the environment by default. Pass overrides to the constructor when needed — for example in tests:
Failed requests throw a RestApiClientError exposing status, statusText, url, and the parsed body:

Accessing runtime context

Inside your component, use SDK hooks to access the current user, record, and component instance:
src/front-components/record-info.tsx
Available hooks:

Application variables

Application variables defined in defineApplication() with isSecret: false are available inside front components via the getApplicationVariable utility:
src/front-components/greeting.tsx
Secret variables (isSecret: true) are not exposed to front components. They are only available in logic functions, which run server-side. This prevents sensitive values like API keys from being sent to the browser.
getApplicationVariable always returns a string (or undefined), regardless of the variable’s declared type. The string is serialized consistently by type (booleans as "true" / "false", numbers as decimal strings, arrays / objects as JSON), the same format used for logic-function process.env — parse it yourself (Number(...), JSON.parse(...), === 'true'). See Variable types. The following system variables are always available via process.env:

TWENTY_FUNCTIONS_URL

Twenty also injects TWENTY_FUNCTIONS_URL into front components and logic functions: the base URL your app’s HTTP-triggered logic functions are served from. It exists because that URL is not always the Twenty server itself. On Twenty Cloud, app routes are served on a dedicated per-workspace domain (https://<your-workspace-subdomain>.withtwenty.com, or the application’s primary public domain when one is configured) so that app-authored responses run on an isolated origin rather than on the Twenty app origin. Self-hosted and local instances serve app routes under the /s prefix on the server itself and may not set the variable at all. Since the base URL varies per workspace and per instance, your code cannot hard-code it — the server injects the right value at runtime. You rarely need to read it directly. Call your routes through RestApiClient with a /s/-prefixed path and the client resolves the URL for you: it strips the /s prefix and targets TWENTY_FUNCTIONS_URL, falling back to <TWENTY_API_URL>/s when the variable is not set. Use resolveUrl('/s/<path>') to get the absolute URL without sending a request, e.g. for a link. Read the variable directly only when building a URL by hand:

Host communication API

Front components can trigger navigation, modals, and notifications using functions from twenty-sdk: Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
src/front-components/archive-record.tsx

Working with multiple records

Use useSelectedRecordIds() to handle multiple selected records. This is useful for bulk operations:
src/front-components/bulk-export.tsx
Surface it with a command menu item restricted to record selections:
src/command-menu-items/bulk-export.command-menu-item.ts

Public assets

Front components can access files from the app’s public/ directory using getPublicAssetUrl:
See the public assets section for details.

Styling

Front components support multiple styling approaches. You can use:
  • Inline stylesstyle={{ color: 'red' }}
  • Twenty UI components — Twenty’s own component library; see Using Twenty UI components below
  • Emotion — CSS-in-JS with @emotion/react
  • Styled-componentsstyled.div patterns
  • Tailwind CSS — utility classes
  • Any CSS-in-JS library compatible with React

Using Twenty UI components

Twenty ships its component library as the twenty-ui package. Front components can use it for buttons, tags, status pills, chips, avatars, icons, typography, and theme tokens that automatically match the workspace’s light and dark theme.

Installation

Add the package to your app, pinned to the version your Twenty instance ships:
twenty-ui is bundled into your front component at build time, so it only needs to be a dependency of your app — there is nothing to configure at runtime.

Importing components

Import from the matching subpath rather than the package root, so only the components you use end up in your bundle:

Icons

Import individual icons from twenty-ui/icon:
Each named icon is tree-shaken, so importing a handful adds little to your bundle. Avoid IconsProvider, useIcons, and iconsState — they pull in the full Tabler icon set (several MB).

Theming and theme tokens

Twenty UI components automatically match the workspace’s light and dark theme — the renderer applies the active color scheme on the host, and the components resolve their colors against it. To use the same design tokens in your own inline styles, call the useTheme() hook. It returns Twenty’s theme tokens (spacing, colors, radii, fonts) wired to the active theme, with no ThemeProvider setup needed in your component:
Because useTheme() is a hook, you read tokens inside the component body, so the values always reflect the live theme. The same token map is also exported as the themeCssVariables constant, but prefer useTheme() in front components — a module-level constant that dereferences themeCssVariables can be undefined while the app manifest is extracted. To branch on the active scheme explicitly, read it with useColorScheme() from twenty-sdk/front-component, which returns 'light' or 'dark'.