Bring your own data

View as Markdown
Last updated September 14, 2026

Most compositions render against Contentstack content: a template connected to a content type, entries resolved by the SDK. But sometimes the data lives somewhere else, or you already hold it: one element of a group-field array you fetched yourself, a product record from a commerce backend, a value computed at request time.

Studio returns two ways to bring that data in without round-tripping through the CMS:

SurfaceWhat it doesUse it when
<StudioComposition />Renders a whole composition (page or standalone section) against a context object you pass in. No SDK data fetch, no hook.You already hold the data, e.g. you're looping a group array and want to render a section per element.
Slot dataAttaches data to a slot prop so the components dropped inside bind it via component_props.A component exposes a slot for authors to fill AND holds data the dropped component needs, e.g. a reusable Hero banner that owns its CTA's destination.

Both are render-time only. They live in your application code, not in the composition's saved spec. Nothing new is stored in Contentstack.

Together with the data prop covered below, that's three props, each scoped to a different part of the tree:

Click to enlarge

How they relate to the data prop

There's a third, already-documented way external data enters a composition: the data prop on <StudioComponent /> (see Component Default Data). Keep the three straight:

APIScope of the dataWho binds it
data prop on <StudioComponent />The whole composition, surfaces as the Component Default Data picker rootAuthors, in the canvas
context prop on <StudioComposition />The whole composition, placed at dataSources.template, so the composition's template bindings resolve against itAuthors (bindings are pre-set in the composition)
Slot dataOne slot's subtree, surfaces as component_props for children dropped in that slotAuthors, in the canvas, scoped to the slot

<StudioComponent /> fetches and renders a composition for a route. <StudioComposition /> renders a composition you hand it the data for. Slot data is a per-slot refinement that works inside either.

The minimum to get started

Render a section against one element you already hold:

import { StudioComposition } from "@contentstack/studio-react";

// `element` is data you fetched yourself — e.g. one item of a group array.
<StudioComposition compositionUid="hero_section" context={element} />

Attach data to a slot so whatever an author drops in can bind it:

import { Slot } from "@contentstack/studio-react";

// The Hero banner owns `ctaDestination`; the slot carries it to the dropped CTA.
<Slot data={{ destination: ctaDestination }}>{ctaSlot}</Slot>

StudioComposition