Skip to main content

Section slots, overrides and exposed props

This page covers the nodes and settings that connect Sections and Templates: the Section Slot, the binding override on a placed Section, and exposed props. You need it when a Template places a Section or changes a value inside one.

The examples use the Blog project: the Blog post content type, the Post hero and Related posts Sections, and the entry AI 101.

Section Slot node​

A Section Slot marks a gap in a Section that a Template fills. Studio lists the component only while you author a Section, never on a Template. The API accepts a section-slot node in a Template with no error and no warning.

{
"uid": "post_hero_byline_slot",
"type": "section-slot",
"attrs": {},
"metadata": {
"defaultSection": { "uid": "blt8888888888888888", "_content_type_uid": "compositions" },
"allowedSections": [{ "uid": "blt8888888888888888", "_content_type_uid": "compositions" }]
},
"props": {},
"slots": {},
"styles": {}
}

A Section Slot node has no slots of its own, so leave out that key. An empty array answers 422 with empty_slot.

Filling the slot from a Template​

A Template fills a Section Slot through the placed Section. Any Template can fill it, connected or freeform. The placed section-composition node keys its slots on the Section Slot node's uid, and each key holds an array of nodes of any type.

{
"uid": "post_hero_placed",
"type": "section-composition",
"attrs": {},
"metadata": { "compositionUID": "blt5555555555555555" },
"props": {},
"slots": {
"post_hero_byline_slot": [
{
"uid": "byline_placed",
"type": "section-composition",
"attrs": {},
"metadata": { "compositionUID": "blt8888888888888888" },
"props": {},
"slots": {},
"styles": {}
}
]
},
"styles": {}
}
  • When you drop a Section on a Template, Studio adds an empty array under slots for each Section Slot. The API rejects an empty array, so remove those keys before you send.
  • When you save a Template, Studio removes each slots key that names a Section Slot the Section no longer has. The API doesn't, so a leftover key stays.
  • A Section can hold several Section Slots, and each has its own uid. Studio makes a 15-character ID, and the API accepts any unique string.

The default Section and the allowed Sections​

metadata.defaultSection and metadata.allowedSections take the key objects shown above. The SDK and the API read only the uid of defaultSection.

  • An empty Section Slot shows its default Section on your site and in Studio's Preview mode. In Design mode it shows a drop zone and a Select section button. The default Section renders with no props and no slot fills.
  • A default Section that loops back to one of its ancestors renders nothing where the loop closes.
  • An empty or missing allowedSections allows any Section. Only Studio enforces the list, and only when you drop a Section into the slot. A component that isn't a Section always drops in.
  • Studio warns: "This section isn't allowed in this slot. Choose one of the slot's allowed sections, or drop a different component."
  • When the allowed list has entries, the Default section setting offers only those Sections. Changing the list to one that leaves out the default clears the default.
  • The API adds each Section Slot's defaultSection UID to linked_sections and ignores allowedSections.

The label​

The label prop has type string. Studio shows it as "Drop placeholder label". It stores the prop as a static_value binding whose key is <slot uid>-label.

{ "type": "string", "binding": { "type": "static_value", "value": "post_hero_byline_slot-label" } }

The text itself sits in the Section's static_value.text as { "key": "post_hero_byline_slot-label", "value": "Byline" }. The label shows on the empty Section Slot on the Section's own canvas, and "Drop Here" shows when it's blank. The label never renders on your site, and an empty Section Slot with no default renders nothing there.

In SEO metadata bindings, a static_value binding's value is the text itself. On a node prop, it's always a key.

Repeater context​

A Section Slot passes the Section's Repeater context to its fill, so the fill reads each item with a repeater binding. A Template Repeater around the placed Section also reaches the fill, because the Section keeps the enclosing Repeater map.

In Studio, a placed Section starts in Design mode when its Section has a Section Slot, and in Preview mode when it has none. The placed Section's metadata.mode sets the mode of its Repeaters, Condition Blocks and Section Slots in Studio. Your site ignores it.

Binding override on a placed section​

A Template places a Section with a section-composition node. Its metadata.compositionUID is the Section's entry UID, not its composable_uid.

{
"uid": "post_hero_placed",
"type": "section-composition",
"attrs": {},
"metadata": { "compositionUID": "blt5555555555555555" },
"props": {},
"slots": {},
"styles": {}
}

The create call answers with the new Section's entry uid, the value to put in compositionUID. A compositionUID that isn't a Section's entry UID shows the error "Component with type '' is not registered."

linked_sections​

You don't send linked_sections. The API ignores a value you send and fills it from ui on every write that carries ui. It holds one { "uid", "_content_type_uid" } row for each compositionUID in ui, fills inside slots included. A PUT without ui leaves the stored value as it was.

A Section gets linked_sections rows too, for the Sections it places and for each Section Slot default. Studio finds the Templates that use a Section through these rows. The API warns "ensure linked_sections references every placed section" on every write that places a Section, though it fills the field. You can ignore that warning.

Pointing the Section at other data​

A placed Section reads its data from metadata.sectionBindingOverride when it's set. Otherwise it reads the Section's linked_schemas.

{
"uid": "post_hero_placed",
"type": "section-composition",
"attrs": {},
"metadata": {
"compositionUID": "blt5555555555555555",
"sectionBindingOverride": {
"selectedField": "related_posts",
"uidRemapping": {}
}
},
"props": {},
"slots": {},
"styles": {}
}
Field of sectionBindingOverrideWhat it does
selectedFieldThe field the Section reads, starting at the data where the placed Section sits. In linked_schemas, selected_field starts at the entry. Inside a Template Repeater it narrows each item, and if it finds nothing in the item, the Section reads the whole item.
uidRemapping{ "<Section field key>": "<Template field key>" }. The SDK applies each pair at every depth. An empty or missing map leaves every key as it is.
rootBindingA template, repeater, contentstack or contentstack_queries binding that replaces the Section's own data. null renders the Section with no data. A missing rootBinding keeps the declared field. When it's present, the SDK ignores selectedField.
matchedSchemaCtThe linked_schemas entry that applies. A freeform Template needs it because it has no content type.
  • Without rootBinding, the SDK reads sectionBindingOverride.selectedField, then metadata.selectedField, then linked_schemas.
  • From linked_schemas, the SDK takes the selected_field of the entry for the Template's content type, else the first entry. It doesn't run the matching rules, so an API-placed Section reads its declared selected_field unless the node has an override.
  • Choosing a value in the Section Data row writes rootBinding, uidRemapping and sometimes matchedSchemaCt. It also sets flat metadata.selectedField and metadata.uidRemapping, for older SDKs.
  • On save, Studio writes { "selectedField", "uidRemapping" } only for a placed Section whose field or remapping differs from its linked_schemas.
  • A pinned entry or query in rootBinding stays the same in every iteration of an enclosing Repeater.
  • Each linked_schemas entry has up to four fields: content_type_uid, selected_field, display_name and cardinality. Leaving out selected_field binds the whole entry.
  • The API checks neither sectionBindingOverride nor any linked_schemas value against your content types.

Exposed section props​

A Section author can let a Template change one prop inside the Section. The exposed props are an array in sectionExposedProps on the Section root node's metadata. It isn't a node you drop.

This entry exposes the Heading Level of Post hero's Header as "Title size".

{
"uid": "post_hero_root",
"type": "page",
"attrs": {},
"metadata": {
"sectionExposedProps": [
{
"uid": "title_size",
"nodeUid": "hero_title",
"propKey": "Tag",
"displayName": "Title size",
"propType": "choice",
"bindingAtExposeTime": { "type": "choice", "value": ["h1"] }
}
]
},
"props": { "children": { "type": "slot", "slot": "root_slot" } },
"slots": {
"root_slot": [
{
"uid": "hero_title",
"type": "header",
"attrs": {},
"metadata": {},
"props": {
"text": {
"type": "plaintext",
"binding": { "type": "template", "value": { "path": { "title": {} } } }
},
"Tag": { "type": "choice", "value": ["h1"] }
},
"slots": {},
"styles": {}
}
]
},
"styles": {}
}
FieldWhat it holds
nodeUidThe uid of the node inside the Section that owns the prop.
propKeyThe prop's name on its component.
uidThe key the placed Section stores its override under. Studio builds it from the trimmed displayName, lowercased, with each run of spaces turned into _.
displayNameWhat a Template author sees under "Exposed As".
propTypeThe prop's type. It decides the control. A string or plaintext prop gets a text input. A boolean, number or datestring prop gets its own input. A choice prop gets a select, an imageurl prop an image input and an href prop a link input.
bindingAtExposeTimeThe binding the prop had when it was exposed.

Studio writes sectionExposedProps when you click Save on a Section and confirm the Expose Props dialog. A save Studio starts on its own skips the dialog and keeps the stored exposed props. The dialog lists every prop of every node in the Section except slot props, Section Slots and placed Sections. It refuses an empty name with "Display name cannot be empty" and a repeated one with "This display name is already used".

  • The API doesn't check sectionExposedProps. It accepts two entries with the same uid, and an entry with no propType and no displayName.
  • Send propType on every entry, because the SDK registers the Section's props from each uid and propType. When propType or displayName is missing, Studio uses the component's own prop type and a name made from propKey.
  • Studio copies a choice prop's options from the original component, so the Section doesn't store them.

Setting an override on the Template​

A placed Section stores each override on its own props, keyed by the exposed prop's uid, as { "type": <propType>, "binding": … }.

{
"uid": "post_hero_placed",
"type": "section-composition",
"attrs": {},
"metadata": { "compositionUID": "blt5555555555555555" },
"props": {
"title_size": {
"type": "choice",
"binding": { "type": "static_value", "value": "post_hero_placed-title_size" }
}
},
"slots": {},
"styles": {}
}

The override needs a binding. A plain value on the placed node's prop doesn't override the Section. A typed value gets its own copy on each placed Section, stored under the key <placed node uid>-<exposed prop uid>.

  • A placed Section prop with no binding falls back to the Section's own binding. A binding marked "autoSeeded": true falls back too.
  • On drop, Studio seeds an exposed prop with an autoSeeded copy of its bindingAtExposeTime, unless that binding is a static_value. For a template binding, the seed puts the Section's selected_field in front of the path.
  • A bindingAtExposeTime of type repeater stays with the Section until you rebind the prop on the Template to a source the Template can read.
  • At render the SDK builds section_exposed_overrides as { "<nodeUid>": { "<propKey>": <value> } } from the placed node's resolved props. It also holds a $<propKey> entry with the live preview tag of the Template field.
  • A prop you rebound on the Template and then cleared still overrides, so the Section's own binding doesn't come back.
  • An override for an unbound or untouched prop isn't in section_exposed_overrides.

For the editor steps, see Build sections.

For whole trees you can copy, see Section and template JSON examples.

Report a problem with this page