Sections & blocks
Merchant-composable content around a protected commerce core, with mixed-type blocks and presets.
Sections let a merchant compose the content of a template — add, remove, reorder, and configure them — without touching code. Cartisto’s model is deliberately commerce-safe: merchants compose content around a protected commerce core.
The model
- Each composable template (
product,collection,cart) has one protected commerce core the merchant can’t remove or reorder — the product buy-box, the cart summary, and so on. - Around the core are content zones (above / below) where the merchant places content sections — testimonials, FAQ, banners, newsletter, and the like.
- The invariant is enforced in the render pipeline, not the UI, so no path (customizer, API, or AI tools) can drop or tamper with the core.
The homepage (index) is pure content — it has no core.
Rendering sections
The platform resolves each section instance and hands you its full partial path
on section.partial — you never build the path yourself. Render it directly:
{% for section in theme.templateSections.index %}
{% if section.display %}
{% render section.partial, component: section, sindex: forloop.index %}
{% endif %}
{% endfor %}
Section partials live at views/sections/<path>.liquid. Because the platform owns
path resolution, that location can change in a future SDK version without editing
a single theme — so always render section.partial, never a hardcoded folder.
Product content zones render above and below the core, and the core’s info column
is a list of platform blocks you render from block.partial:
{% for section in theme.templateSections.product.above %}
{% render section.partial, component: section, product: product %}
{% endfor %}
<div class="pdp-info">
{% for block in theme.templateSections.product.coreBlocks %}
{% render block.partial, block: block, product: product %}
{% endfor %}
</div>
{% for section in theme.templateSections.product.below %}
{% render section.partial, component: section, product: product %}
{% endfor %}
Each section instance carries its resolved settings (and resolved picker data —
see Dynamic sources), so one partial styles
the merchant’s chosen values.
Authoring a section type
Add the type to sections in theme.json with
a path and its settings schema, and ship the partial at views/sections/<path>.liquid.
A content section renders identically anywhere, so the same partial works in any
zone. The quality gate rejects a theme that
declares a section whose partial file is missing.
Blocks: mixed content inside one section
A content section can hold blocks — reorderable child items of different types, each with its own settings. Declare the allowed block types in the section’s catalog entry:
{
"path": "rich-columns",
"name": { "en": "Rich columns", "ar": "أعمدة" },
"settings": [{ "name": "heading", "type": "text" }],
"blocks": [
{ "type": "text", "name": { "en": "Text" }, "settings": [{ "name": "body", "type": "textarea" }] },
{ "type": "image", "name": { "en": "Image" }, "settings": [{ "name": "src", "type": "image" }], "limit": 4 }
]
}
The merchant places blocks of those types in any order; the platform validates each
block’s type and settings on save (limit caps how many of a type are allowed) and
resolves each block’s data. Render them from block.partial — one partial per block
type at views/blocks/<type>.liquid:
{% for block in component.blocks %}
{% render block.partial, block: block %}
{% endfor %}
Presets: demo content on add
Give a section a preset so it isn’t empty the moment a merchant drops it in. On a fresh add (no settings of the merchant’s own), the platform seeds the section from its preset:
{
"path": "rich-columns",
"preset": {
"settings": { "heading": "Featured" },
"blocks": [{ "type": "text", "settings": [{ "name": "body", "value": "Tell your story here." }] }]
}
}
The core is platform-defined You render the core’s markup (it’s your buy-box), but its presence, position rules, and the block types allowed inside it are platform-owned. Required core blocks (title, price, variant picker, buy buttons) can be reordered but never removed — that’s what keeps “compose your storefront” from ever meaning “remove add-to-cart.”