From 68b26f00ba2372e3be7a2ecb1eec85f0654884cb Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Mon, 27 Jul 2026 18:45:10 +0200 Subject: [PATCH] Type PageLayout manifest type prop with PageLayoutType (#23375) Closes #23373 `PageLayoutManifest.type` was typed as `string`, so `definePageLayout({ type: 'NOT_A_VALID_PAGE_LAYOUT_TYPE' })` compiled fine. It is now typed as `` `${PageLayoutType}` ``, which rejects arbitrary strings while keeping both forms assignable: ```ts type: PageLayoutType.STANDALONE_PAGE type: 'STANDALONE_PAGE' ``` A string enum member is assignable to its own literal type, so `` PageLayoutType | `${PageLayoutType}` `` would have been the same type as `` `${PageLayoutType}` `` alone. Going the other way (`type: PageLayoutType` on its own) is strictly narrower and would break every app manifest in `packages/twenty-apps` plus the `create-twenty-app` template, which all pass raw strings. --- .../twenty-docs/developers/extend/apps/layout/page-layouts.mdx | 2 +- .../twenty-shared/src/application/pageLayoutManifestType.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx b/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx index aa04200c98..76f494e517 100644 --- a/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx +++ b/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx @@ -51,7 +51,7 @@ export default definePageLayout({ ### Key points -- `type` is typically `'RECORD_PAGE'` to customize the detail view of a specific object. +- `type` is one of `'RECORD_INDEX'`, `'RECORD_PAGE'`, `'DASHBOARD'` or `'STANDALONE_PAGE'`. Use `'RECORD_PAGE'` to customize the detail view of a specific object. - `objectUniversalIdentifier` specifies which object this layout applies to. - Each `tab` defines a section of the page with a `title`, `position`, and `layoutMode` (`VERTICAL_LIST` for record pages, `GRID` for dashboards). A tab holding a single widget renders it full-bleed automatically; with several widgets they stack as cards. - Each `widget` inside a tab can render a [front component](/developers/extend/apps/layout/front-components), a relation list, or other built-in widget types. diff --git a/packages/twenty-shared/src/application/pageLayoutManifestType.ts b/packages/twenty-shared/src/application/pageLayoutManifestType.ts index 5597b5bf0f..687c130e1d 100644 --- a/packages/twenty-shared/src/application/pageLayoutManifestType.ts +++ b/packages/twenty-shared/src/application/pageLayoutManifestType.ts @@ -2,6 +2,7 @@ import { type SyncableEntityOptions } from '@/application/syncableEntityOptionsT import { type GridPosition, type PageLayoutTabLayoutMode, + type PageLayoutType, type PageLayoutWidgetConditionalDisplay, type PageLayoutWidgetUniversalConfiguration, } from '@/types'; @@ -26,7 +27,7 @@ export type PageLayoutTabManifest = SyncableEntityOptions & { export type PageLayoutManifest = SyncableEntityOptions & { name: string; - type: string; + type: `${PageLayoutType}`; objectUniversalIdentifier?: string; defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier?: string; tabs?: PageLayoutTabManifest[];