Building themes

Theme reference

Generated from the validator's own rules, so it cannot drift from what we accept. Point your editor at the JSON Schema and you get all of this as you type.

Nodes

What you can draw. A section's `render` is a list of these.

boxA container. Becomes a div, or any layout or landmark tag you name.
textA line of text, in the tag you name: a heading, a paragraph, a label.
richRichtext a merchant wrote, sanitised every time it is drawn.
imgA picture, drawn at the width its role says it will be drawn at.
linkAn anchor around anything.
eachRepeats its children over a list, under a limit it does not choose.
ifDraws one set of children or another, on a condition.
slotRepeats its children once per repeatable block, with `block` in scope.
iconOne of the storefront's own icons.
moneyAn amount, formatted in the shop's display currency.
componentOne of the components below. The only interactive thing a theme can place.

Components

The interactive parts. You place and position them; you cannot write one. Those marked with slots take their layout from your theme.

product-cardA product in a grid: picture, title, price, and quick add.
add-to-cartThe button, with a quantity field in front of it. Pass `quantity: false` for a one-press add.
variant-pickerSize, colour and the rest, wired to what is in stock.
search-boxThe search field and its suggestions.
newsletter-formEmail capture, with the shop's own consent wording.
cart-drawerThe basket that slides in when something is added.
paginationNext and previous, for a listing that runs past one page.
priceAn amount with its compare-at and its currency handled.
account-menuSign in, or the customer's own links when they are.
accordionRows that open. You lay out the title and the body; a merchant adds the rows. Slots: title (per block), body (per block).
image-carouselSlides the shopper can move through. You lay out one slide. Slots: item (per block).
popup-panelSomething that opens when pressed. You lay out the button and the panel. Slots: trigger, content.
shop-logoThe shop's own logo, at the size it was uploaded.
shop-menuA menu the merchant built, resolved to real links.
cart-linkThe basket, and how many things are in it.
currency-switcherThe currencies this shop actually sells in.
language-switcherThe languages this shop is published in.
social-linksThe shop's own accounts, as icons.

Data

A section declares what it needs and the page fetches it before drawing anything, so two sections asking for the same list cost one query. A theme cannot write a query of its own.

newest-productsThe most recently added products in the shop.
collection-productsProducts in a category, or the newest if none is chosen.
collectionsThe shop's categories.
product-variantsThe variants of the product on this page.
product-imagesThe pictures of the product on this page.
related-productsProducts that go with the one on this page.
metaobjectsEntries of a custom content type your theme defines.
cart-linesWhat is in the basket right now.
menuA named menu the merchant built.

Design tokens

Your theme.json sets the defaults; the merchant can change any of them. Read them in CSS as the custom property beside each one.

colorBgPage background. CSS: var(--shop-bg). Default: #ffffff
colorFgText. CSS: var(--shop-fg). Default: #0f1115
colorAccentAccent. CSS: var(--shop-accent). Default: #7c3aed
colorMutedMuted text. CSS: var(--shop-muted). Default: #6b7280
fontHeadingHeading font. CSS: var(--shop-font-heading). Default: "Inter", system-ui, sans-serif
fontBodyBody font. CSS: var(--shop-font-body). Default: "Inter", system-ui, sans-serif
fontSizeBodyBody text size. CSS: var(--shop-font-size-body). Default: 16px
fontSizeHeadingLargest heading size. CSS: var(--shop-font-size-heading). Default: 60px
radiusCorner radius. CSS: var(--shop-radius). Default: 0
maxWidthContent width. CSS: var(--shop-max-width). Default: 1200px
controlRadiusButton and field radius. CSS: var(--shop-control-radius). Default: 0
btnBgButton background. CSS: var(--shop-btn-bg). Default: #000
btnFgButton text. CSS: var(--shop-btn-fg). Default: #fff
btnBorderButton border. CSS: var(--shop-btn-border). Default: #000
imageMainMain image, desktop. CSS: var(--shop-img-main). Default: 50vw
imageMainMobileMain image, mobile. CSS: var(--shop-img-main-mobile). Default: 100vw
imageSmallGrid image, desktop. CSS: var(--shop-img-small). Default: 25vw
imageSmallMobileGrid image, mobile. CSS: var(--shop-img-small-mobile). Default: 50vw
imageThumbnailThumbnail, desktop. CSS: var(--shop-img-thumbnail). Default: 96px
imageThumbnailMobileThumbnail, mobile. CSS: var(--shop-img-thumbnail-mobile). Default: 72px
imageSwatchSwatch, desktop. CSS: var(--shop-img-swatch). Default: 48px
imageSwatchMobileSwatch, mobile. CSS: var(--shop-img-swatch-mobile). Default: 40px
checkoutSummarySideOrder summary on the. CSS: var(--shop-checkout-direction). Default: row
checkoutSummaryBgSummary background. CSS: var(--shop-checkout-summary-bg). Default: #F3F7FF
checkoutSummaryFgSummary text. CSS: var(--shop-checkout-summary-fg). Default: #000000
checkoutFontHeadingCheckout heading font. CSS: var(--shop-checkout-font-heading). Default: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
checkoutHeadingSizeCheckout heading size. CSS: var(--shop-checkout-heading-size). Default: 24px

Expression roots

Where a `get` path may start. Which of these are in scope depends on where you are: `block` inside a slot, `item` (or whatever you named it) inside an each.

settings · theme · block · shop · page · product · collection · cart · customer · data

Tags

What a box and a text node may become.

box

div · section · header · footer · nav · main · aside · article · ul · ol · li · figure · figcaption

text

p · h1 · h2 · h3 · h4 · h5 · h6 · span · strong · em · small · blockquote · label

Icons

The storefront's own set. An icon node names one of these.

search · account · bag · bin · menu · close · chevron · clock · trend · folder · instagram · facebook · x · tiktok · youtube · pinterest · linkedin

Limits

Ceilings, all of them boring. A bundle is read on every request, so its size is a speed budget as much as a safety one.

sectionsPerBundle60
fieldsPerSection40
blocksPerSection12
fieldsPerBlock20
templateSections40
metaobjectTypes40
fieldsPerMetaobject30
cssBytes200,000
sectionCssBytes40,000
bundleBytes2,000,000
dataRequestsPerSection6
customSections30
customSectionBytes60,000
Theme reference · WhizzyCommerce