Building sections
Adding a section
Two files, no registry to update.
Two files in one folder, named the same:
src/liquid/sections/js/my-thing/├── my-thing.liquid ← markup + JSON payload + schema└── my-thing.jsx ← default export, receives the JSON as propsThe .liquid file renders the mount point through the shared snippet:
1{% render 'react-section', component: 'my-thing', section: section %}23{% schema %}4{ "name": "My thing", "settings": [], "presets": [{ "name": "My thing" }] }5{% endschema %}And the component receives the payload as props:
1export default function MyThing({ id, settings, blocks }) {2 return <div className="page-container py-12">{settings.heading}</div>3}No registry to update — the build generates it. The filename is the lookup key,
so my-thing.jsx answers to component: 'my-thing'.
What arrives as props
Every section gets the payload built by snippets/json--section.liquid:
| Prop | |
|---|---|
id | The section id. Needed by useSectionState and useCarousel |
settings | The section's settings, keyed by their schema ids |
blocks | Array of { id, type, settings, shopify_attributes } |
| resources | Anything opted into with a with_* parameter |
Settings arrive under their schema ids, which are snake_case, so destructure with a rename where you want camelCase:
const { slide_height: slideHeight = 'large', autoplay = false } = settingsOpting into Shopify data
A section gets a product, collection or menu by asking for it:
1{% render 'react-section', component: 'main-product', section: section,2 with_product: product %}The with_ prefix is deliberate. {% render %} gets a clean scope, but global
objects still reach it — so a plain product parameter would silently populate
on product templates and nowhere else. Prefixing means a resource is included
only when you asked for it, and payload size stays something you control.
See Data serializers for every available resource and the tuning parameters that keep the payload small.
Schemas are yours
The framework never generates, derives or centralises a {% schema %} block.
Each section writes its own, with whatever settings, blocks, visible_if
conditions and presets that section actually needs. That freedom is the point of
the theme — a generator could only ever emit what it anticipated.
If the section is interactive
Read Theme editor before you start. A React section that ignores the editor works perfectly right up until a merchant edits the thing they just selected, and then appears broken.