Skip to content

Theme development

Everything a new developer needs to build Ringroad themes, modeled on themes/default.

Updated View as Markdown

These guides take you from zero to a working theme, following the conventions of themes/default, the reference theme this documentation models every example on. Read Themes and Jinja language first if you haven’t.

Prerequisites

  • Rust toolchain (for ringroad-renderer CLI), or just the repo, since the API loads themes at startup.
  • The concepts: nodes (the unit of editing), templates (whole-page layouts), snippets (macros), theme.json (manifest), and the four jinja extensions (@editor: markers, {% schema %}, {% stylesheet %}, {% javascript %}).

The guides

Guide Covers
Theme from scratch Directory skeleton, theme.json, layout, first node, the whole boot sequence
Writing a node Node anatomy: markup, schema, asset blocks; section vs simple; slots and children strategies
Templates and layout The page shell, page templates, snippets/macros, and the asset pipeline
Storefront data What data is available on each page type, the extra.* contract, cart/checkout/account

Golden rules

  1. A node file is self-contained. Markup, schema, CSS, and JS for one node type live in one file. Name the file after the type.
  2. Never fight the wrapper. The renderer wraps your node in rr-node rr-node--{type} with an id; style through it.
  3. Settings always have values. The engine merges schema defaults at render time, no | default() guards needed for declared settings.
  4. Tokens, not hardcoded colors. The default theme styles exclusively through var(--color-*) / var(--radius-*) / var(--spacing-*) custom properties the layout emits from global settings.
  5. data-* attributes for behavior. The default theme’s main.js drives every interaction from data-* hooks; node JS blocks only add per-node behavior scoped via $$node_id$$.
  6. Snippets are pure. Macros render from their arguments; keep request state out of them.
  7. Stubs beat 500s. Templates and nodes degrade gracefully: optional data renders empty (Lenient undefined), render_node/render_text never raise, {% include … ignore missing %} for optional snippets.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close