Card Grid with Slots

View as Markdown
Last updated July 17, 2026

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 customise 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.

Step 1: Define the Global Fields in Contentstack

In your stack:

gf_card

Click to enlarge

gf_card_list

Click to enlarge

landing_page content type

Click to enlarge

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. Compositions → Sections tab → + New Section → name it card_grid

Click to enlarge

  1. In the section settings, Link Schema → 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.

Click to enlarge

Click to enlarge

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:

Click to enlarge

The section structure:

Click to enlarge

Step 3: Build the product_card Section

  1. Compositions → Sections tab → + New Section → name it product_card
  2. 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) labelled:
  5. Media
  6. Title
  7. Body (optional content)
  8. CTA
  9. Save.

Click to enlarge

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

The section structure:

Click to enlarge

Step 4: Build a Connected Template Against landing_page

  1. Compositions → Templates tab → + 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:

  2. Media → drop an Image component, bind src to template.image

  3. Title → drop a Heading, bind text to template.title
  4. Body → leave empty (cards in gf_card don't have body copy)
  5. CTA → drop a Button, bind label to template.title (use as link text) and href to template.link

  6. Save the template.

Click to enlarge

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

Click to enlarge

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

Step 6: Drop the Same Section a Second Time for related_products

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 customisation: 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