Section Slots
Do It With a Skill
use-section-slot carves a slot into a section that is already designed, so template authors can drop components into a named placeholder without unlocking the surrounding layout.
curl -fsSL https://studio-documentation.contentstackapps.com/install.sh | sh
Slot vs Section Slot: Two Authoring Layers
Studio has two kinds of drop targets, and they open at different authoring layers. Mixing them up is the single most common cause of “I can’t drop this here.”
| Component Slot | Section Slot | |
|---|---|---|
| Declared in | Component code (registerComponent schema, a slot prop) | The section’s ui tree (a section-slot node inside the design) |
| Filled at | Section authoring: the section author drops other components into it | Template authoring: the template author drops components or sections into it |
| Frozen when | The section is saved: whatever’s in the component slot at that moment is locked into the section | Never. Every template instance can fill the slot differently |
| Use it to | Compose a component’s own structure inside a section (put a Button inside a Hero’s children) | Leave a region of the section variable so each template that drops the section decides its content |
Default to component slots. Most swap-ability in a design should live at the component layer: the Section author fills it, every Section that uses the component inherits it, no extra rung of indirection. Only escalate to a Section Slot when the fill decision genuinely belongs to the Template author (per-Template variation the Section author can’t lock in). If you’re reaching for a Section Slot to handle a decision the Section author would happily make once, the Component Slot was the right tool.
The rule that follows: exposing only a component slot is limited to section authoring. The template author can’t touch it. So a Section Slot is needed precisely when you’ve concluded the Template must decide.
The two chain: a component slot in the section’s design can hold a Section Slot. That’s exactly what the Hero Strip example below does. The Hero component declares a children component slot. The section author drops a Section Slot into that children, and the template author fills the Section Slot per instance. Slot inside slot, each at its own authoring layer.
Sections Are Compound Components: Section Slots + Exposed Props Give Them the Shape
Think of a section as a compound component built in Studio. It wraps registered components with layout, bindings, and data scope, and exposes a contract to whoever drops it. That contract has exactly two levers, the same two a code component has:
| Code component surface | Section equivalent | What the template author gets to decide |
|---|---|---|
| Props (title, href, tone, …) | Exposed Section Props | Which values are overridable per instance |
| Slot / children props (<Card><Card.Header>…</Card.Header></Card>) | Section Slots (this page) | Which regions are droppable per instance |
Everything else (the layout containers, the bindings to the linked schema, the internal component wiring) is locked-in section structure. Exposed Props decide what the template author can change. Section Slots decide what they can drop into. Design a section by asking those two questions and picking the right primitive for each.
The Primitive
Section Slot is the third Smart Container (alongside Repeater and Condition Block), but it sits at a different layer: instead of binding to data, it carves an editable placeholder the next composer fills.
A Section Slot is a named placeholder carved out of a section the section author has already designed. The section author builds the structure (layout containers, headings, decorative elements, repeaters) and decides which regions should remain open for template authors to fill. Those regions become Section Slots.
You don’t build a section that is just a Section Slot. A slot only makes sense inside something: a card frame the section already drew, a row in a grid the section already laid out, an “item template” position inside a Repeater the section already bound. The slot is the opening in a designed structure, not the structure itself.
Slots are chainable and recursive: a slot can hold a slotful section, whose slots can hold more sections, all the way down.
Slot vs Prop: When to Use Which
| Section Slot | Expose as Section Prop | |
|---|---|---|
| Exposes | A placeholder in the layout | A value on an existing component |
| Filled with | Any component or section | A literal value, or bound page data |
| Chainable / recursive? | Yes | No, a single value override |
In short: slots expose a placeholder, props expose a value.
- Page authors should drop something: use a slot.
- Page authors should change something already there: use an exposed prop.
A well-designed section often uses both: slots for the variable regions, exposed props for labels and flags.
Authoring a Section With Slots
The Section Slot tile lives in the Smart Containers category of the palette while you’re in section authoring mode (it’s hidden in page editing). But you don’t reach for it first. You reach for it after the section’s shape exists.
The real authoring flow:
- Build the section’s structure first. Layout containers (Box, Row, Grid), bindings to your section’s linked schema, anything that’s fixed about the design: the card frame, the grid wrapper, the heading row, the call-to-action region styling.
- Identify what’s variable per template instance. Look at the structure and ask: “what here should template authors decide instead of me?” The answer is usually one or two regions: the card’s media, the row’s CTA, the panel’s body content.
- Drop a Section Slot into each of those regions. The slot replaces the variable content. The surrounding structure stays.
- Label each slot via the right panel’s Drop placeholder label field: “Drop a card here”, “Media”, “CTA”. This label is what the template author sees on the canvas. It’s the only contract between section author and template author for that placeholder, so make it instructive.
- Save the section.
The order matters. If you drop a Section Slot at the top of an empty section, you’ve made a section that is just a placeholder: there’s no design to wrap the placeholders, no reason for a template author to use this section over dropping the component directly. The value of a slot only exists when there’s section design around it worth preserving across template-instance variations.
What the slot looks like to the page author depends on the label. A slot labeled “Drop a card here” renders as a dashed rectangle saying Drop a card here on the template canvas, waiting for a component or section to be dropped in.
Here’s a Hero Strip section actually built this way: a Hero component owns the headline + subhead (bound to the linked schema’s entry.hero.* fields), and exposes a children slot prop. Inside that slot, the section author drops a Section Slot, the only per-template-instance variation point. Everything around it (the Hero’s layout, gradient background, typography, the linked-schema bindings) is locked-in section structure:

Notice the visual integration. The Section Slot is placed inside the Hero component’s children slot prop (a slot-typed prop the component itself declares, see Component schema: slot). That places the dashed drop target inside the Hero’s frame, surrounded by the Hero’s gradient + spacing.
If the Section Slot were instead a sibling of the Hero at the page root level (page > [Hero, SectionSlot]) the slot would render below the Hero as a disconnected block. The chain from the component’s slot prop to the Section Slot inside it is what makes the slot read as “part of” the section rather than a separate region.
This is the canonical pattern: a registered component declares slot props for variable regions. A section composition places Section Slots inside those slot props. Templates fill the Section Slots with concrete content via drag-drop.
Filling a Slot on a Page
When the section is dropped onto a page, each slot becomes a drop target with its label visible. Drop any component into it.
The slot’s filled content lives on the page, not on the section. So the same section dropped twice on a page can have completely different slot contents in each instance.
Bindings inside the slot content inherit the data context surrounding the slot. If the slot is inside a Repeater, the slot’s children see the current iteration item.
Why Slots Are Powerful: the List + Slot Pattern
The pattern that comes up most often: a section that owns the layout of a list but lets the page decide what each item looks like.
![card_grid section linked to gf_card_list: Box configured as a grid wraps a Repeater bound to template.items[] holding a Section Slot labeled Item template](../assets/diagrams/containers-section-slot-list-pattern.png)
The Global Field that defines the iteration source:
![Two stacked global field schemas (gf_card_list with heading and items[] repeater on top, gf_card with title, image, link below) connected by an arrow showing items[] iterates each gf_card](../assets/diagrams/containers-section-slot-card-list-schema.png)
On a page, drop card_grid and it auto-binds to any gf_card_list field. The slot inside the Repeater renders once as a drop target. Drop a card component into it. At render time, the slot’s contents repeat for every item in the list.
The Full Chain: Sections Inside Slots
The real power: drop a slotful section inside another section’s slot.
Build a card section with four slots:

Then on a page:
- Drop card_grid, which auto-binds to featured_products. One “Item template” slot appears.
- Drop card into that slot. Studio scope-root matches it against the iteration item, no manual binding.
- card‘s four named slots appear. Fill each with a real component.

You have three independent layers of reuse: card_grid owns the grid, card owns the card frame, leaf components own the visuals. Change any layer without touching the others.
What It Feels Like to Author With Slots
Three things are worth knowing: they explain why slots compose the way they do and where the limits are.
Slots only fill on a template, not in the section itself. When you’re authoring the section itself, the Section Slot tile renders as a labeled placeholder you can’t drop into. That’s intentional. Slot fills are decisions the template author makes per drop site, so they don’t make sense inside the section’s own canvas. The moment that section is dropped onto a template, the slot becomes a live drop target labeled with whatever placeholder text you set, ready to accept any component or section the template author drags in.
Slot fills belong to the template, not the section. When a template author drops a card into a section’s slot, the card is stored on the template composition, not on the section. Drop the same section onto two different templates and each instance has its own slot contents. Edit the section later and existing slot fills aren’t affected. You can rename the slot’s placeholder label, reorganize the section’s design, and the template-side fills stay intact. (Delete the slot entirely and its fills become orphaned. Studio cleans them up on the next template save.)
Anything can fill a slot, unless you restrict it. By default the slot doesn’t say “only accept sections of type X” or “only images here”. Any registered component or any section can be dropped, and the label you give the slot is the only hint the template author has about what fits, so use it to communicate intent: “Drop a card here” / “Media” / “CTA” / “Article body”. If you do want to constrain the slot (restrict which sections drop in, or pre-fill an empty slot with a default section), see Slot Defaults & Allowed Sections.
What data does a section see when it’s dropped into another section’s slot?
This is the part that surprises people. When Section B is dropped into Section A’s slot, the data scope flows in from outside, layer by layer:
- B’s template.* is A’s scope, not the template’s own. If A is bound to the template’s featured_card field, B’s inner bindings resolve inside that field. B’s own linked schema auto-binding matches against A’s scope (the featured_card group), not the template’s connected content type. So a card section dropped into a featured-card section’s slot binds to the card-shape inside the featured-card scope.
- B inherits any Repeater scopes around it. If A is inside a Repeater, or A’s slot is inside a Repeater inside A, B sees the current iteration item exactly as A would. The card section dropped inside a card-grid’s iteration slot binds to the current iteration’s card data.
- B can always reach the page entry as an explicit choice. If B genuinely needs the page-level entry (e.g. the page’s brand_color), the Data Picker offers the page scope as an option and it always points at the outermost page entry, no matter how many slots deep B is nested.
Why this matters for design
The combination (slot fills live on the template, scope flows in from the enclosing section, and the template’s connected entry is always reachable as a choice) is what lets the List + Slot pattern work without any per-section glue. The Repeater scopes each iteration to an item. The Section Slot inside the Repeater inherits that scope. Any section dropped into the slot auto-binds against the item. The section’s leaf components read the right fields. No wiring, no fork. The pattern is the direct consequence of slots being scope-pass-through openings.
Variants of the Pattern
| Section | Wrapper | Slot(s) |
|---|---|---|
| Tabs | Repeater over tabs[] | “Tab content” |
| Accordion | Repeater over panels[] | “Panel body” |
| Carousel | Repeater over slides[] | “Slide content” |
| Two-column layout | No Repeater | “Left”, “Right” |
| Hero with CTA | No Repeater | “Headline”, “Subhead”, “CTA” |
Edge Cases
| Scenario | What happens |
|---|---|
| Rename a slot’s label | Existing filled children stay bound. Empty slots show the new label. |
| Delete a slot | Page composers see no placeholder. Next page save cleans up orphaned slot contents. |
| Move a section into a Repeater after slots are filled | Children travel with it. Bindings re-resolve under the new iteration. |
| Same section dropped multiple times | Each instance has its own slot contents. |
| Section deleted from the catalog | The page shows “unknown section” but preserves filled children, no data loss. |
Next
- Slot Defaults & Allowed Sections: pre-fill an empty slot and restrict what drops in
- Expose Section Props: the value-level sibling
- Auto-binding: scope-root matching that makes nested sections “just work”
- Recipe: card grid with slots
- Slot data: for a component’s own slot props, carry data to dropped children with <Slot data={...}>