Packaging & Sealing#
A theme ships as one zip bundle. Everything a storefront needs is inside it; nothing outside it is reachable. Once a version is SEALED it is immutable — installs copy pointers to the sealed artifact, and a fix means publishing the next version.
Bundle layout#
Path |
Contents |
|---|---|
sections/ |
One file per section: markup + {% schema %}. |
blocks/ |
Theme blocks (kind: block) — shared, composable, nestable. |
templates/<page_type>.json |
Starting composition per page type AND per global surface (these SEED installs — see Templates & Global Surfaces). |
locales/ |
Storefront dictionary per locale — every key the t filter reads. |
locales/ |
Editor label tokens per locale — fieldLabel., sectionName., fieldGroup.* (see Theme Locale Files). |
assets/… |
Images, fonts, icons — referenced only via the asset_url filter (fingerprinted CDN URLs). |
surfaces.json / tokens.json / config/… |
Surface declarations, design tokens, theme-level settings schema (color schemes live here). |
What the gate enforces#
The bundle gate compiles and validates EVERYTHING before a version can seal — the same checks run again at install, so a sealed bundle can never install into an invalid state. Rejections name the file and the rule.
Check |
Rule |
|---|---|
Template compile |
Every section and block parses; unknown tags/filters, unclosed blocks, dynamic {% form %} kinds are compile errors. |
Schema contract |
Closed setting-type set; every exposed block type has an editable setting; preset settings reference declared settings; preset blocks live in preset.blocks (not settings). |
Templates |
Every templates/*.json references sections that exist, with settings that validate against their schemas — including seeded blocks. |
Locale files |
Every locales/ file parses as flat string→string JSON with a valid locale name; the declared default locale is the floor every buyer falls back to — a key absent there renders the visible "translation missing" marker (see Theme Locale Files). |
ctx honesty |
A template reading a ctx namespace must declare it in ctx_needs; blocks declare their own. |
Assets |
Every asset_url reference resolves inside the bundle. |
The platform template floor#
To SEAL (and to install from the marketplace), a theme must ship a non-empty template for EVERY routed surface the platform registers — every page type in Templates & Global Surfaces plus the store-state pages (coming soon, maintenance, password) and the global body/overlay surfaces. Only the optional head-injection surfaces (global_head, global_compliance_head) are exempt. The reason is structural: wishlist, categories, brands, vendors, and blogs are native platform features a merchant can enable without your theme's consent — any surface you skip becomes an empty shell the moment the merchant uses the feature. Direct dev-store imports are exempt from the floor so a partial theme can iterate; the floor is the bar for LISTING, not for building.
Publish → seal → install#
Upload the bundle to a listing version; publish runs the gate and SEALS the artifact (content-hashed, immutable). Installing copies pointer rows to the sealed source and materializes compositions from the bundle templates — bytes are read from the sealed artifact, never re-uploaded. Version updates install as a NEW theme side by side; the merchant activates when ready. During the current phase, installs target the developer organization's dev stores.