Beauty Affairs HK

Conventions

What this repository expects from a change, and where its stated conventions differ from the current code.

Formatting

Prettier formats the code, configured in .prettierrc. It uses single quotes, semicolons, trailing commas, 120-character lines, and proseWrap: always, which hard-wraps Markdown.

@shopify/prettier-plugin-liquid formats Liquid.

A pre-commit hook runs Prettier over staged files. npm install installs the hook through simple-git-hooks, so a fresh clone where nobody ran npm install has no hook.

.editorconfig and .vscode/settings.json turn on format on save. .vscode/extensions.json recommends the Shopify Liquid extension, which shows Theme Check results inline.

TypeScript

strict, noEmit, isolatedModules and forceConsistentCasingInFileNames are all on. The target is ES2022, with Bundler module resolution.

Import through the @/ alias instead of long relative paths. Both @/ and ~/ resolve to src/.

tsc only checks src/. It cannot read Liquid, so it cannot tell you that a value on window.theme is missing at runtime. See Liquid to JavaScript contract.

Logging

Use createLogger('namespace') from src/lib/logger.ts instead of console. The logger prints nothing unless a developer turns it on, so log calls left in the code do not reach shoppers.

import { createLogger } from '@/lib/logger';
const log = createLogger('my-feature');
log.info('mounted');

Some older code still calls console directly. The logger patches the global console, so that output is hidden too. New code should still use a namespace, so a developer can turn on its output without everything else.

Tag cart writes with their source

src/lib/cart-source.ts exports withCartSource, which adds a _source line item property in the form <surface>:<function>. Shopify hides properties that start with an underscore on the storefront and at checkout. They still appear in /cart.js, in the order admin and in webhooks.

Use it on every add to cart. The _source property is the only record of which code added a line, and with this many apps writing to the cart, you will need that record.

Section schema requirements

Make merchant-facing behaviour configurable. Add an enable toggle and settings for wording, images and thresholds instead of hardcoding them. AGENTS.md states this requirement, and reviewers check it first.

Run Theme Check after any schema change:

npm run lint:fix
npm run lint

Four section schemas contain trailing commas. Shopify and Theme Check both accept them, but a strict JSON parser rejects them. Do not add more, because any tool that reads schemas with a standard JSON parser fails on them. The four are sections/medispa-service-callout.liquid, sections/review-carousel.liquid, sections/blog-posts-redesign.liquid and sections/seo-content-redesign.liquid.

Section structure

The stated convention is two wrappers per section. The outer element carries the background so it can span the full viewport width. The inner element limits the content width with calc(100% - var(--gutter)), where --gutter is a schema setting.

The code does not match this yet. No section uses a --gutter custom property. A few sections use the wrapper pattern, and they name the wrappers after the section instead of using a shared class:

<div class='shop-by-routine--inner-wrapper'>
{ "class": "shop-by-routine--outer-wrapper" }

Follow the convention for new sections, using the section-named form shown above, because the existing examples use it. Do not convert old sections as part of an unrelated change.

Naming

Liquid files use kebab case. A dot separates a family from its member, as in mini-cart.line-items.liquid. The fn. prefix marks a snippet used for its return value.

TypeScript files use kebab case. React component files use PascalCase to match the component name.

Custom element tag names match their file names, so mini-cart-footer.ts defines <mini-cart-footer>.

Tailwind

Tailwind classes use the tw- prefix, and preflight is off, because Tailwind's reset would break the theme's own base styles. important is on, so a tw- class overrides theme CSS.

The brand colours are ba-light-grey, ba-medium-grey, ba-dark-grey and ba-pink. The fonts are ba-title, ba-body and ba-MinerveModern.

The content globs cover ./**/*.liquid and ./src/**/*.{js,ts,jsx,tsx}, so a class used only in Liquid still ends up in the CSS. A class built at runtime from string fragments does not. If you need one, add it to safelist in tailwind.config.cjs.

Git

Name branches after the issue they come from, for example 2-ba-115-fx-auhk-update-gift-cards-page---update.

Only the theme pull workflow writes to the production branch. Do not branch from it or open pull requests against it. See Deploy and roll back.

What this repository does not have

The repository has no test suite, no CI that builds or type-checks a pull request, and no lint gate other than the local pre-commit hook.

Checking a change is therefore manual. Every operations page in these docs ends with a "Verify the change" section, and a pull request should say what you checked and on which preview theme.

On this page