Overview
A configuration template captures the possibility space for a configurable product — the option tree and the entity references a configurator session walks through. Materials don’t live in a separate library; each one references an entity in the shared entity registry. A template is authored once per product line and reused across every customer order the line serves. A concrete walk through the template is saved as a revision under a Configuration — the Configuration is the container for one customer order, and each revision is an immutable snapshot of the selections and material assignments made against the template. The Configurator drives the walk. Templates live in the templates list on the Configurator page; create one with the New template action.“Template” is an overloaded word. A configuration template (this page) is not a data pipeline and not a report template — three unrelated features happen to share the name. This page is only about the option tree a Configurator walks.
Structure
Every template is a tree with two typed sibling lists at every level —materials (parts that are always included) and option_classes (decision points that branch). There is no polymorphic components array; a material and an option class are distinct kinds of nodes.
Top-level fields:
Materials
Option Classes
Options
Each option carriesoption_id, name, its own materials[], and its own option_classes[]. Nesting is recursive: picking an option can expose nested option classes that were invisible until then — choosing diesel-engine reveals a turbo-configuration class beneath it. Nested classes only become reachable once their containing option is selected.
The instructions Field
instructions on materials and option classes is prose read at decision time. Use it for:
- Cross-tree rules — “If
chassis-size: heavyis selected, thetow-packageclass must includeclass-iv-hitch.” - Sourcing rules — “Pin
voltagefrom the customer’s electrical spec; default to the entity’s standard voltage if absent.” - Decision criteria — “Choose
aluminumfor corrosive environments; steel otherwise.”
The revision_log Field
revision_log is a chronological changelog. A one-line entry is appended when a structural change is made to an existing template mid-run — splitting a static material into a select_one class to accommodate a new quantity, or adding an option because a customer order didn’t fit. It stays empty when authoring the initial template.
Creating a Template
Two paths:From scratch
Best for a new product line where you already know the decision shape.- Create the entities the template will reference. Every entity that appears on a material must exist first, and each must carry a
part_numberattribute (see prerequisites below). - Create the template with a name, description, and the
entity_idof the finished good. - Add top-level materials for everything that’s always included.
- Add top-level option classes for the first-level decisions.
- Under each option, add nested materials and nested option classes as the decision tree requires.
- Fill
instructionson any class or material with non-obvious sourcing rules, cross-tree constraints, or decision criteria. - Save. Leave
revision_logempty.
From an ERP or config-table export via pipeline
Best when the shape of the product already lives in an ERP config table or a spreadsheet. Ingest the source through a pipeline whose output is the template:- Point the pipeline at the config table (or upload it).
- Map the description column to each material’s
name, and derive itsentity_idslug from the same description — not from the part-number column. - Map the quantity column to
quantity. - Do not map part numbers into the template. Carry them separately so they can be pinned per revision when the Configurator runs.
- Review the generated template — option-class structure and
instructionsalmost always need a manual pass, because source tables rarely encode decision semantics.
Recording the derivation as a pipeline (rather than a one-shot import) lets the template retrace to its source when the ERP config changes.
Editing a Template
Templates are editable throughout their life, in two contexts:- Between runs — edit freely. Existing configurations reference materials by
material_id, so don’t rename those keys. - Mid-run — allowed when a customer order doesn’t fit the current option set. The Configurator gates the change through an ask-confirm turn; on approval the template is updated, a one-line entry is appended to
revision_log, and the run resumes against the updated template.
Mid-run edits change the template globally — every other configuration against the same template sees the update on its next state-script call.
Authoring Rules and Prerequisites
material_idis stable. Revisions pin to it; renaming amaterial_idbreaks the addressing key for every prior revision that referenced it. Add a new material and phase the old one out instead.- A
part_numberattribute is required on every referenced entity, declared withattr_type: text. Text typing accommodates alphanumeric numbers (likePN-1001-A) and lets a not-yet-numbered part be pinned to a placeholder value until the real number lands. If the attribute is missing when the Configurator reaches the material assignment phase, add it to the entity definition first. - Part numbers do not live on template materials. They belong on revisions as material-assignment attribute values.
quantityis fixed at the template level. If the same part appears in two contexts with different quantities, model two separate materials with different IDs. If quantity itself is a customer decision, model it as aselect_oneoption class where each option carries a differently-quantified material.- Entities before templates. A template’s material references resolve at write time; every entity must already exist.
- Slugs are unique per factory.
Limits and Caveats
- Cross-class rules in
instructionsare not machine-enforced; selections that violate them are not rejected automatically. Declarative constraints are a planned capability; until they land, prose is the only mechanism. - Deep option trees (4+ levels) are supported but hard to walk and hard to reconfigure — keep nesting shallow when the product allows it.
option_idmust be unique within its own option class;option_class_idmust be unique across the whole template, since selections address classes by ID. A class in one option can technically share an ID with a class in a different option, but conflating them makes the audit trail hard to read.- Renaming
material_idafter any configuration has been built is the single most common way to break existing revisions.

