Conventions
These are the rules every developer and content editor working in this theme needs to follow. Breaking them causes visual bugs, accessibility failures, or build errors that are hard to trace.
Colours
Section titled “Colours”All colours come from the @theme block in
frontend/entrypoints/css/theme.css. No arbitrary hex values in class names —
ever.
Palette:
- Neutrals —
white,salt,warm-gray,off-white - Charcoal scale —
charcoal-50throughcharcoal-600,charcoal(base),light-charcoal - Kale (brand green) —
kale-200,kale-300,kale-400,kale(base) - Accents —
green,blue,berry,tan
Typography
Section titled “Typography”Two brand font families:
- TT Rationalist (serif) — headings, quotes, body-2xl. Weights: 200, 300.
- Restart Soft (sans) — body text, buttons, smaller headings. Weights: 300, 400.
Typography is applied through utility classes like text-heading-lg or
text-body-md, which set font-family, size, line-height, letter-spacing, and
weight in one class. Never set font-family directly — use the utility.
Sizes cascade upward: mobile is the base. Tablet overrides at 768px, desktop at 1280px. Leave tablet and desktop on “Default” and the mobile size applies everywhere.
Spacing and padding
Section titled “Spacing and padding”Sections use a six-setting padding pattern: top and bottom for mobile, tablet, and desktop. Values are in pixels with step 2 or 4.
class="pt-[var(--padding-top)] md:pt-[var(--padding-top-tablet)] lg:pt-[var(--padding-top-desktop)] pb-[var(--padding-bottom)] md:pb-[var(--padding-bottom-tablet)] lg:pb-[var(--padding-bottom-desktop)]"style=" --padding-top: {{ s.padding_top_mobile }}px; --padding-bottom: {{ s.padding_bottom_mobile }}px; --padding-top-tablet: {{ s.padding_top_tablet }}px; --padding-bottom-tablet: {{ s.padding_bottom_tablet }}px; --padding-top-desktop: {{ s.padding_top }}px; --padding-bottom-desktop: {{ s.padding_bottom }}px;"The three breakpoints are independent — changing desktop does nothing to mobile.
Block architecture
Section titled “Block architecture”Every section follows the same pattern:
- Static blocks for pinned header content (title, tag, richtext) —
{% content_for 'block', type: 'title', id: 'section-title' %} - Theme blocks for repeatable content —
{% content_for 'blocks' %} - Each block renders itself. The section never reads block settings.
Block files live in blocks/ and are never redefined per section. Use
{% content_for 'block' %} for static blocks and {% content_for 'blocks' %}
for the reorderable collection. Never {% render block %}.
Translations (i18n)
Section titled “Translations (i18n)”Every schema setting needs a translation in locales/en.default.schema.json.
- Blocks (
blocks/*.liquid) — translations go in the"blocks"section - Sections (
sections/*.liquid) — translations go in the"sections"section - Mixing them up causes errors
Always search for an existing key before adding one — duplicates cause errors.
Liquid syntax
Section titled “Liquid syntax”No ternary operators. Liquid doesn’t support condition ? true : false. Use
if/elsif/else/endif.
Multi-line filters work in individual tags ({% assign %}) but not inside
{% liquid %} blocks. In liquid blocks, keep filter chains on one line.
Richtext defaults must have valid HTML top-level tags (<p>, <h1>–<h6>,
<ul>, <ol>). Plain text without tags fails schema validation.
CSS (Tailwind v4)
Section titled “CSS (Tailwind v4)”CSS-first configuration — no tailwind.config.js. All tokens live in
frontend/entrypoints/css/theme.css.
/* Use width queries, not @screen */@media (width >= 1024px) { ... } /* correct */@screen lg { ... } /* not supported */
/* Use CSS variables, not theme() */color: var(--color-kale); /* correct */color: theme("colors.kale"); /* not supported */CSS files using @apply must include @reference directives:
@reference "tailwindcss";@reference "../theme.css";section_id first
Section titled “section_id first”Every section schema must have section_id as its first setting — no
exceptions.
Curated collections
Section titled “Curated collections”Collection pages can be composed from hand-picked rows instead of the auto-fill grid. When filters are applied, the curated rows hide and a standard grid takes over. See Curated Collection Templates for the full pattern.