Theme Structure
Every LaunchMyStore theme is a folder of plain text files laid out in a fixed, Liquid-compatible directory structure. When you upload a theme ZIP, the installer unpacks it, builds a schema index, then serves it to merchants of that store. This page is the canonical reference for that directory tree.LaunchMyStore is 100% Liquid-compatible. Existing Liquid themes work as-is
when zipped and uploaded. New themes may use the
.aqua extension for
template files, but the two are interchangeable — themes can mix .liquid and
.aqua files freely.The full tree
A typical theme directory looks like this:Top-level directories
There is no
partials/, views/, or components/. Anything reusable lives
under snippets/ or blocks/. The renderer ignores any files or directories
not listed above.
assets/
The assets/ folder holds all static files that the browser fetches
directly: stylesheets, JavaScript bundles, web fonts, images, SVG icons, and
anything else that isn’t a Liquid template.
URL pattern
Each file is served at:asset_url filter, which produces a cache-busted absolute URL:
File types served
- CSS / JS: served as-is with the correct MIME type.
- Images (
.png,.jpg,.webp,.avif,.svg): served raw. For responsive images, preferimage_url/img_urlon uploaded images rather than asset images, because the platform’s image optimization only runs on uploaded resources. - Fonts (
.woff,.woff2,.ttf): served with long-lived cache headers. Reference via@font-faceor usefont_facefilter onfont_pickersettings.
Caching and versioning
Asset files are:- Read once into memory and served from a server-side cache.
- Served at the edge with
Cache-Control: public, max-age=31536000, immutableonce a content hash is appended byasset_url. - Invalidated automatically when the theme is republished — every cached file for the theme is cleared at once.
What does not go here
.liquid/.aquafiles — those belong insections/,snippets/,blocks/,templates/, orlayout/. The renderer will not pick up templates inassets/.- JSON config — that’s
config/. - Merchant-uploaded media — product images, blog post images, etc. are uploaded to LaunchMyStore’s media library, not the theme.
blocks/
Theme blocks are reusable, schema-driven content units that a merchant can
drop into any section that accepts them. They are the building blocks of the
new JSON section model.
Each file is a single Aqua/Liquid template plus an optional {% schema %}
tag.
Naming
Example
{% content_for 'blocks' %} renders the merchant’s configured children in order. See
Templates and sections for the full block
composition model.
sections/
Sections are the largest reusable unit in a theme. Each .aqua / .liquid
file under sections/ is one section that can be referenced from a JSON
template, a section group, or a layout’s {% sections '...' %} tag.
File types
A section group JSON file declares an ordered list of sections that render
together — typically the header bar, announcement bar, and meganav for the
top of every page; or the footer columns and copyright row for the bottom.
'header-group' → sections/header-group.json,
iterates order, and renders each section in turn.
Section schema
Every section file may include a{% schema %} block defining its settings,
block whitelist, presets, and template restrictions. See
Section Schema for the full reference.
The schema is parsed once at install time, cached, and reused for every
render.
snippets/
Snippets are partials — small, reusable Liquid/Aqua fragments rendered via
{% render 'name' %} or the legacy {% include 'name' %}.
with / for / inline arguments are scoped to the
snippet. Snippets have no schema — they’re pure rendering primitives.
Snippets do not have
{% schema %} blocks. If you want merchant-editable
settings, use a block (blocks/) or a section (sections/) instead.App-provided snippets
When apps are installed, theirsnippets/ directory is mounted into the
storefront’s snippet lookup path. A {% render 'app-snippet-name' %} call in
a theme will resolve to the app’s snippet if the theme doesn’t provide its
own with the same name — theme files always win over app files.
templates/
Templates define what renders for a given URL. Each template file maps to
exactly one page type.
Required templates
Customer account templates
When a store enables theme account pages, templates undertemplates/customers/ render the login, registration, account dashboard,
order detail, address book, and password reset/activation pages
(customers/login, customers/register, customers/account,
customers/order, customers/addresses, customers/activate_account,
customers/reset_password). Each can be a .json section template or a
plain .aqua / .liquid template. See
Theme Customer Accounts for the routes, forms,
and objects.
Per-handle variants
Any template can have alternate versions selected per resource. The selector is the handle, used in the URL or specified in the resource’s metadata:Resolution order
For a URL like/products/blue-shirt where the product has template: "alternate":
templates/product.alternate.json— most specific (handle + per-handle)templates/product.alternate.aqua/.liquid— alternate, Liquid formtemplates/product.json— default JSON templatetemplates/product.aqua/.liquid— default, Liquid form- Render fails if none exist.
JSON template shape
JSON templates declare a composition of sections:Liquid template fallback
A theme can also provide a plain Liquid/Aqua template (e.g.templates/gift_card.aqua). The renderer treats the whole file as one
template, evaluates it with the page’s global object in scope, and wraps
the result in the layout (unless {% layout none %} is present).
layout/
Layouts wrap the rendered page body in an HTML shell (<html>, <head>,
<body>). Every page is rendered into a layout unless explicitly bypassed.
A layout must include two magic variables:
{{ content_for_header }}— analytics, meta tags, scripts injected by the platform. Place inside<head>.{{ content_for_layout }}— the rendered template body. Place inside<body>.
config/
Holds theme-level (non-section) configuration.
settings_schema.json follows the same input-setting format as section
schemas — see Input Settings. Merchant values are
exposed in Aqua as the global {{ settings.* }}:
schema-index.json is a build artifact — do not edit by hand. The
storefront uses it to find sections and blocks by type without scanning
the filesystem on every render.
locales/
Translation files for every string the theme renders, plus every schema
label shown in the editor.
Two access patterns:
- In templates:
{{ 'foo.bar' | t }}looks up the active locale. - In schemas:
"label": "t:names.button"is resolved to the merchant’s active editor locale at install time and at render time.
metadata.json (optional)
Top-level theme metadata — name, version, author, support URL. Used by the
admin theme library and marketplace listing. Optional but recommended:
File-naming summary
What the installer does
When a merchant uploadstheme.zip:
- The ZIP is unpacked into a dedicated directory for the new theme.
- The installer scans
sections/,blocks/, andtemplates/for{% schema %}blocks and writes a flat lookup table toconfig/schema-index.json. locales/<lang>.default.jsonis flattened and merged into the index sot:keys resolve at render time.settings_data.jsonis initialized fromsettings_schema.jsondefaults if no merchant values exist.- The asset cache is warmed for the most-requested file paths.
- The theme editor (writes back to
settings_data.jsonand template JSON). - A new theme upload (creates a new
themeId, leaving the old one intact). - The theme file APIs / CLI (which also refresh the render cache).
Next steps
Templates and sections
How JSON templates compose sections and blocks.
Layouts
The
theme.aqua shell, content_for_*, and custom layouts.Locales
Translating storefront copy and schema strings.
Schema
Defining section and block settings.