Skip to content

The settings type system

The 36 SettingDefinition variants, validation rules, default resolution, and the color cascade.

Updated View as Markdown

The schema/ module implements the settings type system that themes declare in theme.json and in node {% schema %} blocks. It has three layers: the type taxonomy (SettingDefinition), validation and defaults (load-time and render-time), and the color cascade (palette → scheme → CSS variables).

The taxonomy

SettingDefinition is a tagged enum, the JSON type field selects the variant (#[serde(tag = "type", rename_all = "snake_case")]). Each variant wraps a config struct in schema/types.rs. The 36 types group into:

Group Types
Basic inputs (8) checkbox, number, radio, range, select, size, text, textarea
Resource pickers (8) product, product_list, collection, collection_list, page, article, article_list, blog
Color (5) color, color_background, color_palette, color_scheme, color_scheme_group
Text/media (11) font_picker, html, image_picker, inline_richtext, link_list, code, metaobject, metaobject_list, richtext, text_alignment, url, video, video_url
Layout (3) header, paragraph, group

Every config struct carries id + label (+ optional info); the full field list per type is in Schema blocks → Setting types. The editor’s SettingsFormRenderer maps each type to a form control (apps/storeadmin, documented in brainstorms/13.h-theme-editor-architecture.md).

SettingType is the discriminant-only view (SettingDefinition::kind()), used by value validation.

Validation

Three operations, at three times:

Load-time schema validation, validate()

Runs on every setting at engine startup (manifest settings and every node schema). A failing schema fails engine startup, never render time:

  • range: min < max, and default within [min, max].
  • select / radio: ≥ 1 option; default must be an option value.
  • color_palette: 2–20 colors; keys must start with a letter.
  • font_picker: default required.
  • metaobject / metaobject_list: metaobject_type required.
  • size: non-empty default must be a valid CSS length; unit must be a supported unit.

Default resolution, default_value()

  • checkboxfalse when unset; select/radio → first option; range → its required default; size → its string default; color_palette → the palette object.
  • Resource pickers, url, video_urlNone (merchant must choose).
  • header / paragraph / groupNone (no value output).

Render-time merge, apply_setting_defaults()

Before a node renders, the merchant’s stored settings map is merged with the schema: missing keys get defaults; stored values that fail validate_value() are salvaged by coerce_value() where possible and otherwise fall back to the default. Structural group entries are flattened depth-first before merging (they contribute no keys), so grouped settings behave exactly like top-level ones. Value rules:

  • checkbox values must be boolean; number/range numeric.
  • code capped at 50 KB; *_list and metaobject_list capped at 50 entries.
  • size values must be valid CSS lengths (see Schema blocks → Setting types). A legacy bare number (stored by the old px range settings) is re-emitted with the setting’s unit (px default), so pre-existing merchant data keeps rendering; anything else falls back to the default.

The color cascade

Colors flow through four layers (schema/color.rs):

flowchart LR
  P[color_palette<br/>named colors] --> S[color_scheme_group<br/>semantic roles]
  S --> C[scheme picker<br/>per-section color_scheme setting]
  C --> V[generate_scheme_css<br/>--color-* variables]
  1. color_palette (theme-level), named colors like "primary": "#0f0f0f". ColorPalette::from_config parses hex (#RGB, #RRGGBB, #RRGGBBAA) into CssColor.
  2. color_scheme_group (theme-level), maps semantic roles (text, background, links, icons, primary_button, …) to palette references ("{{ settings.colors.primary }}") or literal hex. ColorSchemeGroup::resolve expands references into concrete colors and builds scheme_1 (an explicit default_scheme overrides role defaults; BackgroundValue supports solid or gradient backgrounds). Additional named schemes from settings_data.json are documented in the spec but not loaded by the renderer, multi-scheme resolution is scoped to the API binary today.
  3. Scheme picker (section-level), a node’s color_scheme setting selects which scheme applies to the section.
  4. CSS generation, generate_scheme_css emits a :root block and a .color-scheme-{id} scoped block of --color-{role} custom properties. engine/page.rs::build_css_variables calls asset::generate_css_variables with the active scheme and injects the result into the page <style>.

The default theme doesn’t use named schemes, its global colors palette is surfaced directly as {{ settings.colors.* }} and its node color_scheme selects map to CSS modifier classes instead, but the mechanism is fully implemented and exercised by the test fixture theme.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close