[FRONT COMPONENTS] Headless components (#18096)

## Description

- Add `isHeadless` field to `FrontComponent` entity so front components
can run without rendering UI in the command menu
- Introduce headless front component mounting logic:
`HeadlessFrontComponentMountRoot` at the application root,
`useMountHeadlessFrontComponent`, and `useUnmountHeadlessFrontComponent`
hooks to mount/unmount headless components
- Expand the SDK with new action components (`Action`, `ActionLink`,
`ActionOpenSidePanelPage`) and host communication functions
(`openSidePanelPage`, `unmountFrontComponent`)
- Move `CommandMenuPages` type to twenty-shared so the SDK can reference
it for side panel navigation

## Video QA



https://github.com/user-attachments/assets/4f9e3bb1-fcd1-42be-b3f4-a97e80c2add2
This commit is contained in:
Raphaël Bosi
2026-02-20 15:14:42 +01:00
committed by GitHub
parent d444648cc0
commit 7da8450075
100 changed files with 518 additions and 143 deletions
@@ -7,4 +7,5 @@ export const FLAT_FRONT_COMPONENT_EDITABLE_PROPERTIES = [
'sourceComponentPath',
'builtComponentPath',
'componentName',
'isHeadless',
] as const satisfies MetadataEntityPropertyName<'frontComponent'>[];
@@ -33,6 +33,7 @@ export const fromCreateFrontComponentInputToFlatFrontComponentToCreate = ({
builtComponentPath: createFrontComponentInput.builtComponentPath,
componentName: createFrontComponentInput.componentName,
builtComponentChecksum: createFrontComponentInput.builtComponentChecksum,
isHeadless: false,
workspaceId,
createdAt: now,
updatedAt: now,
@@ -20,6 +20,7 @@ export const fromFlatFrontComponentToFrontComponentDto = (
: undefined,
workspaceId: flatFrontComponent.workspaceId,
applicationId: flatFrontComponent.applicationId,
isHeadless: flatFrontComponent.isHeadless,
createdAt: new Date(flatFrontComponent.createdAt),
updatedAt: new Date(flatFrontComponent.updatedAt),
});
@@ -31,6 +31,7 @@ export const fromFrontComponentEntityToFlatFrontComponent = ({
builtComponentPath: frontComponentEntity.builtComponentPath,
componentName: frontComponentEntity.componentName,
builtComponentChecksum: frontComponentEntity.builtComponentChecksum,
isHeadless: frontComponentEntity.isHeadless,
workspaceId: frontComponentEntity.workspaceId,
universalIdentifier: frontComponentEntity.universalIdentifier,
applicationId: frontComponentEntity.applicationId,