Skip to main content
The runtime field in theme.json picks how section design files are written. All three build with the same Vite pipeline and the same platform, so settings, blocks, preview and publish behave the same. A theme may mix runtimes per section. Without src/theme.tsx, the files src/theme.css and src/theme.ts load automatically for global CSS and JS.

One section, three runtimes

These files are exactly what the builder creates with Code → New section for a section named “Feature list” that starts With repeatable items. The schema is the same for every runtime:
src/sections/feature-list/schema.json
src/sections/feature-list/index.tsx
Spread block.attrs on each block’s root element. It adds data-jm-block, which lets the editor select and highlight the block in the preview.

React

A section is the default export of index.tsx. It receives SectionProps:
string
Section instance id.
string
Section type (folder name).
string
Template being rendered: index, product, page.about…
object
Resolved settings: stored values over schema defaults.
BlockProps[]
Every enabled block in order, nested ones included.
BlockProps[]
Top-level blocks only. Nested blocks are in each block’s children.
Import store data and helpers from @/platform, for example useStore, useRouteProduct, useCart, useCurrency, useGlobalSettings, Media, RichText and ThemeIcon.

Liquid

Liquid sections use liquidjs with Shopify syntax.
  • settings is this section’s values. theme is the global theme settings.
  • blocks (also block_list) lists every enabled block. root_blocks lists top-level blocks only.
  • {{ }} output is HTML-escaped. Use | raw only for richtext and html settings: {{ section.settings.body | raw }}.
  • Filters: money, money_without_currency, url, image_url, asset_url, handleize, json, stars, plus every liquidjs built-in.
  • Use | url for every internal link. It produces a store-relative link that works in the preview and on the live store.
  • Snippets live in snippets/<name>.liquid: {% render 'product-card', product: p %}.
  • Markup re-renders when data changes (cart, preview edits). Put animation code in script.ts. It exports mount(el, ctx), returns a cleanup, and runs again after each render.

Vite

A Vite section exports mount(el, ctx) and, optionally, update(el, ctx) to patch the DOM instead of remounting.
Build DOM with createElement and textContent. Never put store text into innerHTML. Internal links use store-relative paths such as /product/slug; the platform routes them.

Runtime data

Liquid sees these as top-level variables. Vite modules get them as ctx. To add to cart, open the cart or check out from Liquid and Vite markup, see Commerce attributes.