Sections and blocks
How you split a page into sections and blocks decides how much a seller can change without touching code.
Pick the right granularity
A section should be one meaningful area of a page: a slideshow, a featured collection, a FAQ list. Split further and sellers spend their time reassembling a page that should have arrived whole; split less and they can't reorder or remove the parts they don't want.
Use blocks for the repeating items inside a section, and only when the count is genuinely variable. A slideshow's slides are blocks. A product card's price and title are not; they belong to the section's markup, driven by settings.
"blocks": [
{ "type": "slide", "label": "t:sections.slideshow.slide", "limit": 8, "settings": [] }
]Choose where a section is rendered
- In a JSON template when sellers should be able to add, remove, and reorder it, or place it more than once with different settings.
- Statically with
{% section %}when it belongs on every page and its position is fixed. Headers, footers, and announcement bars belong here.
Static sections read their data from config/settings_data.json and share one configuration everywhere, so don't use them for anything a seller would want to vary per page.
Constrain what you expose
Use the section schema to keep configurations sane:
templatesrestricts a section to the pages it makes sense on, instead of letting it be added to the cart page by accident.limitcaps how many times a section can be added to one template.max_blocksand per-blocklimitkeep a carousel from becoming forty slides.
{
"label": "t:sections.featured_collection.label",
"templates": ["index", "collection"],
"limit": 2,
"max_blocks": 8
}Give settings good defaults
A section dropped onto a page should look finished before the seller touches it. Set a default on every setting that has a reasonable one, and render a placeholder when a picker is still empty:
{% if section.settings.image.src %}
<img src="{{ section.settings.image.src }}" alt="{{ section.settings.image.alt }}">
{% else %}
{% render 'misc.image-fallback' %}
{% endif %}Do the same for blocks. A section with no blocks yet should still render something the seller can see and click.
Keep section files readable
Move a block's markup into its own snippet once it grows past a handful of lines, one snippet per block type, named block.<type>.liquid:
{% for slide in section.blocks %}
{% render 'block.slide' %}
{% endfor %}The section file then reads as a layout of its parts rather than a wall of markup.
Name things for the seller
label is what a seller reads in the editor, not what you call the file. Use t: locale keys so those names translate, and keep them concrete: "Slide", "Collection", "Call to action".
{ "type": "cta", "label": "t:common.headers.button" }