This is the field-level reference for the StorefrontContext globals
(crates/ringroad-renderer/src/data/). All id-like values are strings
(UUIDs stringified). Under UndefinedBehavior::Lenient, any missing
property renders empty, optional fields are additionally stubbed so
chained access never raises.
Top-level
| Global | Type | Notes |
|---|---|---|
store |
string | The store slug (a plain string, not an object) |
shop |
object | Store profile, see below |
settings |
object | Global theme settings, any key from theme.json settings resolves (settings.colors.primary, settings.heading_font, …) |
product |
object? | Primary product on product pages; undefined elsewhere |
collection |
object? | Primary collection on collection pages |
collections |
object | Nav collections keyed by handle |
cart |
object? | Current cart; None unless a cart token is present |
page |
object | CMS page |
search |
object | query, results_count |
blog |
object | Active blog |
article |
object? | Active article (on article pages) |
linklists |
object | Menus keyed by handle |
request |
object | path, page_type |
locale |
object | code (stub) |
extra |
object | Route-handler data bag; any key resolves |
shop
| Key | Type | Notes |
|---|---|---|
name |
string | |
currency_code |
string | e.g. "NGN" |
currency_symbol |
string | |
locale |
string | |
domain |
string | used for store-scoped URLs (/api/v1/shop/{domain}/…) |
description |
string? | |
is_publicly_visible |
bool | |
logo_url |
string? |
product (ProductObject)
| Key | Type | Notes |
|---|---|---|
id / store_id / category_id |
string | UUIDs |
name |
string | |
slug |
string | |
description |
string? | |
base_price |
integer | minor units (1999 = 19.99), format with ` |
compare_at_price |
integer? | minor units |
currency_code |
string | |
available |
bool | computed from status + stock policy |
featured_image |
string? | URL of first public image |
tags |
array | |
variants |
array | VariantObject: id, title, price (minor units), available, metafields (lazy) |
metafields |
object | lazy metafield map, product.metafields.custom.rating |
Cross-referenced products (
product_referencemetafields) are hollow shells: onlyidis populated;name/pricerender empty (documentedponytail:indata/product.rs).
collections (CollectionsListObject)
Keyed by handle: collections.summer.title. Each entry exposes id,
handle, title only.
collection (CollectionObject)
id, handle, title (no description/products_count, those exist
on the raw data but aren’t surfaced).
cart (CartObject)
| Key | Type | Notes |
|---|---|---|
items |
array | CartItemObject: variant_id, title, price (minor units), quantity (u32), image_url? |
item_count |
integer | computed (`items |
total_price |
integer | minor units |
currency_code |
string |
page (PageObject)
handle, title, content_html (pre-rendered HTML, use | safe).
blog / article
blog:handle,title.article:handle,title,content_html,published_at(RFC 3339 string).
linklists (LinklistsObject)
Keyed by menu handle: linklists["main-menu"].items. Each item:
title, url, children (nested array, dropdowns).
request / search / locale
request:path,page_type("index","product","collection", …).search:query,results_count.locale:code(stub, full localization is a later phase).
extra
Any key, value types vary by route, see Storefront data → the extra.* contract.
Page-render slots
Inside layout/theme.jinja (and templates extending it):
| Variable | Contents |
|---|---|
header_html |
rendered header-group nodes |
page_content |
rendered page nodes |
footer_html |
rendered footer-group nodes |
page_styles |
<style> block: CSS variables + page CSS subset |
page_scripts |
concatenated node JS (IIFE-wrapped, $$node_id$$ replaced) |
Node-local
Every node template also gets node, see
Templates → the node object.
Notable behaviors
- All
*Objects are truthy; unknown keys returnNone→ empty under Lenient. settings.*,extra.*,linklists.*,collections.*are dynamic-key objects, any key resolves at runtime.- Prices are integer minor units everywhere; always pipe through
| moneyfor display.