Skip to main content

Templates and Sections

A LaunchMyStore page is a template that composes sections, each of which composes blocks. Templates declare composition in JSON, sections provide reusable rendering units with their own schema, and blocks layer per-instance configuration on top. This page explains:
  1. How JSON templates declare page composition.
  2. How template resolution picks the right file for a URL.
  3. How sections are reused across templates.
  4. How block-level configuration is layered on top.
  5. How section groups turn the header / footer into editable units.
  6. How the legacy .liquid / .aqua template fallback works.

Anatomy of a JSON template

A JSON template is a manifest. It lists the sections to render and their display order. The renderer reads it once, looks up each section’s Aqua source from sections/<type>.aqua, merges the merchant’s settings, and emits HTML.

Required keys

KeyTypeRequiredDescription
sectionsobjectYesMap of section_id → section instance.
orderarrayYesRender order. Items must be keys in sections.
layoutstring | falseNoOverride the layout ("layout":"password" or false).
wrapperstringNoOptional wrapper element override.

Section instance

KeyTypeDescription
typestringFilename of the section template under sections/ (no extension).
settingsobjectMerchant values for the section’s schema settings.
blocksobjectMap of block_id → block instance.
block_orderarrayBlock render order.
disabledboolIf true, the section is skipped at render.
custom_cssstringOptional per-instance CSS injected with a scoped data attribute.

Block instance

KeyTypeDescription
typestringBlock type as declared in the section’s schema blocks array.
settingsobjectMerchant values for the block’s settings.
staticboolMarks the block as fixed — merchants can’t remove or reorder it.
namestringDisplay name in the editor (supports t: translations).
blocksobjectNested blocks (for blocks that themselves render blocks).

Template resolution

When a request hits a URL, the renderer picks a template file by the following rules, in order. The first one that exists wins. For /products/<handle> where the product has template_suffix: "alternate":
  1. templates/product.alternate.json
  2. templates/product.alternate.aqua
  3. templates/product.alternate.liquid
  4. templates/product.json
  5. templates/product.aqua
  6. templates/product.liquid
  7. — fail with 500 —
For URL patterns where the handle itself is a template suffix (page and customers/*), the lookup is even simpler:
Template resolution is fully cached — after the first request there is no per-request lookup cost.

Selecting a template suffix

Merchants can attach a per-resource template suffix through:
  • The product / page / collection / blog / article admin form (template_suffix column on the resource).
  • The URL query parameter ?view=<suffix>, primarily used for AJAX section fetches.

Layout override per template

A JSON template can override the layout that wraps it:
"layout": false disables the layout entirely — the rendered body becomes the response. See Layouts for details.

How a section renders

Take this snippet from a JSON template:
The renderer:
  1. Opens sections/featured-collection.aqua.
  2. Reads its {% schema %} block (parsed once and cached).
  3. Builds a section object exposing section.id = "main", section.settings = { ... }, section.blocks = [...].
  4. Strips the schema block from the source.
  5. Compiles and renders the remaining template with section in scope.
Inside the section template:
section.lms_attributes emits data-section-id="main" data-section-type="featured-collection" for the editor.

Blocks inside sections

Blocks layer over sections. A section’s schema declares which block types it accepts; the JSON template instance picks values per block and lists them in block_order.

Section schema declaration

{ "type": "@app" } reserves a slot for any storefront block installed by an app extension.

Rendering blocks

section.blocks is the ordered iterator (matches block_order). Looking up by id (section.blocks['title']) is also supported.

Static blocks

A block instance with "static": true is locked — merchants can’t move, duplicate, or delete it in the editor, and it always renders at its declared position. Use this for blocks that are structurally required (the product title on a product page, for example):
Private block types (prefixed with _) combined with "static": true is the canonical way to ship “fixed” elements that the merchant can still configure but can’t remove.

Section reuse across templates

Sections are theme-wide. The same featured-collection.aqua file can appear in index.json, collection.json, and page.welcome.json, each with different settings.
The renderer doesn’t deduplicate — each instance gets its own compiled context and its own DOM subtree.

Restricting section availability

A section’s schema can opt out of certain templates via enabled_on / disabled_on:
The editor uses these to filter the “Add section” picker. The renderer will still execute a section that ended up on a disallowed template — these restrictions are advisory, not enforced.

Section groups

A section group is an ordered list of sections that travel together, declared as a JSON manifest under sections/. Most themes have at least header-group.json and footer-group.json.
The shape is identical to a JSON template, with an added type (the group name) and name (label shown in the editor).

The {% sections '<group>' %} tag

To render a group, use the sections tag from any Liquid/Aqua context — usually the layout:
The tag loads sections/<name>-group.json, then iterates the order array and renders each section in turn, just like a JSON template.
{% sections '...' %} (plural) renders a group. {% section '...' %} (singular, legacy) renders a single static section file. Most themes prefer the group form because it gives merchants a single-button entry to reorder header/footer elements in the editor.
You can ship any group your theme needs:
  • sections/overlay-group.json — global modals, cart drawers, search popups.
  • sections/aside-group.json — sidebar widgets for collection pages.
  • sections/popups-group.json — newsletter / age gate / cookie banner.
Reference them with {% sections 'overlay-group' %} in the layout. The editor surfaces each group as a separately-editable region.

Liquid template fallback

For pages that don’t fit the JSON model, a theme can ship a plain .aqua / .liquid template that is the whole page body:
The renderer:
  1. Detects {% layout '<name>' %} if present and switches the wrapper layout (layout/<name>.aqua).
  2. Detects {% layout none %} and renders the file body without any layout — useful for AJAX endpoints.
  3. Compiles the file once and renders with the page’s global object in scope (e.g. gift_card for templates/gift_card.aqua).
You can mix forms within one theme: keep index.json as a section composition but render gift_card.aqua as a single-file template.

Worked example: product.json

A minimal product page:
Rendered against the URL /products/blue-shirt:
  1. The renderer resolves templates/product.json.
  2. Fetches the product (handle blue-shirt) and exposes it as product.
  3. Renders sections in order: mainrelatedrecently_viewed.
  4. main is product-information.aqua with the schema-driven blocks above; the section’s loop renders title → price → variant → buy → description.
  5. The result is concatenated as content_for_layout and wrapped in layout/theme.aqua.
The same product-information section file is reused on templates/product.alternate.json with different settings and a different block order — no duplication of the section’s HTML or schema.

Patterns

Per-handle landing pages

For /pages/about, ship templates/page.about.json with custom sections. The default page.json still handles every other page.

Themed collection pages

Add templates/collection.featured.json with a different hero and filtering UI, then let merchants set template_suffix = "featured" on selected collections.

Section sharing between template types

Define sections/newsletter.aqua once and reference it from index.json, page.json, cart.json, and footer-group.json. Merchants edit each instance independently.

AJAX section fetches

/products/<handle>?section_id=related returns just that section’s HTML. Middleware intercepts and rewrites to /api/themes/render-section. Use this for “Load more” / “Quick view” / cart drawer updates without a full page navigation.

Next steps

Schema

Define a section’s settings, blocks, and presets.

Input settings

Every available input type for schemas.

Layouts

Wrap the rendered body in HTML.

Tags

{% section %}, {% sections %}, {% render %}, and friends.