JavaScript
Entry Point
src/js/scripts.js is the main entry. It imports styles and creates the App instance on DOMContentLoaded.
The App class is the root of the JS framework. It initializes core services, resolves the Tailwind config for runtime access, and starts the component loading system.
Core Services
The App creates singleton services accessible via app.instances.get('name'):
| Service | Key | Purpose |
|---|---|---|
ResizeManager | resizeManager | Centralized resize handling with debounce |
Device | device | Input detection (touch vs pointer via detect-it) |
DataLayer | dataLayer | GTM dataLayer management |
Scroll | scroller | Lenis smooth scroll (pointer) or native scroll (touch) + GSAP ScrollTrigger |
Page | page | Component lifecycle for main#app content |
Cart | cart | Cart AJAX operations |
Accessing Services
import app from '../core/app'
export default class MyComponent {
constructor(element) {
this.element = element
this.init()
}
init = () => {
const cart = app.instances.get('cart')
const scroller = app.instances.get('scroller')
}
}Module Resolution
The getModule() helper in src/js/core/utils/helpers.js uses import.meta.glob('components/**/*.js') to build a map of all available JS modules. When a data-component attribute is found, the matching module is dynamically imported and instantiated.
This means adding a new interactive component is as simple as:
- Create
components/blocks/my_feature/index.jswith a default export class - Add
data-component="blocks/my_feature"to the HTML element
No manual registration or import is needed.
Component Lifecycle
App-Level Components
Located outside main#app — loaded once by App.loadAppInstances() and persist for the entire session.
Available lifecycle method:
tick()— called every frame viarequestAnimationFrame
Page-Level Components
Located inside main#app — managed by the Page service.
Available lifecycle methods:
load()— called after instantiation, awaited (use for async setup)resize()— called on window resize viaPage.triggerEvent
Page-level components are destroyed when the user navigates to a new page.
Style Loading
Component-scoped SCSS files (style.scss) are eagerly imported via src/js/styles.js:
import.meta.glob([
'../../components/sections/**/style.scss',
'../../components/blocks/**/style.scss',
'../../components/parts/**/style.scss'
], { eager: true })This ensures Vite includes all component styles in the CSS bundle without manual imports.
Shop-Specific Modules
The src/js/shop/ directory contains commerce-specific logic:
| Module | Purpose |
|---|---|
cart.js | Cart AJAX operations (add, update, remove) |
wishlist.js | Wishlist integration with the companion app |
proxy.js | HTTP client for App Proxy requests |
bundle-cart.js | Bundle add-to-cart logic |
Runtime Tailwind Config
The resolved Tailwind configuration is available at runtime via app.theme. This is made possible by a Vite resolve alias for tailwind.config.js, allowing JS components to read breakpoints, colors, and other design tokens.