Docs
Preferences

Preferences

The install form: pages, sections and inputs, and how the wizard runs it.

preferences describes the form a person fills in when installing or editing an instance. The hub renders it as a wizard: one page at a time, with Back / Next and a progress bar.

const preferences = {
  pages: [
    {
      id: 'devices',
      title: 'Devices',
      description: 'Pick the sensor and the lights it should control.',   // optional banner
      inputs: [
        { key: 'sensor', label: 'Motion sensor', type: 'entity', domainFilter: 'binary_sensor', required: true },
        { key: 'lights', label: 'Lights', type: 'entity', domainFilter: 'light', multiple: true, required: true },
      ],
    },
    {
      id: 'timing',
      title: 'Timing',
      sections: [                                                        // inputs can be grouped
        { id: 'delay', title: 'Delay', inputs: [
          { key: 'offAfterMinutes', label: 'Turn off after (minutes)', type: 'number', default: 1, minValue: 1, maxValue: 120 },
        ]},
        { id: 'night', title: 'Night only', inputs: [
          { key: 'nightOnly', label: 'Only run between sunset and sunrise', type: 'boolean', default: false },
        ]},
      ],
    },
  ],
};

Structure

  • Pages have an id, a title, and either inputs directly or sections of inputs. Optional description shows a banner above the inputs; loadingDescription is the spinner caption while the hub prepares the page (used by discovery wizards). A page or section with a visible condition is skipped when the condition is false.
  • Inputs have a key (a valid JavaScript identifier; it becomes a global), a label, a type, and type-specific options. All fields are listed on the Input types reference.
  • Static or dynamic. preferences can be the object above or a function (values) => ({ pages }) that the hub calls with the answers so far. See Dynamic preferences.

Common input options

OptionPurpose
requiredthe wizard refuses to continue without a value
defaultpre-filled value in the form (not applied at run time — your code still handles undefined)
descriptionhelp text under the input
multipleseveral picks for entity and enum
optionschoices for enum: [{ value, label, description? }]
minValue / maxValue / unitnumeric bounds; unit (e.g. '°C') makes clients render in the home's units and store the canonical value
domainFilter / deviceClassFilternarrow an entity picker ('light', 'binary_sensor' + 'motion')
placeholder, readonly, widgetpresentation (widget: 'tiles' renders an enum as cards, 'textarea' a multi-line string)
submitOnChangere-run a dynamic preferences function as soon as this input changes
visibledeclarative show/hide condition — see Conditions and visibility

Older examples use filter: { domain, deviceClass } and defaultValue. The hub still normalises the legacy filter object into domainFilter / deviceClassFilter; defaultValue is ignored — use default.

Reading the answers in code

Every input's key becomes a global variable when its type supports it, and every answer is available in settings[key]. Which types become globals, and in what shape, is on Inputs to globals.

Validation

The wizard validates on each page: required inputs, numeric bounds, enum membership (a stored value missing from options is dropped on re-save — keep options stable or merge stored values back in), minItems / maxItems on arrays. The install only completes when the last page validates; then the hub stores the settings and calls installed (or updated).

On this page