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.liquidmarkup + JSON payload + schema
└── my-thing.jsxdefault export, receives the JSON as props

The .liquid file renders the mount point through the shared snippet:

1{% render 'react-section', component: 'my-thing', section: section %}
2
3{% 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
idThe section id. Needed by useSectionState and useCarousel
settingsThe section's settings, keyed by their schema ids
blocksArray of { id, type, settings, shopify_attributes }
resourcesAnything 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 } = settings

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