Studio Docs

When to Use

The pitfall table for authoring a Section: what fails silently on the canvas, why, and the fix. Read before reporting a Section done.

Part of the Section-authoring set. Start at build-section.

Common Pitfalls

PitfallWhy it bitesFix
Trying to link the section to a scalar field (title, description, image)Studio’s picker doesn’t offer scalar fields: a section composes UI against a shape, not a valuePick the parent Group / Global Field / CT / Block. Expose individual props later via Expose Section Prop
Linking to a multi-variant schema without dropping a RepeaterSection composes against the whole list as one shape. Renders only the first item or fails to bindWhen isMultiple=y, drop a Repeater bound to the array path and place components inside it
Picking Modular Block instead of a specific Block typeBindings are typed against the union of block shapes: most fields don’t resolveIf the section is for one block type, pick block and select that specific block. If the section handles many, use Repeater + Condition Block per block type
Skipping Connect A SchemaSection is static-only. Won’t auto-bind on templates. Authors wire every value by handPick a structural schema. Only skip when you know the section is purely presentational
Binding a prop to a field that isn’t in the Data Picker (forcing a path, keeping a stale binding to a removed field)The bind resolves to undefined at runtime, so the component falls back to its registration defaultValue. The canvas shows plausible-looking placeholder content, so the break is invisible until production renders empty.Field-existence gate (Step 5d): only bind fields the picker offers. When the field is missing, fix the linked schema or the CT (migrate-ct-schema). Never force the bind.
A whole-array/object component prop with no multi-valued field on the CT (e.g. Article Grid bound to articles on a CT that has no articles reference)Nothing to bind the collection to, so the component renders its default array forever (ARTICLE ONE / TWO / THREE). Looks like it “works” in Design Mode.Collection-source gate (Step 5e): add the multi-Reference / Modular Block / multiple Group, or pin a query, or decompose to Repeater + atomic child Section (build-repeating-section).
Reading Design-Mode placeholder as real bound dataDesign Mode renders registerComponent defaults. A broken bind and a working bind look identical there. Ship it and production is empty.Always verify in Preview Mode (Step 5f). If Preview still shows the generic defaults, the bind didn’t resolve. Re-check field existence + source.
Dropping Studio default components instead of Registered ComponentsNo brand consistency. Section ignores the project’s component librarySwitch palette category to Registered Components before dragging
Skipping the Expose Props step on SaveTemplate authors get a locked section, no value overrides possibleToggle the props that should be overridable in the Expose Props modal
Assuming the Section is broken because the canvas shows defaults, not CMS valuesDesign Mode renders registration defaults. Preview Mode renders real bindings. See use-repeater for the two-mode model.Toggle Preview Mode in Properties, then Configuration.
Binding inside a Repeater without a Condition Block on references / modular blocksIteration items are polymorphic. Bindings silently failWrap with Condition Block (single-CT references included)
Picking from the Section’s linked-schema root for a prop that sits inside a RepeaterWrong scope: every iteration shows the same value (the parent’s field), not the per-item valueInside a Repeater, the Data Picker switches to the iteration item’s fields automatically. Bind from that root
Naming the section “Section 1” / “New Section”Authors cannot tell sections apart in the paletteUse an intent-revealing name like Hero Strip, Card Grid, Testimonial Card
Dropping a Rows / Box wrapper before the first real componentLeaves a visible “Drop Here” placeholder zone in the canvas (and in every screenshot) that authors must clean up later. Rows is an e2e-test scaffolding habit, NOT a Studio authoring pattern.Drop the first component directly onto the canvas root slot. Wrap in a container ONLY when you need explicit layout (e.g. an hstack to put two cards side-by-side).
Adding a Repeater for a single, non-list use caseRepeater iterates a multi-valued field. A static page with one Hero + one Product Card needs zero iteration. Adding one introduces a phantom iteration scope and shifts the Data Picker so the parent Section’s fields aren’t reachable from inside.Use Repeater ONLY when the linked field is genuinely a list (Modular Block list, multi-Group, multi-Reference, multi-entry pinned query). For a single hero or single card: drop the component directly.
Path A when the card visual may be reused elsewhereLocks the card into one parent. Reuse contexts drift out of syncDefault to Path B (see § Path A vs Path B).
Slot inside Repeater without a sized layout containerChild stretches full canvas widthWrap in grid/flex/max-width Box. See use-section-slot § Layout container.
Leaving empty “Drop Here” zones at the bottom of the canvasSaved compositions render those zones as visible placeholders in screenshots and to authors browsing the section gallery.Before Save, switch to Layers and delete any orphan empty Box / Slot rows. Acceptance: the Layers tree contains ONLY the components you intended. No orphan structural wrappers remain.
Typing a Tailwind (or any scanned-utility) class into the Design panel and seeing no effect: the class is on the element in DevTools with no rule behind itTailwind emits CSS only for classes it finds while scanning source files. A composition is JSON in Contentstack, not a file in the repo, so a class that exists only in the Design panel is never generated. Identical symptom to a typo’d class name.Keep load-bearing utilities in source: put the layout on a registered component, or list the class in Tailwind’s safelist so it is always emitted. Reach for the Design panel for values the design system already ships.
Assigning a CSS class to a Basic box and expecting display: flex/grid to apply: the box renders but the children stack vertically (no flex) or single-column (no grid).The Basic Box component is just <div {...rest} {...studioAttributes}>. Studio renders box layout from the node’s styles.default.responsiveStyles.default (set via the Design panel on the node) and surfaces it through the renderer’s style pipeline. An external CSS class on the app side has no node-level styles to attach to and only applies whatever rules its stylesheet defines. It does NOT make Studio’s renderer emit display: flex.Author Basic-box layout via node responsiveStyles in the Design panel: select the Box, open the Design tab, then set display, gap, alignItems, flexDirection, etc. The renderer writes these into the DOM. Reach for a CSS class only for tokens/colors/typography already wired through your design system, never for the load-bearing layout shape. (Custom registered components are different: they can apply layout via their own React/CSS.)