Skip to content

The Engine and page rendering

Engine API surface, the render_page pipeline, template resolution, and cache policies.

Updated View as Markdown

The engine/ module owns the MiniJinja environment, theme manifests, asset pipelines, and the DataSources handle. This page documents the public API and the page-rendering pipeline.

Engine API

Engine::new_from_dir(ds, themes_dir, global_scripts)

Builds the engine from a themes/ directory. Every subdirectory becomes a theme keyed by its name (the slug). Global scripts (Vec<html::Javascript>) are injected into every render before any node scripts.

render_template(name, ctx)

Renders a template by namespaced name ("default/nodes/hero.jinja"). Errors are wrapped as Error::Template with the template name.

render_page(theme_slug, page_key, load_config, is_preview, context) -> RenderedPage

The full page pipeline (below). load_config is a caller-provided closure returning the persisted TemplateConfig for a (theme_slug, page_key, is_preview) triple; None falls back to the theme preset. The API binary uses is_preview to check draft columns before live ones.

render_node_fragment(slug, node_id, instance, depth, global) -> String

Renders one node and its full descendant subtree in isolation, no layout, no header/footer. Used by the editor for setting-change hot-swap. Applies schema defaults, resolves children, and returns the node’s HTML wrapped in the same rr-node-{id} element the storefront produces. If the node’s type no longer exists in the theme, returns an empty string (and logs) rather than failing the swap.

build_assets(theme_slug) -> AssetBuild

Content-hashes the theme’s combined CSS and JS:

Field Meaning
combined_css / combined_js The raw combined strings
hashed_css_name / hashed_js_name combined.{8-hex-hash}.css / .js for immutable CDN caching
assets_json { "combined_css": …, "combined_js": … } manifest

themes(), asset_pipelines(), data_sources(), global_scripts(), get_assets_path(slug)

Accessors for the loaded state.

The render_page pipeline

  1. Load configs, page config for page_key, plus the header-group and footer-group configs (persisted or presets), plus the _settings config. A TemplateConfig::Settings where a page was expected is an error.
  2. Merge settings, stored global settings are merged with schema defaults, then color_scheme / heading_font / body_font are surfaced into context.settings.settings, and the whole thing is merged into the StorefrontContext so templates see {{ settings.colors.primary }} etc.
  3. Resolve node trees, resolve_node_config turns each page config into a tree of ResolvedNodes (see Node resolution).
  4. Render recursively, each node renders its own template with a per-node context; the set of rendered node types is collected for CSS subsetting.
  5. Assemble assets, page_css(rendered_types) (subset + __layout__
    • color-scheme variables, preview CSS when is_preview), and scripts: global scripts, then per-node rendered JS ($$node_id$$ substituted, IIFE-wrapped), then preview JS when is_preview.
  6. Build the page context, header_html, page_content, footer_html, page_styles, page_scripts, plus every storefront global. Optional objects (product, collection, cart, article) fall back to a StubObject so chained access never crashes.
  7. Resolve the template, see below. A JSON template config falls through to render_json_page, which wraps content in a minimal shell (or the theme’s templates/404.jinja if present).
  8. Render and return, RenderedPage { html, page_styles, page_scripts, cache_headers }.

Template resolution

resolve_template_path(slug, page_key, alternate, env):

  1. templates/{page_key}.jinja, a real Jinja template wins.
  2. templates/{page_key}.{alternate}.jinja, alternate variant (not currently used by the default theme).
  3. templates/404.jinja, fallback page.
  4. Otherwise the 404 template name anyway; the render errors upstream.

JSON template configs (templates/{page_key}.json) are not registered with MiniJinja, they’re handled by the section engine through load_config (the TemplatePath::Json variant).

Cache policies

cache_policy_for(page_key):

Policy Page keys
Long product, collection, page, blog, article
None cart, checkout, all account/* pages
Short everything else
Custom { max_age, stale_while_revalidate } reserved

The CachePolicy enum (Long / Short / None / Custom) is exposed as cache_headers on RenderedPage for the API binary to emit.

Script emission

html::Javascript models script tags, RemoteScript (src/href), ContentScript (inline body), plus classic/module/nomodule ScriptTypes and CrossOrigin. Inline content escapes </script> as <\/script> so a template’s JS can’t prematurely close the tag.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close