Skip to content

Conventions

Rules marked with MUST are strict and non-negotiable. Rules marked with SHOULD are guidelines — follow them unless you have a good reason not to.

File Structure

  • MUST place all Liquid source files in components/, never directly in sections/ or snippets/
  • MUST never manually edit files in sections/, snippets/, or assets/ — these are generated
  • MUST use index.liquid as the main file for any component folder
  • MUST use index.js for the component's JavaScript (one class per file)
  • MUST use style.scss for the component's scoped styles
  • SHOULD keep component folders flat when possible — only nest when there are genuine sub-components

Naming

  • MUST use snake_case for component folder names: cart_summary, add_to_cart_button
  • MUST use snake_case for Liquid file names: primary.liquid, sub_mobile.liquid
  • MUST prefix CSS classes used only for JS selection with js-: js-button, js-slider
  • MUST prefix layout utility classes with ll-: ll-container, ll-grid, ll-section
  • MUST NOT use js- prefixed classes for styling
  • MUST NOT use style classes for JS DOM selection
  • SHOULD use PascalCase for JavaScript class names matching the component: CartSummary, AddToCartButton

data-component

  • MUST use the path from the component type root: blocks/cart_summary, sections/header, parts/video_hls
  • MUST ensure the data-component value uniquely matches exactly one JS module
  • MUST NOT use leading slashes: use blocks/my_feature, not /blocks/my_feature

JavaScript

  • MUST export a single default class from each component JS file
  • MUST accept the DOM element as the constructor's first argument
  • MUST use arrow function class fields for methods (ensures correct this binding)
  • MUST import app from '../core/app' (or the correct relative path) to access services — never use globals
  • SHOULD cache DOM queries in init() or a dedicated cacheElements() method
  • SHOULD clean up event listeners and GSAP animations when a component is destroyed
  • MUST NOT use var — use const and let
  • MUST NOT add console.log in production code (remove debug logs before merging)

Liquid

  • MUST use {% render %} to include snippets, never {% include %} (deprecated)
  • MUST use single quotes for HTML attribute values in Liquid: class='my-class'
  • SHOULD pass data to snippets via named parameters: {% render 'parts.button', label: 'Click', variant: 'primary' %}
  • SHOULD keep Liquid logic minimal — complex logic belongs in JS

Styling

  • SHOULD prefer Tailwind utility classes in Liquid over custom CSS
  • SHOULD use @apply sparingly in SCSS — only when utilities can't be used in markup
  • MUST use the project's custom breakpoints, not arbitrary pixel values
  • MUST NOT use inline styles except for dynamic values (e.g., style="--ratio: ")
  • SHOULD use CSS custom properties for dynamic theming, not Sass variables

Imports and Dependencies

  • MUST use ESM imports (import/export), never CommonJS (require)
  • MUST follow the import sort order enforced by Biome (external, internal, relative)
  • SHOULD prefer existing libraries (GSAP, Swiper, Lenis) over adding new ones
  • MUST add new dependencies via npm install, never by copying files manually

Git

  • MUST run npm run lint:fix before committing
  • MUST write commit messages that explain the "why", not the "what"
  • MUST NOT commit node_modules/, .env, or build artifacts that are gitignored
  • SHOULD keep commits focused — one logical change per commit

Internal developer documentation