Skip to main content

Configuration Data Model

When you work with Mimeeq's observers, actions, or events, you're interacting with a layered data structure that represents how a product's configuration options are organized. Understanding this hierarchy is essential for building custom UIs, consuming configuration data, or debugging why something appears the way it does.

This article explains each layer from the bottom up: what it is, what data it carries, and how you access it.

The Hierarchy

Mimeeq organizes product configuration in up to four levels:

Container (optional)       ← High-level category, custom UI only
└─ Group ← Organizational section in the option panel
└─ Block ← A single configurable aspect (e.g., "Frame Color")
└─ Options ← The choices available (sourced from Option Sets)

Not every product uses all levels. A simple product might have a few blocks in a single group with no containers. A complex product like a configurable vehicle might use all four levels.

Options and Option Sets

Options are the individual choices a user can make — "Oak", "Walnut", "Birch" for a material block, or "Red", "Blue", "Green" for a color block.

Options live inside Option Sets, which are reusable collections managed in the Mimeeq Admin Panel. A single option set can be shared across multiple products, so updating it in one place updates all products that reference it. Option sets can also be organized into Material Collections, which group related option sets together (e.g., a "2024 Premium Fabrics" collection containing multiple fabric option sets).

Each option carries data you'll encounter in observers and event payloads:

PropertyDescription
nameDisplay name shown to users
codeConfiguration code used in the configuration string
priceCodeCode used for pricing calculations
valueInternal value
imageSrcPath to option image (thumbnails, swatches)
thumbnailAbsolute URL to the 425px thumbnail
optionSetIdWhich option set this option belongs to
hideInPdfWhether to exclude from PDF exports
hideInOptionPanelWhether to hide in the configurator UI
metafieldsCustom parameters attached to this option
tip

For special widgets (text, number, slider, color, engrave, image, print on demand), option data is structured differently. See Widget Types below.

Blocks

A Block represents a single configurable aspect of the product — "Frame Color", "Seat Material", "Width", "Engraving Text". It's the core unit of the configuration panel.

Each block has a widget type that determines how its options are presented to the user, and a mode that determines where its options come from.

You access blocks through the optionSets.blocks observer:

window.mimeeqApp.observers.optionSets.blocks.subscribe(({ newValue }) => {
if (newValue) {
newValue.forEach(block => {
console.log(block.name); // "Frame Color"
console.log(block.blockName); // "FrameColor" (identifier used in code)
console.log(block.widgetType); // "THUMBNAILS"
console.log(block.options); // Array of available options
console.log(block.optionsLength); // Number of options
});
}
});

Key block properties

PropertyDescription
idUnique identifier
blockNameName used in code, configuration codes, and the markOptionByBlockNameAndOptionCode action
nameLocalized display name
widgetTypeHow options are rendered — see Widget Types
modeHow options are sourced — LINKED, MANUAL, ENGRAVE, IMAGE, PRINT_ON_DEMAND, INPUT, COLOR, SLIDER, BUTTON, MESSAGE
optionsArray of available OptionSetOption objects
optionSetIdsIDs of option sets attached to this block
letterMappingsMaps option set IDs to letters used in configuration code encoding
clearableWhether the user can deselect (return to empty)
isDisabledWhether the block is currently disabled (e.g., by rules)
isHiddenWhether the block is hidden (e.g., by rules)
thumbnailBlock image, available for custom UIs
note

The blockName is what you pass to markOptionByBlockNameAndOptionCode. It's case-sensitive and matches the name set in the admin panel.

Block modes

The mode property tells you where the block's options come from:

ModeDescription
LINKEDUses existing Option Sets or Material Collections. Most common mode.
MANUALUses option sets created locally for this specific block.
ENGRAVEText engraving/embossing input.
IMAGEUser image upload (logos, textures).
PRINT_ON_DEMANDAdvanced image placement on print areas.
INPUTText or number input field.
COLORColor picker widget.
SLIDERNumeric slider.
BUTTONInteractive button that triggers rules. Does not store a value.
MESSAGEDisplay-only informational content. Does not store a value.

For LINKED and MANUAL modes, the block's type property further specifies whether options come from a MATERIAL_COLLECTION or an OPTION_SET.

Widget Types

The widgetType on a block controls how options are rendered in the standard UI. When building a custom UI, you'll use this value to decide which component to render for each block.

Selection widgets

These present a list of options for the user to pick from:

Widget TypeDescription
RADIO_PLAIN_TEXTVertical radio button list with text labels
NUMBERS_BUTTONRow of clickable buttons for numbers or short text
NUMBERS_SCALEScale/range selector for numeric values
SELECT_LISTBOXScrollable listbox (dropdown-like)
SELECT_RADIODropdown with radio selection
THUMBNAILSGrid of image thumbnails
THUMBNAILS_GROUPSThumbnails with a dropdown to switch between option sets
FILTERFilterable list with attribute-based narrowing
FILTER_GROUPSFilterable list grouped by attribute categories
MULTICHOICEMultiple selections allowed (checkboxes)

Input widgets

These capture direct user input rather than a selection from predefined options:

Widget TypeDescription
TEXTSingle-line text input
NUMBERNumeric input with validation
SLIDERNumeric slider with min/max range
ENGRAVEMulti-line text with font and formatting options
COLORColor picker (hex value)
IMAGEImage/texture upload
PRINT_ON_DEMANDImage upload with positioning on print areas

Non-value widgets

These don't contribute to the configuration code:

Widget TypeDescription
BUTTONTriggers rules when clicked. Omitted from configuration codes.
MESSAGEDisplays informational content. Omitted from configuration codes.
tip

When building a custom UI, the widgetType is your switch statement. Map each type to your own component, and use the block's options, inputSettings, engraveSettings, colorSettings, or printOnDemandSettings depending on which widget you're rendering.

Groups

A Group organizes related blocks into a named section. In the standard Mimeeq UI, groups appear as collapsible sections in the option panel. A product always has at least one group.

You access groups through the optionSets.blockGroups observer, which provides groups enriched with selection status:

window.mimeeqApp.observers.optionSets.blockGroups.subscribe(({ newValue }) => {
if (newValue) {
newValue.forEach(group => {
console.log(group.name); // "Upholstery"
console.log(group.hasErrors); // true if required selections are missing
console.log(group.values); // Array of { name, value } for selected blocks
});
}
});

Key group properties

PropertyDescription
idUnique identifier
nameLocalized display name
optionSetIdsIDs of blocks that belong to this group
selectMatchingIf true, selecting an option in one block will auto-select matching options in other blocks of the same group (e.g., matching fabric across seat and back)
hasErrorstrue if any block in this group has missing required selections
valuesArray of BlockSelectedValue — the current selections for each visible block
hideOnSpecificationIf true, hide this group from PDF specs and summaries
previewOptional preview image settings for the group

The hasErrors flag is your go-to for building validation indicators. When true, at least one block in the group needs attention.

Containers

A Container adds an optional higher-level grouping above groups. This is purely organizational and exists specifically for custom UI implementations — the standard Mimeeq configurator UI does not render containers.

If a product has containers defined, they appear in the optionSets.blockGroupContainers observer:

window.mimeeqApp.observers.optionSets.blockGroupContainers.subscribe(({ newValue }) => {
if (newValue && newValue.length > 0) {
// Product uses containers — build multi-level navigation
newValue.forEach(container => {
console.log(container.containerName); // "Interior"
console.log(container.hasErrors); // Aggregated from all groups
console.log(container.values); // Array of group selection data
});
} else {
// No containers — use blockGroups directly for single-level navigation
}
});

Key container properties

PropertyDescription
containerIdUnique identifier
containerNameDisplay name (e.g., "Exterior", "Interior", "Performance")
valueArray of group IDs belonging to this container
groupNamesArray of group names for display purposes
valuesAggregated selection data from all groups (with hasErrors per group)
hasErrorstrue if any group in this container has validation errors
note

Containers are optional. Many products won't have them. Always check if blockGroupContainers emits a non-empty array before building multi-level navigation — and fall back to blockGroups for single-level layout.

Selected Options

The optionSets.selectedOptions observer gives you the current configuration state — what's selected across all blocks:

window.mimeeqApp.observers.optionSets.selectedOptions.subscribe(({ newValue }) => {
if (newValue) {
// For standard products, all selections are under "SINGLE_PRODUCT_ID"
const options = newValue['SINGLE_PRODUCT_ID'];

options.forEach(option => {
console.log(option.blockId); // Which block this selection belongs to
console.log(option.name); // Display name of the selected option
console.log(option.code); // Configuration code value
});
}
});

For modular products, the keys are instance IDs instead of "SINGLE_PRODUCT_ID", with one entry per component on the scene:

// Modular: iterate over all component instances
Object.entries(newValue).forEach(([instanceId, options]) => {
console.log(`Component ${instanceId}: ${options.length} options selected`);
});

How It All Connects

Here's a practical example of how these layers relate. Consider a configurable office chair:

Container: "Seating" (only used in custom UIs)

  • Group: "Frame & Base"
    • Block: "Frame Color" (widget: THUMBNAILS, mode: LINKED)
      • Options: "Black", "Silver", "White" (from a shared Material Collection)
    • Block: "Base Type" (widget: RADIO_PLAIN_TEXT, mode: LINKED)
      • Options: "5-Star", "4-Leg", "Sled"
  • Group: "Upholstery"
    • Block: "Seat Fabric" (widget: FILTER, mode: LINKED)
      • Options: 200+ fabrics from a Material Collection with filter attributes
    • Block: "Back Fabric" (widget: FILTER, mode: LINKED)
      • Options: same Material Collection, with selectMatching linking to Seat Fabric
  • Group: "Personalization"
    • Block: "Nameplate" (widget: ENGRAVE, mode: ENGRAVE)
      • User enters custom text
    • Block: "Logo" (widget: IMAGE, mode: IMAGE)
      • User uploads an image

The standard Mimeeq UI renders the Groups and Blocks. If you're building a custom UI and the product has Containers, you can use them to create a richer navigation structure — tabs, accordions, or a step-by-step wizard.