doc-site
Developer guide

Making common changes

Step by step recipes for the changes this theme needs most often.

Making common changes

Each recipe lists what changes together. Missing one of the pieces is the usual cause of a change that works locally and does nothing in production.

Add behaviour to an existing section

  1. Create the entrypoint in src/entrypoints/, or beside its siblings if the section belongs to a subsystem such as homepage-redesign/components/.
// src/entrypoints/homepage-redesign/components/my-feature.ts
import { createLogger } from '@/lib/logger';

const log = createLogger('my-feature');

document.addEventListener('DOMContentLoaded', () => {
  const root = document.querySelector<HTMLElement>('[data-my-feature]');
  if (!root) return;
  log.info('mounted');
});
  1. Render it from the section, at the top of the Liquid file:
{%- render 'vite-tag' with 'homepage-redesign/components/my-feature.ts' -%}
  1. Add a CSS entrypoint beside it if the feature needs styles, and render that too.

  2. Run npm run build. Confirm snippets/vite-tag.liquid now contains a branch for your path.

  3. Commit the source, the built assets and the regenerated snippet together.

Use createLogger rather than console.log. Console output is suppressed for customers, and you can switch a namespaced logger on with ?ba_debug=my-feature.

Add a theme setting

Decide first whether the value belongs in theme settings at all. A value that describes a product belongs on the product as a metafield. A value that describes how a page looks belongs in theme settings or on the section.

For a global setting:

  1. Add it to the right group in config/settings_schema.json, or create a group.
  2. Read it in Liquid as settings.your_setting_id.
  3. If JavaScript needs it, write it to window.theme from a snippet and declare it in src/@types/global.ts.
  4. Document it in Theme settings and in the relevant Operations page.

Do not edit config/settings_data.json by hand. Shopify writes that file, and the next theme editor save or theme pull overwrites your change.

For a section-level setting, add it to that section's {% schema %} block instead. The value then lives in the JSON template, and each instance of the section gets its own.

Add a section

  1. Create sections/my-section.liquid.
  2. Render any entrypoints it needs at the top.
  3. Add a {% schema %} block with a name, settings, and a presets entry so it appears in the theme editor's Add section list.
  4. Constrain it with enabled_on or disabled_on in the schema if it only belongs on some templates.
  5. Build, then add it to a page in the theme editor to confirm the preset works.

A section with no presets entry cannot be added through the theme editor. It can still be referenced directly from a JSON template, which is how several of the layout-level sections here work.

Add a mini-cart element

The drawer has a working template for this at src/entrypoints/mini-cart/elements/00-example.ts. Copy it.

The contract every element follows:

  1. Extend HTMLElement.
  2. In connectedCallback, find the parent with this.closest('mini-cart') and throw if it is missing.
  3. Call parentMiniCart.execOnReady(...) and take the bus from parentMiniCart.bus. Do not create your own CartEventBus, because a second bus listens to the same window events but the root element will not know about your element.
  4. Listen to CartEvents.DebouncedChange rather than Changed if rendering is expensive.
  5. In disconnectedCallback, abort the controller and unbind.
  6. Guard the registration with if (!customElements.get('my-element')).

Then add a matching block to sections/mini-cart.liquid so a merchandiser can place it, and a snippet that renders the markup.

Before writing any cart mutation, read Mini-cart, in particular the serialisation rules. Calling a SimpleCartService method from inside runExclusive deadlocks the cart.

Change something on a MediSpa page

MediSpa pages use their own layouts, their own sections and a stricter script blocklist.

  1. Confirm which layout the template uses. Check the layout key in the JSON template.
  2. Check the layout's YETT_BLACKLIST before adding anything that depends on a third-party script.
  3. Prefer the medispa-* sections over the general ones. They exist because the general ones pull in jQuery or a blocked app.
  4. Test on a real MediSpa template rather than on the homepage.

Add a value to window.theme

  1. Write it from a Liquid snippet:
<script>
  window.theme = window.theme || {};
  window.theme.myFeature = {{ my_value | json }};
</script>
  1. Declare it in src/@types/global.ts under the theme interface. Without this, npm run typecheck fails and the value is untyped at every call site.

  2. Read it in TypeScript. Treat it as possibly absent, because a page that does not render the snippet will not have it.

Change a price or a currency amount

Money in this codebase is in cents wherever it comes from Shopify, and in dollars wherever it comes from a theme setting or a metafield.

Convert exactly once, at the boundary where you format for display. src/entrypoints/utils.ts provides formatMoney, shopifyFormatCurrency and formatCentsInMoneyTemplate for this.

The MediSpa calendar config snippet documents its own convention in a comment. Read it before touching prices there. A second conversion produces a value a hundred times too large, and reviewers tend to miss it because the code looks reasonable.

Add a translation string

  1. Add the key to locales/en.default.json.
  2. Use it in Liquid with {{ 'your.key' | t }}.
  3. Leave the other locale files alone unless you have translations. Shopify falls back to the default.

Schema labels go in locales/en.default.schema.json rather than the main file.

What to check before opening a pull request

npm run typecheck
npm run lint
npm run build

Then confirm:

The diff includes the regenerated assets/ files and snippets/vite-tag.liquid.

snippets/vite-tag.liquid points at hashed filenames, not at localhost:5173.

config/settings_data.json and templates/*.json contain only changes you meant to make. The dev server syncs theme editor changes down, so these files pick up merchandiser edits.

You have merged production into your branch, so you are not about to overwrite a theme editor change. See Branches and theme sync.

On this page