diff --git a/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx
index 409ab29c15..258650e049 100644
--- a/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx
@@ -837,6 +837,255 @@ export default defineFrontComponent({
* **مُنشأ بالقالب**: شغّل `yarn twenty entity:add` واختر خيار إضافة مكوّن أمامي جديد.
* **يدوي**: أنشئ ملفًا جديدًا `.tsx` واستخدم `defineFrontComponent()` مع اتباع النمط نفسه.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| الحقل | النوع | الوصف |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `التسمية` | `string` (required) | Display label shown in the command menu |
+| `أيقونة` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | الوصف |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `string` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| دالة | Signature | الوصف |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `التنقل` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+
+
Archive this record?
+
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
+ name: 'archive-record',
+ description: 'Archives the current record',
+ component: ArchiveRecord,
+});
+```
+
### المهارات
تُحدِّد المهارات تعليمات وإمكانات قابلة لإعادة الاستخدام يمكن لوكلاء الذكاء الاصطناعي استخدامها داخل مساحة العمل لديك. استخدم `defineSkill()` لتعريف مهارات مع تحقّق مدمج:
diff --git a/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
index a713b70424..08ff346423 100644
--- a/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
+++ b/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/de/developers/contribute/capabilities/front
### Zustandsverwaltung
-[Jotai](https://jotai.org/) handles state management.
+[Jotai](https://jotai.org/) übernimmt die Zustandsverwaltung.
Siehe [Best Practices](/l/de/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) für mehr Informationen zur Zustandsverwaltung.
diff --git a/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx
index 9fa92f19f7..69dae71045 100644
--- a/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx
+++ b/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx
@@ -1,20 +1,20 @@
---
title: Erste Schritte
-description: Create your first Twenty app in minutes.
+description: Erstellen Sie in wenigen Minuten Ihre erste Twenty-App.
---
Apps befinden sich derzeit in der Alpha-Testphase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter.
-Apps let you extend Twenty with custom objects, fields, logic functions, AI skills, and UI components — all managed as code.
+Apps ermöglichen es Ihnen, Twenty mit benutzerdefinierten Objekten, Feldern, Logikfunktionen, KI-Fähigkeiten und UI-Komponenten zu erweitern — alles als Code verwaltet.
**Was Sie heute tun können:**
* Benutzerdefinierte Objekte und Felder als Code definieren (verwaltetes Datenmodell)
-* Build logic functions with custom triggers (HTTP routes, cron, database events)
+* Erstellen Sie Logikfunktionen mit benutzerdefinierten Triggern (HTTP-Routen, cron, Datenbankereignisse)
* Fähigkeiten für KI-Agenten definieren
-* Build front components that render inside Twenty's UI
+* Erstellen Sie Frontend-Komponenten, die in der Twenty-UI gerendert werden
* Dieselbe App in mehreren Workspaces bereitstellen
## Voraussetzungen
diff --git a/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx
index d9f0634aff..221bb8b0fe 100644
--- a/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx
+++ b/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx
@@ -1,6 +1,6 @@
---
-title: Publishing
-description: Distribute your Twenty app to the marketplace or deploy it internally.
+title: Veröffentlichen
+description: Veröffentlichen Sie Ihre Twenty-App auf dem Twenty-Marktplatz oder stellen Sie sie intern bereit.
---
@@ -9,41 +9,41 @@ Apps befinden sich derzeit in der Alpha-Testphase. Die Funktion ist funktionsfä
## Übersicht
-Once your app is [built and tested locally](/l/de/developers/extend/apps/building), you have two paths for distributing it:
+Sobald Ihre App [lokal gebaut und getestet](/l/de/developers/extend/apps/building) wurde, haben Sie zwei Möglichkeiten, sie zu verteilen:
-* **Publish to npm** — list your app in the Twenty marketplace for any workspace to discover and install.
-* **Push a tarball** — deploy your app to a specific Twenty server for internal use without making it publicly available.
+* **Auf npm veröffentlichen** — führen Sie Ihre App im Twenty-Marktplatz auf, damit jeder Arbeitsbereich sie entdecken und installieren kann.
+* **Einen Tarball pushen** — stellen Sie Ihre App auf einem bestimmten Twenty-Server für die interne Nutzung bereit, ohne sie öffentlich verfügbar zu machen.
-## Publishing to npm
+## Auf npm veröffentlichen
-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.
+Die Veröffentlichung auf npm macht Ihre App im Twenty-Marktplatz auffindbar. Jeder Twenty-Arbeitsbereich kann Marktplatz-Apps direkt über die Benutzeroberfläche durchsuchen, installieren und aktualisieren.
-### Requirements
+### Anforderungen
-* An [npm](https://www.npmjs.com) account
-* Your package name **must** use the `twenty-app-` prefix (e.g., `twenty-app-postcard-sender`)
+* Ein [npm](https://www.npmjs.com)-Konto
+* Ihr Paketname **muss** das Präfix `twenty-app-` verwenden (z. B. `twenty-app-postcard-sender`)
### Schritte
-1. **Build your app** — the CLI compiles your TypeScript sources and generates the application manifest:
+1. **App erstellen** — die CLI kompiliert Ihre TypeScript-Quellen und erzeugt das Anwendungsmanifest:
```bash filename="Terminal"
yarn twenty app:build
```
-2. **Publish to npm** — push the built package to the npm registry:
+2. **Auf npm veröffentlichen** — pushen Sie das gebaute Paket in die npm-Registry:
```bash filename="Terminal"
npx twenty app:publish
```
-### Auto-discovery
+### Automatische Erkennung
-Packages with the `twenty-app-` prefix are automatically discovered by the Twenty marketplace catalog. Once published, your app appears in the marketplace within a few minutes — no manual registration or approval required.
+Pakete mit dem Präfix `twenty-app-` werden vom Twenty-Marktplatzkatalog automatisch erkannt. Nach der Veröffentlichung erscheint Ihre App innerhalb weniger Minuten im Marktplatz — keine manuelle Registrierung oder Genehmigung erforderlich.
-### CI publishing
+### CI-Veröffentlichung
-The scaffolded project includes a GitHub Actions workflow that publishes on every release. It runs `app:build`, then `npm publish --provenance` from the build output:
+Das vorgefertigte Projekt enthält einen GitHub-Actions-Workflow, der bei jedem Release eine Veröffentlichung durchführt. Er führt `app:build` aus und danach `npm publish --provenance` aus dem Build-Output:
```yaml filename=".github/workflows/publish.yml"
name: Publish
@@ -72,48 +72,48 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
-For other CI systems (GitLab CI, CircleCI, etc.), the same three commands apply: `yarn install`, `npx twenty app:build`, then `npm publish` from `.twenty/output`.
+Für andere CI-Systeme (GitLab CI, CircleCI usw.) gelten die gleichen drei Befehle: `yarn install`, `npx twenty app:build` und anschließend `npm publish` aus `.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](https://docs.npmjs.com/generating-provenance-statements) for setup instructions.
+**npm-Provenance** ist optional, wird jedoch empfohlen. Das Veröffentlichen mit `--provenance` fügt Ihrem npm-Eintrag ein Vertrauensabzeichen hinzu, sodass Nutzer überprüfen können, dass das Paket aus einem bestimmten Commit in einer öffentlichen CI-Pipeline gebaut wurde. Siehe die [npm-Provenance-Dokumentation](https://docs.npmjs.com/generating-provenance-statements) für Einrichtungshinweise.
-## Internal distribution
+## Interne Verteilung
-For apps you don't want publicly available — proprietary tools, enterprise-only integrations, or experimental builds — you can push a tarball directly to a Twenty server.
+Für Apps, die Sie nicht öffentlich verfügbar machen möchten — proprietäre Tools, nur für Unternehmen bestimmte Integrationen oder experimentelle Builds — können Sie einen Tarball direkt auf einen Twenty-Server pushen.
-### Push a tarball
+### Einen Tarball pushen
-Build your app and deploy it to a specific server in one step:
+Erstellen Sie Ihre App und stellen Sie sie in einem Schritt auf einem bestimmten Server bereit:
```bash filename="Terminal"
npx twenty app:publish --server
```
-Any workspace on that server can then install and upgrade the app from the **Applications** settings page.
+Jeder Arbeitsbereich auf diesem Server kann die App anschließend über die Seite **Applications** in den Einstellungen installieren und aktualisieren.
-### Version management
+### Versionsverwaltung
-To release an update:
+So veröffentlichen Sie ein Update:
-1. Bump the `version` field in your `package.json`
-2. Push a new tarball with `npx twenty app:publish --server `
-3. Workspaces on that server will see the upgrade available in their settings
+1. Erhöhen Sie das Feld `version` in Ihrer `package.json`
+2. Pushen Sie einen neuen Tarball mit `npx twenty app:publish --server `
+3. Arbeitsbereiche auf diesem Server sehen in ihren Einstellungen, dass ein Upgrade verfügbar ist.
-Internal apps are scoped to the server they're pushed to. They won't appear in the public marketplace and can't be installed by workspaces on other servers.
+Interne Apps sind auf den Server beschränkt, auf den sie gepusht werden. Sie erscheinen nicht im öffentlichen Marktplatz und können von Arbeitsbereichen auf anderen Servern nicht installiert werden.
-## App categories
+## App-Kategorien
-Twenty organizes apps into three categories based on how they're distributed:
+Twenty organisiert Apps in drei Kategorien, basierend auf ihrer Vertriebsart:
-| Kategorie | Wie es funktioniert | Visible in marketplace? |
-| --------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------- |
-| **Entwicklung** | Local dev mode apps running via `yarn twenty app:dev`. Used for building and testing. | Nein |
-| **Published** | Apps published to npm with the `twenty-app-` prefix. Listed in the marketplace for any workspace to install. | Ja |
-| **Internal** | Apps deployed via tarball to a specific server. Available only to workspaces on that server. | Nein |
+| Kategorie | Wie es funktioniert | Im Marktplatz sichtbar? |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- |
+| **Entwicklung** | Lokale Apps im Entwicklungsmodus, die über `yarn twenty app:dev` ausgeführt werden. Zum Erstellen und Testen verwendet. | Nein |
+| **Veröffentlicht** | Auf npm veröffentlichte Apps mit dem Präfix `twenty-app-`. Im Marktplatz gelistet, damit jeder Arbeitsbereich sie installieren kann. | Ja |
+| **Intern** | Apps, die per Tarball auf einen bestimmten Server bereitgestellt werden. Nur für Arbeitsbereiche auf diesem Server verfügbar. | Nein |
-Start in **Development** mode while building your app. When it's ready, choose **Published** (npm) for broad distribution or **Internal** (tarball) for private deployment.
+Beginnen Sie im **Entwicklungsmodus**, während Sie Ihre App erstellen. Wenn sie bereit ist, wählen Sie **Veröffentlicht** (npm) für die breite Verteilung oder **Intern** (Tarball) für die private Bereitstellung.
diff --git a/packages/twenty-docs/l/de/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/de/developers/extend/capabilities/apps.mdx
index f2470441a7..6645bae140 100644
--- a/packages/twenty-docs/l/de/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/de/developers/extend/capabilities/apps.mdx
@@ -321,11 +321,11 @@ Sie können Standardfelder überschreiben, indem Sie in Ihrem `fields`-Array ein
dies wird jedoch nicht empfohlen.
-### Defining fields on existing objects
+### Felder für bestehende Objekte definieren
-Use `defineField()` to add custom fields to existing objects — both standard objects (like `company`, `person`, `opportunity`) and custom objects defined by other apps. Each field lives in its own file and references the target object by its `universalIdentifier`.
+Verwenden Sie `defineField()`, um benutzerdefinierte Felder zu bestehenden Objekten hinzuzufügen — sowohl zu Standardobjekten (wie `company`, `person`, `opportunity`) als auch zu benutzerdefinierten Objekten, die von anderen Apps definiert werden. Jedes Feld befindet sich in einer eigenen Datei und verweist auf das Zielobjekt über dessen `universalIdentifier`.
-To reference standard objects, import `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk`. This constant provides stable identifiers for all built-in objects and their fields:
+Um auf Standardobjekte zu verweisen, importieren Sie `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` aus `twenty-sdk`. Diese Konstante stellt stabile Bezeichner für alle integrierten Objekte und deren Felder bereit:
```typescript
// src/fields/apollo-total-funding.field.ts
@@ -349,22 +349,22 @@ export default defineField({
Hauptpunkte:
-* `objectUniversalIdentifier` tells Twenty which object to attach the field to. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` for standard objects.
-* Each field requires its own stable `universalIdentifier`, a `name`, `type`, `label`, and the target `objectUniversalIdentifier`.
-* You can scaffold new fields using `yarn twenty entity:add` and choosing the field option.
-* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` is also exported as `STANDARD_OBJECT` for convenience — both refer to the same constant.
+* `objectUniversalIdentifier` teilt Twenty mit, an welches Objekt das Feld angehängt werden soll. Verwenden Sie `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` für Standardobjekte.
+* Jedes Feld benötigt einen eigenen stabilen `universalIdentifier`, `name`, `type`, `label` und den Ziel-`objectUniversalIdentifier`.
+* Sie können mit `yarn twenty entity:add` neue Felder anlegen, indem Sie die Feldoption wählen.
+* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` wird der Einfachheit halber auch als `STANDARD_OBJECT` exportiert — beide verweisen auf dieselbe Konstante.
-Available standard objects include: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion`, and `workspaceMember`.
+Verfügbare Standardobjekte sind unter anderem: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion` und `workspaceMember`.
-Each standard object also exposes its field identifiers. For example, to reference a specific field on a standard object in role permissions:
+Jedes Standardobjekt stellt außerdem seine Feldbezeichner bereit. Beispielsweise, um in Rollenberechtigungen auf ein bestimmtes Feld eines Standardobjekts zu verweisen:
```typescript
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.fields.name.universalIdentifier
```
-#### Relation fields on existing objects
+#### Beziehungsfelder bei bestehenden Objekten
-You can also define relation fields that link existing objects to your custom objects:
+Sie können auch Beziehungsfelder definieren, die bestehende Objekte mit Ihren benutzerdefinierten Objekten verknüpfen:
```typescript
// src/fields/people-on-call-recording.field.ts
@@ -837,6 +837,255 @@ Sie können neue Frontend-Komponenten auf zwei Arten erstellen:
* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Frontend-Komponente.
* **Manuell**: Erstellen Sie eine neue `.tsx`-Datei und verwenden Sie `defineFrontComponent()` nach demselben Muster.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| Feld | Typ | Beschreibung |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `beschriftung` | `string` (required) | Display label shown in the command menu |
+| `symbol` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | Beschreibung |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `string` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| Funktion | Signature | Beschreibung |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `navigieren` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+
+
Archive this record?
+
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
+ name: 'archive-record',
+ description: 'Archives the current record',
+ component: ArchiveRecord,
+});
+```
+
### Fähigkeiten
Skills definieren wiederverwendbare Anweisungen und Fähigkeiten, die KI-Agenten in Ihrem Arbeitsbereich verwenden können. Verwenden Sie `defineSkill()`, um Skills mit eingebauter Validierung zu definieren:
@@ -974,12 +1223,12 @@ uploadFile(
): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }>
```
-| Parameter | Typ | Beschreibung |
-| ---------------------------------- | -------- | ------------------------------------------------------------------------------- |
-| `fileBuffer` | `Buffer` | Der Rohinhalt der Datei |
-| `filename` | `string` | Der Name der Datei (wird für Speicherung und Anzeige verwendet) |
-| `contentType` | `string` | MIME-Typ der Datei (standardmäßig `application/octet-stream`, wenn weggelassen) |
-| `fieldMetadataUniversalIdentifier` | `string` | Der `universalIdentifier` des Dateityp-Felds in Ihrem Objekt |
+| Parameter | Typ | Beschreibung |
+| ---------------------------------- | -------------- | ------------------------------------------------------------------------------- |
+| `fileBuffer` | `Buffer` | Der Rohinhalt der Datei |
+| `filename` | `string` | Der Name der Datei (wird für Speicherung und Anzeige verwendet) |
+| `contentType` | `string` | MIME-Typ der Datei (standardmäßig `application/octet-stream`, wenn weggelassen) |
+| `fieldMetadataUniversalIdentifier` | `Zeichenkette` | Der `universalIdentifier` des Dateityp-Felds in Ihrem Objekt |
Hauptpunkte:
diff --git a/packages/twenty-docs/l/de/developers/extend/extend.mdx b/packages/twenty-docs/l/de/developers/extend/extend.mdx
index f38eb0aabe..d12db12273 100644
--- a/packages/twenty-docs/l/de/developers/extend/extend.mdx
+++ b/packages/twenty-docs/l/de/developers/extend/extend.mdx
@@ -15,7 +15,7 @@ Twenty ist darauf ausgelegt, erweiterbar zu sein. Verwenden Sie unsere APIs, Web
* **APIs**: Abfragen und ändern Sie Ihre CRM-Daten programmatisch mit REST oder GraphQL
* **Webhooks**: Erhalten Sie Benachrichtigungen in Echtzeit, wenn Ereignisse in Twenty auftreten
-* **Apps**: Build custom applications that extend Twenty's capabilities
+* **Apps**: Erstellen Sie benutzerdefinierte Anwendungen, die die Funktionalität von Twenty erweitern
## Erste Schritte
@@ -27,6 +27,6 @@ Twenty ist darauf ausgelegt, erweiterbar zu sein. Verwenden Sie unsere APIs, Web
Erhalten Sie Benachrichtigungen über Ereignisse in Echtzeit
- Build customizations as code
+ Erstellen Sie Anpassungen als Code
diff --git a/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
index 30fb17f7be..77ea6146b3 100644
--- a/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
+++ b/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
@@ -77,7 +77,7 @@ Per evitare [re-render](/l/it/developers/contribute/capabilities/frontend-develo
### Gestione dello stato
-[Jotai](https://jotai.org/) handles state management.
+[Jotai](https://jotai.org/) gestisce lo stato.
Vedi [best practices](/l/it/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) per ulteriori informazioni sulla gestione dello stato.
diff --git a/packages/twenty-docs/l/it/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/it/developers/extend/capabilities/apps.mdx
index dcb7e5b82f..63c4f35caf 100644
--- a/packages/twenty-docs/l/it/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/it/developers/extend/capabilities/apps.mdx
@@ -837,6 +837,255 @@ Puoi creare nuovi componenti front-end in due modi:
* **Generata dallo scaffolder**: Esegui `yarn twenty entity:add` e scegli l'opzione per aggiungere un nuovo componente front-end.
* **Manuale**: Crea un nuovo file `.tsx` e usa `defineFrontComponent()`, seguendo lo stesso schema.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| Campo | Tipo | Descrizione |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `etichetta` | `string` (required) | Display label shown in the command menu |
+| `icona` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | Descrizione |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `string` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| Funzione | Signature | Descrizione |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `naviga` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+
+
Archive this record?
+
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
+ name: 'archive-record',
+ description: 'Archives the current record',
+ component: ArchiveRecord,
+});
+```
+
### Abilità
Skills define reusable instructions and capabilities that AI agents can use within your workspace. Use `defineSkill()` to define skills with built-in validation:
diff --git a/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
index 9743a94c47..31c274ae2b 100644
--- a/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
+++ b/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/pt/developers/contribute/capabilities/front
### Gerenciamento de Estado
-[Jotai](https://jotai.org/) handles state management.
+[Jotai](https://jotai.org/) gerencia o estado.
Veja [melhores práticas](/l/pt/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) para mais informações sobre gerenciamento de estado.
diff --git a/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx
index 03244d1f76..ca1cec8a00 100644
--- a/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx
@@ -838,6 +838,255 @@ Você pode criar novos componentes de front-end de duas formas:
* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar um novo componente de front-end.
* **Manual**: Crie um novo ficheiro `.tsx` e use `defineFrontComponent()`, seguindo o mesmo padrão.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| Campo | Tipo | Descrição |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `etiqueta` | `string` (required) | Display label shown in the command menu |
+| `ícone` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | Descrição |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `string` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| Função | Signature | Descrição |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `navegar` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+
+
Archive this record?
+
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
+ name: 'archive-record',
+ description: 'Archives the current record',
+ component: ArchiveRecord,
+});
+```
+
### Habilidades
As habilidades definem instruções e capacidades reutilizáveis que os agentes de IA podem usar no seu espaço de trabalho. Use `defineSkill()` para definir habilidades com validação integrada:
diff --git a/packages/twenty-docs/l/ro/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/ro/developers/extend/capabilities/apps.mdx
index 1a3bfb583d..4b4c18f577 100644
--- a/packages/twenty-docs/l/ro/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/ro/developers/extend/capabilities/apps.mdx
@@ -837,6 +837,255 @@ Puteți crea componente Front noi în două moduri:
* **Generat**: Rulați `yarn twenty entity:add` și alegeți opțiunea de a adăuga o componentă frontend nouă.
* **Manual**: Creați un fișier nou `.tsx` și folosiți `defineFrontComponent()`, urmând același model.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| Câmp | Tip | Descriere |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `etichetă` | `string` (required) | Display label shown in the command menu |
+| `pictogramă` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | Descriere |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `string` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| Funcție | Signature | Descriere |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `navigate` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+
+
Archive this record?
+
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
+ name: 'archive-record',
+ description: 'Archives the current record',
+ component: ArchiveRecord,
+});
+```
+
### Abilități
Abilitățile definesc instrucțiuni și capabilități reutilizabile pe care agenții AI le pot folosi în spațiul dvs. de lucru. Folosiți `defineSkill()` pentru a defini abilități cu validare încorporată:
diff --git a/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx
index c0685379f8..282b91f07d 100644
--- a/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx
@@ -837,6 +837,255 @@ export default defineFrontComponent({
* **Сгенерировано**: Запустите `yarn twenty entity:add` и выберите опцию добавления нового фронтенд-компонента.
* **Вручную**: Создайте новый файл `.tsx` и используйте `defineFrontComponent()`, следуя тому же шаблону.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| Поле | Тип | Описание |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `метка` | `string` (required) | Display label shown in the command menu |
+| `иконка` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | Описание |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `строка` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| Функция | Signature | Описание |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `навигация` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+
+
Archive this record?
+
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
+ name: 'archive-record',
+ description: 'Archives the current record',
+ component: ArchiveRecord,
+});
+```
+
### Навыки
Навыки определяют многократно используемые инструкции и возможности, которые агенты ИИ могут использовать в вашем рабочем пространстве. Используйте `defineSkill()` для определения навыков со встроенной валидацией:
diff --git a/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx
index 096d5d075e..6950093da2 100644
--- a/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx
@@ -837,6 +837,255 @@ Yeni ön uç bileşenlerini iki şekilde oluşturabilirsiniz:
* **Şablondan**: `yarn twenty entity:add` çalıştırın ve yeni bir ön uç bileşeni ekleme seçeneğini seçin.
* **Manuel**: Aynı deseni izleyerek yeni bir `.tsx` dosyası oluşturun ve `defineFrontComponent()` kullanın.
+#### Where front components can be used
+
+Front components can render in two 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.
+
+#### 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** — 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.
+
+```typescript
+export default defineFrontComponent({
+ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ name: 'my-action',
+ description: 'Runs an action without opening the side panel',
+ component: MyAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
+ label: 'Run my action',
+ },
+});
+```
+
+#### Adding command menu items
+
+To make a front component appear as an item in Twenty's command menu, add the `command` property to `defineFrontComponent()`. When users open the command menu (Cmd+K / Ctrl+K), the item shows up and triggers the front component on click.
+
+The `command` object accepts the following fields:
+
+| Alan | Tür | Açıklama |
+| --------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `universalIdentifier` | `string` (required) | Unique ID for the command menu item |
+| `etiket` | `string` (required) | Display label shown in the command menu |
+| `simge` | `string` (optional) | Icon name (e.g., `'IconSparkles'`) |
+| `isPinned` | `boolean` (optional) | Whether the command is pinned at the top of the menu |
+| `availabilityType` | `'GLOBAL' \| 'RECORD_SELECTION'` (optional) | `GLOBAL` shows the command everywhere; `RECORD_SELECTION` shows it only in record contexts |
+| `availabilityObjectUniversalIdentifier` | `string` (optional) | Restrict the command to a specific object type (e.g., Person) |
+
+Here is an example from the call-recording app that adds a command scoped to Person records:
+
+```typescript
+import { defineFrontComponent } from 'twenty-sdk';
+
+export default defineFrontComponent({
+ universalIdentifier: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
+ name: 'Summarize Person Call Recordings',
+ description: 'Generates a summary of call recordings for a person',
+ component: SummarizePersonRecordings,
+ command: {
+ universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-234567890123',
+ label: 'Summarize call recordings',
+ icon: 'IconSparkles',
+ isPinned: false,
+ availabilityType: 'RECORD_SELECTION',
+ availabilityObjectUniversalIdentifier:
+ '20202020-e674-48e5-a542-72570eee7213',
+ },
+});
+```
+
+When the command is synced, it appears in the command menu. If the front component is non-headless the side panel opens with the component rendered inside. If it is headless the component mounts in the background and executes its logic.
+
+#### 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/command`:
+
+* **`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 specific side panel page. Props: `page`, `pageTitle`, `pageIcon`.
+
+Here is a full example of a headless front component using `Command` to run an action from the command menu:
+
+```typescript
+// src/front-components/run-action.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { Command } from 'twenty-sdk/command';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const RunAction = () => {
+ const execute = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ createTask: {
+ __args: { data: { title: 'Created by my app' } },
+ id: true,
+ },
+ });
+ };
+
+ return ;
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
+ name: 'run-action',
+ description: 'Creates a task from the command menu',
+ component: RunAction,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
+ label: 'Run my action',
+ icon: 'IconPlayerPlay',
+ },
+});
+```
+
+And an example using `CommandModal` to ask for confirmation before executing:
+
+```typescript
+// src/front-components/delete-draft.tsx
+import { defineFrontComponent } from 'twenty-sdk';
+import { CommandModal } from 'twenty-sdk/command';
+
+const DeleteDraft = () => {
+ const execute = async () => {
+ // perform the deletion
+ };
+
+ return (
+
+ );
+};
+
+export default defineFrontComponent({
+ universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
+ name: 'delete-draft',
+ description: 'Deletes a draft with confirmation',
+ component: DeleteDraft,
+ isHeadless: true,
+ command: {
+ universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
+ label: 'Delete draft',
+ icon: 'IconTrash',
+ },
+});
+```
+
+#### Execution context
+
+Every front component receives an execution context that provides information about where and how it is running. Access context values using hooks from `twenty-sdk`:
+
+| Hook | Return type | Açıklama |
+| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `useFrontComponentId()` | `string` | The unique ID of the current front component instance |
+| `useRecordId()` | `string \| null` | The ID of the current record, when the component runs in a record context (e.g., a record page widget or a command scoped to a record). Returns `null` otherwise. |
+| `useUserId()` | `string \| null` | The ID of the current user |
+
+```typescript
+import { useRecordId, useUserId } from 'twenty-sdk';
+
+const MyWidget = () => {
+ const recordId = useRecordId();
+ const userId = useUserId();
+
+ return (
+
+
Record: {recordId ?? 'none'}
+
User: {userId ?? 'anonymous'}
+
+ );
+};
+```
+
+The context is reactive — if the surrounding record changes, hooks automatically return the updated values.
+
+#### Host API functions
+
+Front components run in an isolated sandbox but can interact with Twenty's UI through a set of functions provided by the host. Import them directly from `twenty-sdk`:
+
+```typescript
+import {
+ navigate,
+ closeSidePanel,
+ enqueueSnackbar,
+ unmountFrontComponent,
+ openSidePanelPage,
+ openCommandConfirmationModal,
+} from 'twenty-sdk';
+```
+
+| Fonksiyon | Signature | Açıklama |
+| ------------------------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `gezin` | `(to, params?, queryParams?, options?) => Promise` | Navigate to a typed app path within Twenty |
+| `closeSidePanel` | `() => Promise` | Close the side panel |
+| `enqueueSnackbar` | `(params) => Promise` | Show a snackbar notification. Params: `message`, `variant` (`'error'`, `'success'`, `'info'`, `'warning'`), optional `duration`, `detailedMessage`, `dedupeKey` |
+| `unmountFrontComponent` | `() => Promise` | Unmount the current front component (used by headless components to clean up after execution) |
+| `openSidePanelPage` | `(params) => Promise` | Open a page in the side panel. Params: `page`, `pageTitle`, `pageIcon`, `shouldResetSearchState` |
+| `openCommandConfirmationModal` | `(params) => Promise<'confirm' \| 'cancel'>` | Show a confirmation modal and wait for the user's response. Params: `title`, `subtitle`, `confirmButtonText`, `confirmButtonAccent` (`'default'`, `'blue'`, `'danger'`) |
+
+Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
+
+```typescript
+import { defineFrontComponent, useRecordId } from 'twenty-sdk';
+import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
+import { CoreApiClient } from 'twenty-sdk/clients';
+
+const ArchiveRecord = () => {
+ const recordId = useRecordId();
+
+ const handleArchive = async () => {
+ const client = new CoreApiClient();
+
+ await client.mutation({
+ updateTask: {
+ __args: { id: recordId, data: { status: 'ARCHIVED' } },
+ id: true,
+ },
+ });
+
+ await enqueueSnackbar({
+ message: 'Record archived',
+ variant: 'success',
+ });
+
+ await closeSidePanel();
+ };
+
+ return (
+