Studio Docs

Card Grid With Slots

A complete end-to-end build of the list + slot pattern: one section owns the grid layout, a second section owns the card frame with named slots, and template authors compose the cards visually on the template canvas.

This is the richest pattern Studio supports for reusable layout. Once you have it, it generalises to tabs, accordions, carousels, anything else built on “repeat this shape, but let me customize each item”.

You’ll build:

  • A gf_card_list Global Field that defines “a list of card-shaped items”
  • A gf_card Global Field that defines “what a single card looks like as data”
  • A card_grid section: the wrapper + iteration
  • A product_card section: the visual card with 4 named slots
  • A landing_page content type that uses gf_card_list for its featured products

End state: a single card_grid drop on the template, with product_card filling its slot, renders N cards with real product data.

Do It With a Skill

build-repeating-section builds the parent Repeater and Section Slot, and use-section-slot carves the slot if the section already exists.

curl -fsSL https://studio-documentation.contentstackapps.com/install.sh | sh

Step 1: Define the Global Fields in Contentstack

In your stack:

gf_card

gf_card Global Field schema, title text, image file, link, and badge text.

gf_card_list

gf_card_list Global Field schema, heading text and an items repeater of gf_card.

landing_page content type

landing_page content type with title text plus two gf_card_list fields, featured_products and related_products.

Two gf_card_list fields so we can verify Studio’s multi-match picker later.

Populate one landing_page entry with values in featured_products.items[] (5 products) and related_products.items[] (3 products).

Step 2: build the card_grid Section in Studio

  1. In Compositions, open the Sections tab and select + New Section. Name it card_grid

New Section modal where you name card_grid and pick its linked Global Field schema

  1. In the section settings, open Link Schema and pick gf_card_list (the Global Field)
  2. On the canvas, drop a Box at the root: this is the grid container. Set its CSS to a grid layout via the Design panel:
    display: grid
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr))
    gap: 24px
  3. Drop a Heading above the grid Box. Bind it to template.heading.
  4. Inside the grid Box, drop a Repeater from the Smart Containers palette. Bind its source to template.items[].
  5. Inside the Repeater, drop a Section Slot from Smart Containers. Label it Item template.
  6. Save.

Authored card_grid section on canvas, showing Heading, grid Box, Repeater wrapping a single Item template Section Slot

Layers panel for card_grid showing the Repeater containing the Section Slot, confirming the slot lives inside the iteration scope

Selecting the Repeater node surfaces its Properties panel, including the Preview Mode toggle, the Items source (here Related Posts), and the Contents descriptor showing the Condition Block child. This is where you flip Preview Mode on to see real iteration on the canvas:

Repeater node selected in Layers: right panel shows Configuration with Preview Mode toggle, Properties with Contents=Condition Block + Items=Related Posts

The section structure:

card_grid section structure. Heading bound to template.heading, grid Box wrapping a Repeater on template.items, with an Item template Section Slot inside.

Step 3: build the product_card Section

  1. In Compositions, open the Sections tab and select + New Section. Name it product_card
  2. In Link Schema, pick gf_card
  3. On the canvas, drop a Box at the root: this is the card frame. Style it: border-radius, padding, shadow.
  4. Inside the card Box, drop four Section Slots (Smart Containers palette) labeled:
    • Media
    • Title
    • Body (optional content)
    • CTA
  5. Save.

product_card section on canvas: card frame Box holding the four named Section Slots (Media, Title, Body, CTA)

Studio’s Expose Props modal opens on Save. Skip it (no props to expose yet: these are slots, not values).

The section structure:

product_card section structure, a Box card frame holding four Section Slots labeled Media, Title, Body, and CTA.

Step 4: build a connected Template against landing_page

  1. In Compositions, open the Templates tab and select + New Template. Pick landing_page
  2. Drag the card_grid section onto the canvas

Studio auto-binds: card_grid linked to gf_card_list, and landing_page has two gf_card_list fields. Multi-match: Studio binds to one of them and shows a dropdown.

  1. In the right panel for the card_grid instance, you’ll see a Linked Field dropdown with featured_products and related_products. Pick featured_products.

The Repeater inside card_grid is now iterating over the entry’s featured products. The slot inside the Repeater renders as a single drop target: Item template.

  1. Drag your product_card section onto the Item template slot.

Studio uses scope-root matching: the iteration item shape is gf_card, which matches product_card‘s linked schema. No manual binding needed. product_card is automatically bound to the current iteration item.

  1. The product_card‘s four slots now appear: Media, Title, Body, CTA. Fill them:

    • Media: drop an Image component, bind src to template.image
    • Title: drop a Heading, bind text to template.title
    • Body: leave empty (cards in gf_card don’t have body copy)
    • CTA: drop a Button, bind label to template.title (use as link text) and href to template.link
  2. Save the template.

Connected landing_page template canvas with card_grid filled by product_card, slots resolved to real entry data

Step 5: Verify the Render

Open the route on your site that matches the template’s URL pattern, for example /landing/<slug>.

You should see:

  • The page’s featured_products.heading rendered as a heading
  • 5 cards in a responsive grid, one per product entry in featured_products.items[]
  • Each card showing the entry’s image, title, and CTA

Card-grid section rendered output, a heading 'Featured products' from gf_card_list, with five product cards in a row beneath it. Each card has an image thumbnail, a title, and a CTA link.

One template, two sections, real product data, full visual control.

Back on the template canvas:

  1. Drag a second card_grid onto the template (below the first)
  2. In the right panel for this instance, the Linked Field dropdown shows the same two options. Pick related_products this time
  3. Drop a product_card into the second grid’s slot, exactly as before
  4. Fill its slots, and notice you can fill them differently than the first instance

Both card_grid instances render with their own bound list. Both product_card instances have independent slot contents. Per-instance customization: same sections, different page-level fills.

Why This Pattern is Powerful

Three independent layers of reuse:

LayerOwnsReused across
card_gridGrid layout (columns, gap, responsive) + iteration wiringAny list of gf_card_list
product_cardCard frame (border, shadow, padding) + named regionsAny gf_card iteration item
Leaf componentsThe actual visual content of each slotFilled per template instance

Change the grid’s columns once and every page that uses card_grid updates. Change the card frame’s shadow once and every card on every page updates. Change one slot’s binding on one page and only that page changes.

Variants of the Same Pattern

The List + Slot pattern works for:

SectionWrapperSlot
card_gridRepeater + grid BoxItem template
tabsRepeater over tabsTab content
accordionRepeater over panelsPanel body
carouselRepeater over slidesSlide content
two_columnNo RepeaterLeft, Right
hero_with_ctaNo RepeaterHeadline, Subhead, CTA

All built the same way: section wraps the layout, slots own the variable content, linked schemas drive auto-binding.

See Also