The YAML Composer features a template system that drastically reduces repetition in your configuration files. Instead of copying and pasting code, you can write a single template to define multiple similar devices.
I’m going to post some examples of how I’m using it in my installation.
This is an ongoing process so I’ll be posting more as I go.
I’ve been asking Gemini to help me tidy up the syntaxes here. It produced some minor syntax errors, but after I corrected them, Gemini then produced the correct syntax.
The result is pretty amazing I think. My initial version was very messy and unstructured. Gemini helped me come up with a clean structure.
Visual Studio Code Settings
In the vscode settings, add this so it doesn’t show the error wiggly lines on our custom tags:
{
"yaml.customTags": [
"!for",
"!if",
"!if mapping",
"!var",
"!var mapping",
"!include",
"!include mapping",
"!insert",
"!insert mapping",
"!elseif",
"!elsif",
"!elif",
"!else",
"!literal",
"!literal mapping",
"!sub",
"!sub mapping",
"!deep",
"!remove",
"!replace",
"!replace mapping",
"!default",
"!default mapping",
"!freeze",
"!freeze mapping",
],
}
Defining My Semantic Locations
This first example demonstrates the for loop ability coupled with template recursion.
(I asked Gemini to come up with / generate the recursion scheme for me)
It enables me to edit and define my locations in a very simple hierarchy that’s easy to instantly see and understand.
Note: !for loops were just merged into 5.3 snapshot. Loops are not yet supported in 5.2.
Template, variables, aliases/anchors are available in 5.2.
version: 1
variables:
# Hierarchical location structure for the home, with indoor and outdoor locations
locations:
Indoor:
FrontEntry:
Hallway:
LivingRoom:
Kitchen:
LoungeRoom:
LaundryRoom:
Garage:
BedRooms:
MasterBedRoom:
MasterBathRoom:
MasterToilet:
BedRoom1:
BedRoom2:
StudyRoom:
StudioRoom:
MainBathRoom:
MainToilet:
Outdoor:
Driveway:
FrontPorch:
FrontYard:
BackYard:
BackPorch:
ClothesLine:
SwimmingPool:
# Centralized location properties lookup table
location_config:
# Indoor Locations
Indoor: {tags: [Indoor], icon: "if:lucide:home"}
FrontEntry: {tags: [Entry], icon: "if:lucide:door-open"}
Hallway: {tags: [Corridor], icon: "if:material-symbols:hallway-outline"}
LivingRoom: {tags: [FamilyRoom], icon: "if:lucide:sofa"}
Kitchen: {tags: [Kitchen], icon: "if:lucide:cooking-pot"}
LoungeRoom: {tags: [FamilyRoom], icon: "if:lucide:tv"}
LaundryRoom: {tags: [LaundryRoom], icon: "if:lucide:washing-machine"}
Garage: {tags: [Garage], icon: "if:lucide:car"}
BedRooms: {tags: [Bedroom], icon: "if:lucide:bed-double"}
MasterBedRoom: {tags: [Bedroom], icon: "if:lucide:bed-double"}
MasterBathRoom: {tags: [Bathroom], icon: "if:lucide:bath"}
MasterToilet: {tags: [Bathroom, Toilet], icon: "if:material-symbols:wc"}
BedRoom1: {tags: [Bedroom], icon: "if:lucide:bed"}
BedRoom2: {tags: [Bedroom], icon: "if:lucide:bed"}
StudyRoom: {tags: [Room], icon: "if:lucide:laptop"}
StudioRoom: {tags: [Room], icon: "if:lucide:palette"}
MainBathRoom: {tags: [Bathroom], icon: "if:lucide:bath"}
MainToilet: {tags: [Bathroom, Toilet], icon: "if:material-symbols:wc"}
# Outdoor Locations (Includes preposition)
Outdoor: {tags: [Outdoor], icon: "if:lucide:trees", prep: "in"}
Driveway: {tags: [Carport], icon: "if:material-symbols:garage-door-outline", prep: "on"}
FrontPorch: {tags: [Porch], icon: "if:material-symbols:deck-outline", prep: "on"}
FrontYard: {tags: [Garden], icon: "if:lucide:flower-2", prep: "in"}
BackYard: {tags: [Garden], icon: "if:lucide:sun", prep: "in"}
BackPorch: {tags: [Porch], icon: "if:material-symbols:deck-outline", prep: "on"}
ClothesLine: {tags: [Outdoor], icon: "if:lucide:shirt", prep: "near"}
SwimmingPool: {tags: [SwimmingPool], icon: "if:material-symbols:pool-outline", prep: "at"}
templates:
create_location_groups:
!for name, children in node_map:
!var conf: ${location_config[name] || {}}
${name}:
type: Group
label: "${name | label}"
icon: ${conf.icon || "iconify:carbon:floorplan"}
tags: ${conf.tags || [name]}
!if parent_name:
groups: ["${parent_name}"]
!if conf.prep:
metadata:
preposition: ${conf.prep}
# Recurse into children if the map value contains child entries
!if children && !children.isEmpty: !insert
template: create_location_groups
vars:
node_map: ${children}
parent_name: ${name}
items: !insert
template: create_location_groups
vars:
node_map: ${locations}
parent_name: null
Output
# ==============================================================================
# Generated by openHAB 5.3.0 (Build #5555) YAML Composer, DO NOT EDIT
# Source: yamlcomposer/semantic_locations.yaml
# Generated: 2026-08-24T18:39:44.226776352+10:00[Australia/Brisbane]
# ==============================================================================
version: 1
items:
Indoor:
type: Group
label: Indoor
icon: if:lucide:home
tags:
- Indoor
FrontEntry:
type: Group
label: Front Entry
icon: if:lucide:door-open
tags:
- Entry
groups:
- Indoor
Hallway:
type: Group
label: Hallway
icon: if:material-symbols:hallway-outline
tags:
- Corridor
groups:
- Indoor
LivingRoom:
type: Group
label: Living Room
icon: if:lucide:sofa
tags:
- FamilyRoom
groups:
- Indoor
Kitchen:
type: Group
label: Kitchen
icon: if:lucide:cooking-pot
tags:
- Kitchen
groups:
- Indoor
LoungeRoom:
type: Group
label: Lounge Room
icon: if:lucide:tv
tags:
- FamilyRoom
groups:
- Indoor
LaundryRoom:
type: Group
label: Laundry Room
icon: if:lucide:washing-machine
tags:
- LaundryRoom
groups:
- Indoor
Garage:
type: Group
label: Garage
icon: if:lucide:car
tags:
- Garage
groups:
- Indoor
BedRooms:
type: Group
label: Bed Rooms
icon: if:lucide:bed-double
tags:
- Bedroom
groups:
- Indoor
MasterBedRoom:
type: Group
label: Master Bed Room
icon: if:lucide:bed-double
tags:
- Bedroom
groups:
- BedRooms
MasterBathRoom:
type: Group
label: Master Bath Room
icon: if:lucide:bath
tags:
- Bathroom
groups:
- MasterBedRoom
MasterToilet:
type: Group
label: Master Toilet
icon: if:material-symbols:wc
tags:
- Bathroom
- Toilet
groups:
- MasterBedRoom
BedRoom1:
type: Group
label: Bed Room 1
icon: if:lucide:bed
tags:
- Bedroom
groups:
- BedRooms
BedRoom2:
type: Group
label: Bed Room 2
icon: if:lucide:bed
tags:
- Bedroom
groups:
- BedRooms
StudyRoom:
type: Group
label: Study Room
icon: if:lucide:laptop
tags:
- Room
groups:
- Indoor
StudioRoom:
type: Group
label: Studio Room
icon: if:lucide:palette
tags:
- Room
groups:
- Indoor
MainBathRoom:
type: Group
label: Main Bath Room
icon: if:lucide:bath
tags:
- Bathroom
groups:
- Indoor
MainToilet:
type: Group
label: Main Toilet
icon: if:material-symbols:wc
tags:
- Bathroom
- Toilet
groups:
- Indoor
Outdoor:
type: Group
label: Outdoor
icon: if:lucide:trees
tags:
- Outdoor
metadata:
preposition: in
Driveway:
type: Group
label: Driveway
icon: if:material-symbols:garage-door-outline
tags:
- Carport
groups:
- Outdoor
metadata:
preposition: on
FrontPorch:
type: Group
label: Front Porch
icon: if:material-symbols:deck-outline
tags:
- Porch
groups:
- Outdoor
metadata:
preposition: on
FrontYard:
type: Group
label: Front Yard
icon: if:lucide:flower-2
tags:
- Garden
groups:
- Outdoor
metadata:
preposition: in
BackYard:
type: Group
label: Back Yard
icon: if:lucide:sun
tags:
- Garden
groups:
- Outdoor
metadata:
preposition: in
BackPorch:
type: Group
label: Back Porch
icon: if:material-symbols:deck-outline
tags:
- Porch
groups:
- Outdoor
metadata:
preposition: on
ClothesLine:
type: Group
label: Clothes Line
icon: if:lucide:shirt
tags:
- Outdoor
groups:
- Outdoor
metadata:
preposition: near
SwimmingPool:
type: Group
label: Swimming Pool
icon: if:material-symbols:pool-outline
tags:
- SwimmingPool
groups:
- Outdoor
metadata:
preposition: at
Defining General Groups
This demonstrates a nested for loop.
# Groups configuration for OpenHAB devices
version: 1
variables:
groups:
"Contact:OR:OPEN,CLOSED":
gDoorsAndWindows:
gExternalDoors: [gDoorsAndWindows]
gWindows: [gDoorsAndWindows]
gInternalDoors:
gSecuritySensors:
gLeftOpenAlert:
"Switch:OR:ON,OFF":
gSecurityLights:
gLights:
gInsideLights: [gLights]
gOutsideLights: [gLights]
gLivingRoomLights:
gLoungeRoomLights:
gMasterBedRoomLights:
gBackYardLights:
groups: [gOutsideLights]
metadata:
<<: !include "$inc/assistants.inc.yaml?tag=Light"
synonyms: "Back Porch Lights"
gBackPorch_Switch2:
gMasterBedRoom_CeilingFan: [MasterBedRoom, gInsideLights]
"Number:MAX":
gIndoorHumidity: [gHumidity]
default:
gExhaustFans:
gExhaustFanButtons:
gLightButtons:
gTemperature:
gHumidity:
gDimmers:
gBrightness:
gIPAddress:
gPresenceSimulators:
gGroupedSwitches:
gDoorBell:
items:
!for type_key, group_map in groups:
!for name, raw_conf in group_map:
# If raw_conf is a list, treat it as parent groups; otherwise use as-is
!var conf: "${raw_conf is list ? { groups: raw_conf } : (raw_conf || {})}"
"${name}":
type: Group
label: "${name.replaceFirst('^g(?=[A-Z])', '') | label}"
!if type_key != 'default':
!var type_parts: "${type_key.split(':')}"
group:
type: "${type_parts[0]}"
function: "${type_parts[1]}"
# split creates an array, not a list. Use `|length` instead of `.size`
!if type_parts | length > 2:
parameters: ${type_parts[2].split(',')}
<<: ${conf}
Output
# ==============================================================================
# Generated by openHAB 5.3.0 (Build #5555) YAML Composer, DO NOT EDIT
# Source: yamlcomposer/groups.yaml
# Generated: 2026-08-24T19:49:39.317181990+10:00[Australia/Brisbane]
# ==============================================================================
version: 1
items:
gDoorsAndWindows:
type: Group
label: Doors And Windows
group:
type: Contact
function: OR
parameters:
- OPEN
- CLOSED
gExternalDoors:
type: Group
label: External Doors
group:
type: Contact
function: OR
parameters:
- OPEN
- CLOSED
gWindows:
type: Group
label: Windows
group:
type: Contact
function: OR
parameters:
- OPEN
- CLOSED
gInternalDoors:
type: Group
label: Internal Doors
group:
type: Contact
function: OR
parameters:
- OPEN
- CLOSED
gSecuritySensors:
type: Group
label: Security Sensors
group:
type: Contact
function: OR
parameters:
- OPEN
- CLOSED
gLeftOpenAlert:
type: Group
label: Left Open Alert
group:
type: Contact
function: OR
parameters:
- OPEN
- CLOSED
gSecurityLights:
type: Group
label: Security Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gLights:
type: Group
label: Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gInsideLights:
type: Group
label: Inside Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gOutsideLights:
type: Group
label: Outside Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gLivingRoomLights:
type: Group
label: Living Room Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gLoungeRoomLights:
type: Group
label: Lounge Room Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gMasterBedRoomLights:
type: Group
label: Master Bed Room Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gBackYardLights:
type: Group
label: Back Yard Lights
group:
type: Switch
function: OR
parameters:
- ON
- OFF
groups:
- gOutsideLights
metadata:
synonyms: Back Porch Lights
alexa: Light
ga: Light
gBackPorch_Switch2:
type: Group
label: Back Porch Switch 2
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gMasterBedRoom_CeilingFan:
type: Group
label: Master Bed Room Ceiling Fan
group:
type: Switch
function: OR
parameters:
- ON
- OFF
gIndoorHumidity:
type: Group
label: Indoor Humidity
group:
type: Number
function: MAX
gExhaustFans:
type: Group
label: Exhaust Fans
gExhaustFanButtons:
type: Group
label: Exhaust Fan Buttons
gLightButtons:
type: Group
label: Light Buttons
gTemperature:
type: Group
label: Temperature
gHumidity:
type: Group
label: Humidity
gDimmers:
type: Group
label: Dimmers
gBrightness:
type: Group
label: Brightness
gIPAddress:
type: Group
label: IP Address
gPresenceSimulators:
type: Group
label: Presence Simulators
gGroupedSwitches:
type: Group
label: Grouped Switches
gDoorBell:
type: Group
label: Door Bell