doc-site
Architecture

System overview

What this theme is made of, which system owns each behaviour, and where the boundaries sit.

System overview

Beauty Affairs AU is one Shopify theme in one repository. There is no separate app, no server and no database that this team runs. Everything either renders in Liquid, runs in the browser, or belongs to Shopify or an installed app.

Before any change, work out which of the four owners makes it.

Four owners and the surfaces they edit: a developer commits to the repository, a merchandiser edits theme settings in the theme editor, a store manager edits store data in Shopify Admin, and installed apps inject script tags. All of them reach the live theme, and a GitHub Action copies theme editor changes back into the production branch.

The two halves of the repository

The repository is a standard Shopify theme at the root, with a source project added in src/.

DirectoryContentsEdited by
layout/, templates/, sections/, snippets/, blocks/LiquidDeveloper, plus the theme editor for JSON templates
config/Theme settings schema and saved valuesDeveloper for the schema, theme editor for the values
locales/Translation stringsDeveloper
assets/Build output, plus older hand-written filesVite, mostly
src/TypeScript, TSX and source CSSDeveloper only
scripts/Node scripts for onboarding, deploys and the dev tunnelDeveloper only

.shopifyignore keeps src/, scripts/, node_modules/ and the tooling config out of every theme push, so the store never receives source files. Only the compiled output in assets/ is uploaded.

How source reaches the browser

Liquid cannot import a TypeScript module, so a generated snippet connects the two.

A left to right pipeline: src/entrypoints is compiled by Vite, which writes hashed bundles into assets/, records them in vite-manifest.json, and rewrites vite-tag.liquid. A Liquid section renders vite-tag, which emits a tag pointing at the Shopify CDN copy of the asset.

A section that needs behaviour renders one line:

{%- render 'vite-tag' with 'mini-cart/elements/mini-cart.ts' -%}

snippets/vite-tag.liquid is a generated lookup table mapping every entrypoint path to its hashed output file. Vite rewrites it on every build. Full detail is in How the build works.

Ownership of behaviour

BehaviourOwned byNotes
Page structure and stylingThis repositoryLiquid plus compiled CSS
Cart drawer, reward progress, free giftsThis repositoryReads thresholds from theme settings and gifts from a metaobject
Booking calendar UIThis repositoryReact, mounted into a Liquid placeholder
Appointment availabilitySesamiThe theme calls their SDK and renders what it returns
Email and SMS captureKlaviyoThe theme holds form IDs and coordinates when a popup may open
Booking intent routingZapierThe theme posts a payload to a webhook URL held in theme settings
Search and collection filteringBoostRenders through its own snippets
Discount display and promotionsDiscount NinjaInjects its own scripts
AnalyticsGoogle Tag ManagerContainer ID in theme settings

Anything in the right column outside this repository can change without a commit here. That is the main reason a behaviour can differ between environments with no code difference.

Trust boundaries

The browser is not trusted. Shopify recomputes every price, discount and gift the theme shows when the customer reaches checkout. Theme code that appears to control a price controls only how the price is displayed.

Third-party scripts share the page. The theme uses Yett to hold back specific vendor scripts until the theme releases them, with the blocklist set in layout/theme.liquid. MediSpa landing pages use a stricter list in layout/theme.redirect.liquid, because the team has no admin access to some apps' own page-targeting settings.

The cart is shared state. Several apps write to the Shopify Ajax Cart, and none of them notify the theme. The mini-cart patches window.fetch to observe those writes. See Mini-cart.

Failure modes

A stale snippets/vite-tag.liquid points Liquid at a hashed file that no longer exists in assets/, so the browser gets a 404 and the feature does nothing. Rebuilding fixes it. See Feature does nothing and the console shows a 404.

A push from a stale branch overwrites any theme editor change made after the last pull. The Pull theme from Shopify workflow exists to prevent this, and it only writes to production. See Branches and theme sync.

When an app stops responding, its feature stops working. A Sesami outage produces a calendar with no slots, which looks identical to a clinic with no availability.

Where to go next

You wantPage
The build in detailHow the build works
Which layout a page usesLayouts and templates
How the cart stays consistentMini-cart
How a booking is madeMediSpa booking
What each installed app doesIntegrations

On this page