Theme Block Extensions
Theme blocks are Liquid-based UI components that merchants can add to their storefront themes. They appear in the theme editor alongside native blocks, allowing merchants to position and configure them visually.How Theme Blocks Work
- Your app installs block files (
.aquatemplate +.schema.jsonschema) - Blocks appear in the merchant’s theme editor under “App Blocks”
- Merchants drag blocks into sections and configure settings
- LaunchMyStore renders your block using the Liquid template engine
Block File Structure
Each theme block requires two files:Creating a Theme Block
1. Write the Liquid Template
Theme blocks use.aqua files with standard Liquid syntax:
2. Define the Schema
The schema controls what settings appear in the theme editor:Top-level Schema Fields
The schema JSON accepts the following top-level keys:| Field | Type | Description |
|---|---|---|
name | string (required) | Display name in the theme editor block picker. |
target | string | string[] (required) | Page-type slot where the block can be inserted. See Available Targets. |
tag | string | HTML wrapper element for the block (default section). |
class | string | Class name applied to the wrapper element. Useful for shared per-app CSS hooks. |
settings | object[] | Block-level settings shown in the theme editor. See Setting Types. |
blocks | object[] | Nested block templates the merchant can add inside this block — same type / name / settings shape as a section’s blocks array. |
max_blocks | integer | Hard cap on how many nested blocks a merchant can add (default 50, configurable via MAX_BLOCKS_PER_SECTION). |
presets | object[] | Pre-configured combinations of settings + nested blocks shown as quick-add options in the picker. Each preset has { name, settings?, blocks? }. |
color_scheme | string | Default color-scheme handle to apply (e.g. "scheme-1"). Honoured by themes that wire schemes through their t:section.color_scheme plumbing. |
Available Targets
Thetarget field determines which page types your block can be added to:
| Target | Description | Available Objects |
|---|---|---|
index | Homepage | shop, collections, articles |
product | Product pages | product, shop, collection |
collection | Collection pages | collection, products, shop |
cart | Cart page | cart, shop |
article | Blog articles | article, blog, shop |
page | Custom pages | page, shop |
blog | Blog listing | blog, articles, shop |
search | Search results | search, results, shop |
You can target multiple page types by specifying an array:
"target": ["product", "collection"]Setting Types
Basic Inputs
Selection Inputs
Range & Toggle
Visual Pickers
Resource Pickers
Installing Theme Blocks
Install blocks when your app is installed on a store:Per-app CSS/JS
There is noextension_asset_url filter. Apps ship CSS/JS in one of
two ways:
1. Inline <style> / <script> in the .aqua template
For small, dynamic CSS that depends on block.settings.*, inline a
<style> tag inside the template (as shown in the example above).
This is the recommended approach for block-scoped styles.
2. Bundled assets (per-merchant disk copy)
Files inextensions.assets[] are downloaded and stored under
extensions/{domainSlug}/{appHandle}/assets/. They’re publicly
served at the same path, so reference them as absolute URLs:
__domainSlug is the merchant’s store identifier and is the same path
segment the host uses when copying your bundled assets onto disk.
3. App embeds (page-wide scripts)
For scripts that should load on every page (analytics, chat widgets, review widgets that scan the page), use an app embed instead of a block. See App Embeds — embeds supportscriptSrc, inlineHtml, and stylesheetUrl and are injected by the
host into the rendered HTML.
Block manifests accept
stylesheetUrl and scriptUrl fields, but the
host does not currently inject them when the block renders. If your
block needs external CSS/JS, declare it as an app embed (option 3) or
inline it in the .aqua template (option 1).Theme assets (different from extension assets)
For files inside the merchant’s theme (the theme’sassets/ folder),
use the standard Liquid filters:
{{ 'foo.css' | asset_url }}— theme asset CDN URL{{ 'foo.png' | asset_img_url }}— theme image asset{{ 'foo.svg' | inline_asset_content }}— inline SVG content{{ 'foo.pdf' | file_url }}— theme file CDN URL
Snippets
Create reusable components as snippets:Accessing Data
Block Settings
Access settings viablock.settings:
Global Objects
Standard Liquid theme global objects are available:Metafields
Access your app’s metafields:Best Practices
Keep templates performant
Keep templates performant
Avoid complex logic in Liquid. Pre-compute values in your backend and store them in metafields.
Use semantic HTML
Use semantic HTML
Use proper heading levels, ARIA labels, and semantic elements for accessibility.
Scope your CSS
Scope your CSS
Prefix class names with your app handle to avoid style conflicts with the theme.
Lazy load JavaScript
Lazy load JavaScript
Use
defer or dynamic imports for JavaScript to avoid blocking page render.Support theme settings
Support theme settings
Respect the merchant’s theme colors and fonts where possible. Use CSS custom properties.
Test across themes
Test across themes
Test your blocks with multiple themes to ensure compatibility with different layouts.