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.
- 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 adefineCommandMenuItem, 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
yarn twenty dev (or running a one-shot yarn twenty apply), the quick action appears in the top-right corner of the page:

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 withdefineSettingsFrontComponent 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
Headless vs non-headless
Front components come in two rendering modes controlled by theisHeadless 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
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
Thetwenty-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 theexecuteprop.CommandLink— Navigates to an app path. Props:to,params,queryParams,options.CommandModal— Opens a confirmation modal. If the user confirms, executes theexecutecallback. Props:title,subtitle,execute,confirmButtonText,confirmButtonAccent.CommandOpenSidePanelPage— Opens a side panel page. Props depend onpage— e.g.ViewRecordtakesrecordId+objectNameSingular(plus an optionaltabid to open the record on a specific tab), other pages takepageTitle+pageIcon.
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
CommandModal to ask for confirmation before executing:
src/front-components/delete-draft.tsx
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 withhttpRouteTriggerSettings 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
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, useRestApiClient 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:
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
Application variables
Application variables defined indefineApplication() with isSecret: false are available inside front components via the getApplicationVariable utility:
src/front-components/greeting.tsx
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 fromtwenty-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
UseuseSelectedRecordIds() to handle multiple selected records. This is useful for bulk operations:
src/front-components/bulk-export.tsx
src/command-menu-items/bulk-export.command-menu-item.ts
Public assets
Front components can access files from the app’spublic/ directory using getPublicAssetUrl:
Styling
Front components support multiple styling approaches. You can use:- Inline styles —
style={{ color: 'red' }} - Twenty UI components — Twenty’s own component library; see Using Twenty UI components below
- Emotion — CSS-in-JS with
@emotion/react - Styled-components —
styled.divpatterns - Tailwind CSS — utility classes
- Any CSS-in-JS library compatible with React
Using Twenty UI components
Twenty ships its component library as thetwenty-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 fromtwenty-ui/icon:
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 theuseTheme() hook. It returns Twenty’s theme tokens (spacing, colors, radii, fonts) wired to the active theme, with no ThemeProvider setup needed in your component:
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'.