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 insections/orsnippets/ - MUST never manually edit files in
sections/,snippets/, orassets/— these are generated - MUST use
index.liquidas the main file for any component folder - MUST use
index.jsfor the component's JavaScript (one class per file) - MUST use
style.scssfor the component's scoped styles - SHOULD keep component folders flat when possible — only nest when there are genuine sub-components
Naming
- MUST use
snake_casefor component folder names:cart_summary,add_to_cart_button - MUST use
snake_casefor 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-componentvalue 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
thisbinding) - MUST import
appfrom'../core/app'(or the correct relative path) to access services — never use globals - SHOULD cache DOM queries in
init()or a dedicatedcacheElements()method - SHOULD clean up event listeners and GSAP animations when a component is destroyed
- MUST NOT use
var— useconstandlet - MUST NOT add
console.login 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
@applysparingly 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:fixbefore 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