Skip to content

Components

Component Structure

A component is a folder inside components/ containing up to three files:

components/blocks/cart_summary/
  index.liquid    ← Liquid template (required)
  index.js        ← JavaScript class (optional)
  style.scss      ← Scoped styles (optional)

The Liquid file is the only required file. JavaScript and styles are opt-in per component.

Connecting JS to HTML

Components are connected to their JavaScript via the data-component attribute:

html
<div data-component="blocks/cart_summary">
  <!-- component markup -->
</div>

The attribute value must match the path from the component type root (blocks/, sections/, parts/). The JS module system uses import.meta.glob to discover all components/**/*.js files and matches them by path.

WARNING

Do not use leading slashes. Use blocks/my_feature, not /blocks/my_feature.

JavaScript Class Pattern

Every component JS file exports a single default class:

javascript
export default class CartSummary {
  constructor(element) {
    this.element = element
    this.init()
  }

  init = () => {
    // Cache DOM elements, bind events
  }

  // Optional lifecycle methods:
  load()    // Called after instantiation (Page-level only, awaited)
  resize()  // Called on window resize via Page.triggerEvent
  tick()    // Called every frame via requestAnimationFrame (App-level)
}

Rules

  • Export a single default class
  • Accept the DOM element as the constructor's first argument
  • Use arrow function class fields for methods (ensures correct this binding)
  • Import app from the core module to access services — never use globals

Loading Contexts

Components are loaded in two contexts depending on their position in the DOM:

ContextSelectorManagerPurpose
App-level[data-component] outside main#appApp.loadAppInstances()Persistent chrome (header, overlays)
Page-level[data-component] inside main#appPage.createInstances()Page content, destroyed on navigation

App-level components persist across page navigations. Page-level components are created when the page loads and destroyed when the user navigates away.

Component Categories

Sections (components/sections/)

Full Shopify sections with {% schema %} blocks. These define configurable content areas in the Shopify theme editor.

Examples: header, footer, product, collection

Blocks (components/blocks/)

Reusable UI blocks rendered via {% render %}. These are the workhorses of the theme.

Examples: cart_summary, cart_item, pdp/gallery, pdp/info, layout/header/nav

Parts (components/parts/)

Small, reusable primitives.

Examples: buttons/primary, form/input, image, price, video_hls

Icons (components/icons/)

SVG icon partials. Each icon is a single .liquid file.

Globals (components/global/)

Cross-cutting Liquid files like head, javascript_variables, translation_strings.

Rendering Components

Use {% render %} with the flattened snippet name (dots instead of slashes):

liquid
{% render 'parts.button', label: 'Add to Cart', variant: 'primary' %}
{% render 'blocks.cart_summary' %}
{% render 'icons.search' %}

TIP

Always pass data via named parameters. Never use {% include %} (deprecated).

Internal developer documentation