# Layout Assignments

<table><thead><tr><th width="240">Attribute</th><th>Type</th><th>Description</th><th>Package Types Applicable</th></tr></thead><tbody><tr><td>ignoreLayoutAssignments</td><td>boolean</td><td>Strip UI-magnet metadata (action overrides, object-wide and per-recordType compactLayoutAssignment) from this package's <code>*.object-meta.xml</code> files at build time so the artifact can deploy without depending on UI components owned by another package.</td><td><ul><li>source</li><li>unlocked</li><li>diff</li></ul></td></tr><tr><td>applyLayoutAssignments</td><td>boolean</td><td>Re-applies layout assignments declared in <code>mutators/layout-assignments.yml</code> at deploy time, composing partial CustomObject and Profile metadata using the target org's envelope. Defaults to enabled when the YAML is present; set to <code>false</code> to opt out.</td><td><ul><li>source</li><li>unlocked</li></ul></td></tr></tbody></table>

In a Flxbl project, the package that owns a CustomObject is rarely the same one that owns the FlexiPages, Lightning record pages and CompactLayouts assigned to it. The CustomObject definition references those UI components by name, which means deploying the object package fails unless the UI package is already in the org. The two flags below split that dependency by **stripping the references at build time** in the object-owning package and **re-applying them at deploy time** from the UI package.

## How it works

```
┌──────────────────────┐                          ┌─────────────────────┐
│ Object package       │   build time             │ UI package          │
│ ignoreLayoutAssign-  │  ────── strip ─────►     │ mutators/           │
│ ments: true          │                          │ layout-assignments. │
│                      │                          │ yml                 │
│ Account.object-      │                          │                     │
│ meta.xml             │   deploy time            │ applyLayout-        │
│  (no inline refs)    │  ◄──── compose ────      │ Assignments: true   │
└──────────────────────┘                          └─────────────────────┘
```

* **Build time** — when `ignoreLayoutAssignments` is `true`, sfp removes inline `<actionOverrides>` (Flexipage / Visualforce / LightningComponent), top-level `<compactLayoutAssignment>` and per-recordType `<compactLayoutAssignment>` from every `*.object-meta.xml` in the package. The artifact deploys cleanly even if the UI package isn't yet in the org. The strip log lands in `.sfpowerscripts/logs/<package>` so build stdout stays tidy.
* **Deploy time** — the UI package carries `mutators/layout-assignments.yml`. At install time, sfp reads the YAML, fetches each object's envelope (`label`, `pluralLabel`, `nameField`, `sharingModel`, `deploymentStatus`, recordType `active`/`label`) from the **target org** via REST/Tooling, and composes a partial `CustomObject` (and partial `Profile` for layout assignments) that re-applies the references. Because the envelope is sourced from the live org, the deploy never overwrites object metadata.
* **Pull time** — when `sfp pull` retrieves into a package marked with `ignoreLayoutAssignments: true`, the inline references are stripped again so source-tracking churn doesn't cycle on every pull.

## YAML format

The YAML lives at `mutators/layout-assignments.yml` inside the **UI** package directory. It is schema-validated; typos and unknown keys cause the deploy to fail loudly rather than silently dropping entries.

```yaml
# Layout-magnet metadata that this package OWNS but lives on objects
# and profiles defined in other packages. Composed at deploy time using
# the target org's envelope plus the assignments below.

objects:
  Account:
    # Object-wide compact layout (CustomObject's top-level
    # <compactLayoutAssignment>)
    compactLayout: Account_Default_Compact

    # Replaces standard actions on the object
    actionOverrides:
      - actionName: View
        type: Flexipage           # Flexipage | Visualforce | LightningComponent
        content: Account_Record_Page
        formFactor: Large         # optional
        skipRecordTypeSelect: false  # optional

    # Per-recordType compact layout assignments
    recordTypes:
      Business:
        compactLayout: Business_Compact
      Personal:
        compactLayout: Person_Account_Compact

profiles:
  Sales_User:
    # Profile <layoutAssignments>. Deployed as a partial Profile that
    # merges additively — other profile sections (objectPermissions,
    # userPermissions, ...) are untouched.
    layoutAssignments:
      - layout: Account-Business_Layout
        recordType: Account.Business
      - layout: Account-Personal_Layout
        recordType: Account.Personal
```

## Setting up an existing project

Use `sfp project layout-assignments extract` once per UI package to seed the YAML from inline assignments already in your source. The command refuses to overwrite an existing YAML — pass `--force` to confirm overwrite.

```bash
# Migration: pull existing inline assignments into a UI-owned YAML and
# strip them from the object package's source in one shot.
sfp project layout-assignments extract \
  --source-package src/core-crm \
  --target-package src/ui-crm \
  --strip
```

After the YAML exists, hand-edit it as the source of truth. Subsequent stripping should happen at build time via `ignoreLayoutAssignments` rather than re-running the extract command.

## Sample sfdx-project.json

```json
{
  "packageDirectories": [
    {
      "path": "src/core-crm",
      "package": "core-crm",
      "versionNumber": "1.0.0.NEXT",
      "type": "source",
      "ignoreLayoutAssignments": true
    },
    {
      "path": "src/ui-crm",
      "package": "ui-crm",
      "versionNumber": "1.0.0.NEXT",
      "type": "source",
      "applyLayoutAssignments": true
    }
  ]
}
```

## What is and isn't handled

| Reference                                                                               | Strip at build                              | Re-apply at deploy              |
| --------------------------------------------------------------------------------------- | ------------------------------------------- | ------------------------------- |
| `<actionOverrides>` of type `Flexipage` / `Visualforce` / `LightningComponent`          | ✓                                           | ✓                               |
| Object-wide `<compactLayoutAssignment>`                                                 | ✓                                           | ✓                               |
| Per-recordType `<compactLayoutAssignment>`                                              | ✓                                           | ✓                               |
| Profile `<layoutAssignments>`                                                           | sfprofiles reconciler prunes them at deploy | ✓ (composed as partial Profile) |
| `<actionOverrides>` of type `Default` (no content)                                      | n/a — built-in Salesforce behaviour         | n/a                             |
| `<recordTypes>` definition itself (active, label, picklistValues, businessProcess, ...) | n/a — owned by the object package           | n/a                             |

If the YAML references an object or recordType that isn't present in the target org, the modifier skips it with a warning rather than failing the deploy. Profile names that don't exist in the target org are likewise skipped.

{% hint style="info" %}
The deploy-time composer uses the target org's envelope verbatim — `label`, `pluralLabel`, `nameField`, `deploymentStatus`, `sharingModel` for the CustomObject and `active`, `label` for each recordType. This means re-deploying the partial is idempotent and never overrides the live object's metadata.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp/sfp-community/building-artifacts/configuring-installation-behaviour-of-a-package/layout-assignments.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
