Packaging & Sealing

The bundle layout, what the gate enforces, and the publish → seal → install lifecycle.

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/.vein

One file per section: markup + {% schema %}.

blocks/.vein

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/.json

Storefront dictionary per locale — every key the t filter reads.

locales/.schema.json

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.