doc-site
Developer guide

Source map

What lives in each directory of the Beauty Affairs AU theme, and what depends on what.

Source map

Repository root

PathContentsGenerated?
layout/Six layouts. See Layouts and templatesNo
templates/51 JSON templates, 59 Liquid templates, plus customers/JSON templates are written by the theme editor
sections/Around 197 theme editor sections and section groupsNo
snippets/Around 280 Liquid fragments, including app-provided onesvite-tag.liquid is generated
blocks/19 theme blocksNo
config/settings_schema.json, settings_data.json, markets.jsonsettings_data.json and markets.json are written by Shopify
locales/11 translation files, en.default.json is the sourceNo
assets/Compiled bundles plus older hand-written assetsPartly
src/TypeScript, TSX and source CSSNo
scripts/Node scripts for onboarding, deploys and the tunnelNo

Inside src

src/
├── @types/        Ambient types and third-party SDK shapes
├── assets/        theme_in.css, the Tailwind entry
├── components/    Shared logic, imported by entrypoints
├── entrypoints/   One bundle per file
└── lib/           Small cross-cutting helpers

Only files under src/entrypoints/ become bundles. Everything else is imported.

src/@types

FileContents
global.tsThe window.theme and window.Shopify shapes, and every global the theme sets
shopify.tsShopify storefront object types: Product, Variant, Cart
calendar.tsSesami SDK shape, calendar config, Klaviyo and Zapier payloads
klaviyo.tsKlaviyo globals
vite-virtual.d.tsVite virtual module declarations

global.ts is the most useful file in the repository for understanding what Liquid hands to JavaScript. Every window.theme.* key that a Liquid file sets is declared there.

src/lib

FileContents
logger.tsThe conditional console logger and namespace system
cart-source.tsThe _source line item property convention
utils.tscreateEnum

src/components

One directory per feature. These hold logic that entrypoints import.

DirectoryFeature
medispa-calendar/The React booking calendar, 12 components plus Jotai atoms
popup-logic/Popup manager, timer, adapters and sniffers, popup definitions
purchase-gift-manager/Multi-buy gift promotion logic
cart-reward-banner/Homepage reward tier banner
homepage-prominence-banner/Homepage gifts banner
pack-options/Product pack size selection
swatch-filters/Colour swatch filtering
clickable-slideshow/Slideshow with clickable regions
counter/Countdown and counting behaviour
utils/defer and deferJS polling helpers, MediSpa landing page helpers

In utils/defer.ts, defer(fn, selector) polls every 50 milliseconds until an element exists, and deferJS(fn, validator) polls until a predicate is true. Both are exposed on window. The theme uses them to wait for app scripts whose load order it cannot control.

src/entrypoints

Around 60 top-level entrypoints plus two subsystem directories.

PathSubsystem
mini-cart/Cart drawer. internals/ for logic, elements/ for custom elements, components/ for features
homepage-redesign/components/One entrypoint pair per homepage section
medispa-*.tsMediSpa landing page behaviours, one per section
theme.css, styles.css, custom.css, theme.styles.cssGlobal stylesheets loaded by the layouts
utils.tsdebounce, cn, and the money formatting helpers
main.tsNothing but the Vite modulepreload polyfill

Most entrypoints come in pairs. sections/hero-banner.liquid renders both homepage-redesign/components/hero-banner.css and hero-banner.ts, so the styles load only where the section does.

The full mapping from Liquid file to entrypoint is in Entrypoint map.

How Liquid passes data to TypeScript

A feature uses one of four channels. Find the channel and you know where to look.

ChannelHow it worksUsed by
Global on window.themeA Liquid snippet writes it and an entrypoint reads it. src/@types/global.ts declares keysBooking calendar, reward banner
Data attributeThe custom element that owns the element reads itMini-cart section settings, for example data-open-on-add
Custom event on windowAny script can dispatch it without importing anythingMini-cart command events
Inline JSON script tagCode queries it from the DOMMediSpa treatment lists, one script[data-medispa-products-fragment] per Services Overview section

Path aliases

tsconfig.json maps @/* and ~/* to ./src/*. Both work. @/ is more common in this codebase.

import { createLogger } from '@/lib/logger';

snippets/vite-tag.liquid also rewrites ~/ and @/ prefixes to ../ when resolving an entrypoint path, so render 'vite-tag' with '@/entrypoints/foo.ts' resolves the same as the bare path.

Key dependencies

PackageUsed by
react, react-domOnly the MediSpa booking calendar
jotaiOnly the booking calendar's shared state
swiperCarousels across the homepage and MediSpa pages
date-fnsDate handling in the calendar
clsxThe cn helper in src/entrypoints/utils.ts
react-spinnersCalendar loading state

Only the booking calendar uses React. Adding a second React island would double the bundle on pages that need it, so prefer a custom element unless the feature needs React.

jQuery is declared in tsconfig.json types and referenced from older assets, but it is not an npm dependency of src/. The MediSpa landing pages were deliberately built without it.

On this page