Skip to content

Architecture

Dossier is built on Shopify’s Skeleton theme with theme blocks, JSON templates, section groups and custom elements, and no JavaScript framework. This page explains the conventions that hold the theme together, so that your changes follow them.

Every template is JSON, except gift_card.liquid. Three section groups are shared by every page of theme.liquid:

  • g-header.json: Announcement bar and Header;
  • g-sidebars.json: Mobile menu, Cart drawer and Cart notification, rendered last in <body>;
  • g-footer.json: Footer.

Each section of a group accepts only its own group and appears at most once. password.liquid renders no group.

File names, section and block types carry a prefix:

Prefix Meaning
g- Section group
h-, f-, a- Sections of the header, footer and sidebars groups
main- Main section of a template
section- Sections merchants add to any template
sra- Sections rendered only through the Section Rendering API, invisible in the theme editor
gen- Public theme blocks, shared by several sections
_<parent>- Private theme blocks of one section, for example _section-slideshow-slide
_prod- Private blocks shared by Product information and Featured product
wc- Custom elements and their modules
util- Shared JavaScript modules and Liquid utility snippets

Snippets are grouped by area: head-, media-, prod-, coll-, blog-, cart-, nav-, form-, util-.

Blocks are theme blocks in blocks/, private by default (the file name starts with _), so they appear only in the section that declares them. The only section blocks are the @app blocks and the mega menu promotions of the Header.

Theme blocks are not visible to their section as section.blocks with their type and settings. When a section needs to know something about its blocks, it reads the rendered HTML of {% content_for 'blocks' %}, captured once, or the block receives what it needs as a parameter.

Colors come only from the theme’s color scheme group. Every section has a color_scheme setting and applies color-{{ section.settings.color_scheme }} to its root element; the class sets the CSS variables of the scheme (--color-surface, --color-ink, --color-brand…) and the background and text color. The classes are generated in Liquid from the schemes that exist, so a scheme added by the merchant works everywhere. Use the variables, never fixed colors, for anything that must keep its contrast.

Custom elements and progressive enhancement

Section titled “Custom elements and progressive enhancement”

Every page works without JavaScript: navigation and menus are <details> elements, the product form is a real <form> that posts to /cart/add, the cart updates with real forms. JavaScript adds behavior on top through custom elements, one ES module per element (wc-<name>.js), loaded with <script type="module"> only where the element is rendered.

The header comment of each Liquid file declares its JavaScript: web-component: wc-<name>, a module name, or none. Data that only Liquid knows reaches the scripts in <script type="application/json"> tags, and texts in data- attributes, already translated.

Partial updates, such as variant changes, the cart and predictive search, use the Section Rendering API: the element requests the section’s HTML for the new state and replaces part of the page. The product page has no variant JSON: the variant picker re-renders the section with option_values.

Components talk to each other through DOM events on document:

Event When detail
cart:added After a product is added from the product form or a product card. Cancelable: the component that shows the confirmation (cart drawer or cart notification) cancels it. item: the line returned by Shopify
cart:rendered After the cart HTML is updated on the page. Bubbles. —
cart:refreshed After the cart section is requested again following an add. Bubbles. —
scheduled-content:change When a scheduled section or block appears or disappears. Bubbles. —

Listen to cart:added to react to an add, for example to update a third-party counter; don’t cancel it, or the customer won’t see a confirmation.

<html> carries dir from the storefront language. The CSS uses only logical properties (margin-inline-start, inset-inline-end, Tailwind’s ms-, pe-, start- and so on), and directional icons are mirrored. Scripts read the direction from the document. Keep to logical properties in your CSS so the theme keeps working in Arabic and Hebrew.

Every visible text is a key in locales/en.default.json, and every theme editor label a key in locales/en.default.schema.json, both translated in 31 more languages. A new text needs a key in every language file.

Theme and guide by ICT Sviluppo