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
- React
- Liquid
- Vite
src/sections/feature-list/index.tsx
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 ofindex.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.@/platform, for example useStore, useRouteProduct, useCart, useCurrency, useGlobalSettings, Media, RichText and ThemeIcon.
Liquid
Liquid sections use liquidjs with Shopify syntax.settingsis this section’s values.themeis the global theme settings.blocks(alsoblock_list) lists every enabled block.root_blockslists top-level blocks only.{{ }}output is HTML-escaped. Use| rawonly forrichtextandhtmlsettings:{{ section.settings.body | raw }}.- Filters:
money,money_without_currency,url,image_url,asset_url,handleize,json,stars, plus every liquidjs built-in. - Use
| urlfor 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 exportsmount(el, ctx), returns a cleanup, and runs again after each render.
Vite
A Vite section exportsmount(el, ctx) and, optionally, update(el, ctx) to patch the DOM instead of remounting.
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 asctx.
To add to cart, open the cart or check out from Liquid and Vite markup, see Commerce attributes.

