Templates & Global Surfaces#
A section defines WHAT can render; a template defines what a page STARTS as. Each templates/<page_type>.json file in the bundle is an ordered list of section instances — type, position, settings, and (for block-capable sections) explicit starting blocks with stable ids you choose.
{
"page_type": "home",
"sections": [
{ "type": "hero", "position": 1, "settings": {} },
{ "type": "featured-products", "position": 2, "settings": {} },
{ "type": "marquee", "position": 3, "settings": {
"blocks": [
{"id": "home-marquee__block_0", "type": "word", "settings": {}}
]
}}
]
}
Empty settings ({}) are correct in templates: schema setting defaults materialize per-section at install. Set explicit values only where the template's composition differs from the schema default.
Page types#
Alternate templates#
A theme can ship more than one look for the same surface. Name the file
// templates/page__contact.json — the base page plus a contact form
{
"page_type": "page__contact",
"name": "Contact",
"sections": [
{ "type": "content-page", "position": 0, "settings": {} },
{ "type": "contact", "position": 1, "settings": {} }
]
}
Merchants assign templates per resource: a Page, a product, or a blog post carries a template handle, chosen in its admin form. A resource with no handle renders the base template. If the active theme has no template matching a resource's handle — a theme switch, say — the platform falls back to the base template explicitly, so a configured page never renders blank.
This is how contact pages work end to end: the merchant writes an ordinary Page, assigns the Contact template, and the template's contact section carries the contact_submit form. Nothing about contact is a special page type — the Page provides the words, the template provides the form.
Standard surface keys: home, shop, product, collection, collection_list, category, category_list, page, policy, blog, blog_list, blog_category, vendor, vendor_list, brand, brand_list, search, cart, wishlist, account, login, register, not_found — plus store-state pages (coming_soon, maintenance, password) and the global surfaces below. Alternate templates (product__summer) use the double-underscore suffix.
Global surfaces#
Four surfaces render on EVERY page around the page template: global_body_start (header, announcement), global_body_end (footer), global_overlay (drawers, popups, localization prompt), and the head surfaces (global_head, global_compliance_head). They are compositions like any other — sections, blocks, settings — but they are edited ONCE and apply everywhere.
Surface |
Renders |
Typical sections |
|---|---|---|
global_body_start |
Opening of , before the page template |
announcement bar, header |
global_body_end |
End of , after the page template |
footer |
global_overlay |
Above everything, portal layer |
cart drawer, localization prompt, popups |
global_head / global_compliance_head |
Inside |
meta/custom-code sections |
Per-template overrides of a global#
Editing a global section from the Global Sections view changes it EVERYWHERE. Editing the same section while a specific template is open materializes a per-template OVERRIDE: that template gets its own copy; every other page keeps the theme default. Resetting the override deletes the copy and the template falls back to inheriting the global again. Themes do not declare any of this — it is platform behavior over the same sections.
Visibility is the template's lever, not duplication: a template can hide a global section (disabled on the override) rather than shipping a second variant of it. One footer, overridden where a landing page needs it quieter — never two footer sections.