> ## Documentation Index
> Fetch the complete documentation index at: https://twenty-claude-cool-pascal-5ay683.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ページレイアウト

> definePageLayout と definePageLayoutTab を使用して、レコードの詳細ページのカスタマイズ（タブ、ウィジェット、front components のレンダー位置）を行います。

**ページレイアウト**は、レコードの詳細ページがどのように構成されるかを制御します。どのタブを表示し、そのタブにどのウィジェットを含めるかを決定します。 自分が所有するオブジェクトに対してレイアウトを宣言するには `definePageLayout()` を使用し、既に存在するレイアウト（自分のもの、または標準の Twenty のレイアウト）に単一のタブを追加するには `definePageLayoutTab()` を使用します。

| ユースケース                                    | エンティティ                |
| ----------------------------------------- | --------------------- |
| 自分が所有するオブジェクト上のレコードページ全体のレイアウトを定義する       | `definePageLayout`    |
| 既存のレイアウト（自分のオブジェクト、または標準オブジェクト）にタブを1つ追加する | `definePageLayoutTab` |

## definePageLayout

自分が詳細ページ全体を所有している場合に使用します。通常は、自分で定義したカスタムオブジェクトに対して使用します。

```ts src/page-layouts/example-record-page-layout.ts theme={null}
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';

export default definePageLayout({
  universalIdentifier: '203aeb94-6701-46d6-9af1-be2bbcc9e134',
  name: 'Example Record Page',
  type: 'RECORD_PAGE',
  objectUniversalIdentifier: EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER,
  tabs: [
    {
      universalIdentifier: '6ed26b60-a51d-4ad7-86dd-1c04c7f3cac5',
      title: 'Hello World',
      position: 50,
      icon: 'IconWorld',
      layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
      widgets: [
        {
          universalIdentifier: 'aa4234e0-2e5f-4c02-a96a-573449e2351d',
          title: 'Hello World',
          type: 'FRONT_COMPONENT',
          configuration: {
            configurationType: 'FRONT_COMPONENT',
            frontComponentUniversalIdentifier:
              HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER,
          },
        },
      ],
    },
  ],
});
```

### 主なポイント

* `type` は `'RECORD_INDEX'`、`'RECORD_PAGE'`、`'DASHBOARD'`、`'STANDALONE_PAGE'` のいずれかです。 特定のオブジェクトの詳細ビューをカスタマイズするには `'RECORD_PAGE'` を使用します。
* `objectUniversalIdentifier` は、このレイアウトを適用するオブジェクトを指定します。
* 各 `tab` は、`title`、`position`、`layoutMode` を持つページのセクションを定義します。レコードページおよびスタンドアロンページには `VERTICAL_LIST`、ダッシュボードには `GRID`、タブのビューポートを埋める単一のウィジェットには `CANVAS` を使用します。 `VERTICAL_LIST` タブでは、ウィジェットが縦方向に積み重ねられます。 タイムライン、ファイル、メモ、タスク、ワークフローなど、独自のスクロールを管理する組み込みウィジェットは 1 つのビューポートを埋めます。フィールド、フロントコンポーネント、グラフ、その他のコンテンツに合わせたウィジェットは、そのコンテンツの高さまたは設定された高さでレンダリングされます。 `GRID` タブでは、ウィジェットは常に 12 列グリッド上のカードとして配置されます。 `CANVAS` ウィジェットには明示的な位置がありません。キャンバスタブに複数のウィジェットが含まれる場合、それらはビューポート全体を埋めるのではなく、コンテンツの高さでレンダリングされます。
* `layoutMode` を明示的に設定します。 `layoutMode` を省略すると、`STANDALONE_PAGE` では `VERTICAL_LIST`、それ以外では `GRID` が適用されますが、これはレコードページで望ましい動作であることはほとんどありません。
* タブ内の各 `widget` は、[front component](/l/ja/developers/extend/apps/layout/front-components)、リレーションリスト、その他のビルトインウィジェットタイプをレンダリングできます。
* `FRONT_COMPONENT` ウィジェットでは、同じアプリのコマンドメニュー項目ユニバーサル識別子を順序付き配列として `headerCommandMenuItemUniversalIdentifiers` に設定できます。 これらのアクションはウィジェットカードヘッダーにアイコンボタンとして表示され、コマンドレベルの可用性チェックと権限チェックが維持されます。 識別子は一意である必要があり、アプリのインストール時に解決される必要があります。
* タブの `position` は表示順を制御します。 組み込みタブの後にカスタムタブを配置するには、より大きな値（例：50）を使用します。

### フィールド ウィジェット

`FIELD` ウィジェットは、レコードの 1 つのフィールドをレンダリングします。 リレーションフィールドの場合、関連レコードの一覧を埋め込むこともできます。

```ts theme={null}
{
  universalIdentifier: 'c1c2c3c4-c5c6-4000-8000-000000000003',
  title: 'People → Opportunities',
  type: 'FIELD',
  configuration: {
    configurationType: 'FIELD',
    fieldMetadataId: PEOPLE_FIELD_UNIVERSAL_IDENTIFIER,
    fieldDisplayMode: 'TABLE',
    nestedRelationFieldMetadataId: OPPORTUNITIES_FIELD_UNIVERSAL_IDENTIFIER,
  },
}
```

* `fieldMetadataId` は、レイアウトのオブジェクト上のフィールドのユニバーサル識別子を受け取ります。
* `fieldDisplayMode` は `'FIELD'`、`'CARD'`、`'EDITOR'`、`'VIEW'`、`'TABLE'` のいずれかです。 `TABLE` は、1 対多のリレーションフィールドのレコードを一覧表示するビューを埋め込みます。
* `nestedRelationFieldMetadataId` は任意で、リレーション先オブジェクト上の 1 対多リレーションフィールドのユニバーサル識別子を受け取り、2 ホップ先のリレーションにあるレコードを一覧表示するために使用されます（例: 会社ページでその会社の担当者が持つ商談を一覧表示する、または人物ページでその人物の所属する会社の商談を一覧表示する、など）。 最初のホップは 1 対多または多対 1 のリレーションフィールドのどちらでもかまいませんが、2 つ目は必ず 1 対多でなければなりません（ジャンクションリレーションはサポートされません）。また、`fieldDisplayMode: 'TABLE'` が必須であり、ネストされたウィジェットは常に埋め込みビューとしてレンダリングされるため、これを他の表示モードと組み合わせると検証エラーになります。

## definePageLayoutTab

既存のレイアウトにタブを**追加**したい場合にのみ使用します。たとえば、標準の Company ページにアナリティクスタブを追加する場合や、自分のオブジェクトのレイアウトに AI サマリータブを追加する場合などです。

```ts src/page-layouts/example-extra-tab.ts theme={null}
import {
  definePageLayoutTab,
  PageLayoutTabLayoutMode,
  STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk/define';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';

export default definePageLayoutTab({
  universalIdentifier: 'b1b2b3b4-b5b6-4000-8000-000000000001',
  pageLayoutUniversalIdentifier:
    STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.companyRecordPage
      .universalIdentifier,
  title: 'Hello World',
  position: 1000,
  icon: 'IconWorld',
  layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
  widgets: [
    {
      universalIdentifier: 'b1b2b3b4-b5b6-4000-8000-000000000002',
      title: 'Hello World',
      type: 'FRONT_COMPONENT',
      configuration: {
        configurationType: 'FRONT_COMPONENT',
        frontComponentUniversalIdentifier:
          HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER,
      },
    },
  ],
});
```

### 主なポイント

* `pageLayoutUniversalIdentifier` は**必須**であり、インストール時点ですでに存在するページレイアウトを指している必要があります。標準の Twenty のレイアウト、または自分のアプリで定義したレイアウトのいずれかです。 別のインストール済みアプリが所有するレイアウトへのアプリ間参照は、現時点ではサポートされていません。 親レイアウトが存在しない場合、インストールは明確な検証エラーとともに失敗します。

* 標準の Twenty レイアウトの場合は、`twenty-sdk/define` から識別子を import します:

  ```ts theme={null}
  import { STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS } from 'twenty-sdk/define';

  // STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.companyRecordPage.universalIdentifier
  // STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.personRecordPage.universalIdentifier
  // STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.taskRecordPage.universalIdentifier
  // STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.opportunityRecordPage.universalIdentifier
  // STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.noteRecordPage.universalIdentifier
  // …
  ```

  各レイアウトエントリは、その `tabs` とその `widgets` も公開しているため、任意の階層を参照できます:

  ```ts theme={null}
  STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.taskRecordPage.tabs.home
    .universalIdentifier;
  STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS.taskRecordPage.tabs.home.widgets
    .fields.universalIdentifier;
  ```

  短いエイリアス `STANDARD_PAGE_LAYOUT` も利用できます:

  ```ts theme={null}
  import { STANDARD_PAGE_LAYOUT } from 'twenty-sdk/define';

  STANDARD_PAGE_LAYOUT.companyRecordPage.universalIdentifier;
  ```

* `widgets` はこのタブのみにスコープされます。`definePageLayout` 内でインライン定義されたウィジェットとまったく同様に、[front components](/l/ja/developers/extend/apps/layout/front-components)、views などを参照します。

* `position` は、対象のレイアウト上にある既存のタブとの順序を制御します。 組み込みタブとの相対位置が希望どおりになるような値を選択してください。

* 既存のレイアウトに追加だけを行いたい場合は、`definePageLayout` の代わりにこちらを使用してください。 レイアウト全体を自分が所有している場合は、`definePageLayout` を使用してください。
