ObjectUIObjectUI

Slotted Pages

Customize record detail pages by overriding only the slots you care about — let the default synthesizer handle the rest.

Slotted Pages

Every record detail page in ObjectUI is synthesized from the object definition by default (see buildDefaultPageSchema). You get a Lightning-style page — header, highlights, tabs, related lists, history — without writing a single line of page schema.

When you want to customize part of that page, you have two options:

  1. Full page (kind: "full", the default): author the entire regions[].components[] tree. Total control, total responsibility — you re-author every region.
  2. Slotted page (kind: "slotted"): provide overrides for only the slots you care about. The default-page synthesizer fills in every slot you didn't override.

For "I love the default page but want to customize just the header," slotted pages are the right tool.

Slot menu (v1)

SlotReplaces
headerpage:header
actionsrecord:quick_actions (the action bar)
highlightsThe chips + chevron path strip
detailsThe Details tab body (other tabs stay synthesized)
tabsThe entire page:tabs node — use to add or reorder tabs (wins over details)
discussionrecord:discussion (the inline conversation footer)

Each slot accepts a single component schema or an array (arrays are flattened in place). Each slot is a full replacement at the slot boundary — there is no deep-merge or JSON-Patch in v1.

Example: customize only the header

import type { Page } from '@objectstack/spec/ui';

export const AccountDetailPage: Page = {
  name: 'account_detail_page',
  label: 'Account Detail',
  type: 'record',
  object: 'account',
  kind: 'slotted',
  regions: [], // slotted pages don't author regions
  slots: {
    header: {
      type: 'page:header',
      id: 'account_header_slotted',
      properties: {
        title: '{name}',
        subtitle: '{industry} · {type}',
        eyebrow: 'ACCOUNT',
        icon: 'building-2',
        breadcrumb: true,
      },
    },
  },
};

Result: the account record page renders with your custom header, and the synthesizer fills in the highlights, tabs (Details / Related / History), and discussion regions as if you'd authored nothing else.

Composing default + custom

When you want "the default actions plus one custom button," you have to replace the whole actions slot — there's no append/insert operation in v1. To avoid copying the synthesizer's internals, @object-ui/plugin-detail exports the sub-builders the synthesizer uses internally:

import {
  buildDefaultHeader,
  buildDefaultActions,
  buildDefaultHighlights,
  buildDefaultDetails,
  buildDefaultTabs,
  buildDefaultDiscussion,
} from '@object-ui/plugin-detail';

You can call them with the object definition (and any options you'd normally pass to buildDefaultPageSchema) and spread the result into your slot override.

When to use slotted vs full

  • Slotted — customizing 1–2 regions of an otherwise standard detail page. Most "I want a fancier header" / "add a banner" / "swap the Details layout" requests.
  • Full — building a record page that doesn't look like the default at all (e.g. a multi-column dashboard-style record). Author every region yourself.

The two modes are mutually exclusive: a page either has kind: "full" (default) and uses regions[], or kind: "slotted" and uses slots.

Disabling the synthesizer entirely

The default-page synthesizer is on by default. To fall back to the legacy DetailView monolith for an object (typically for debugging a regression), set objectDef.detail.renderViaSchema = false, or pass ?renderViaSchema=0 in the URL.

On this page