Beyond Basic: Mastering Home Assistant Blueprints for Reusable, Parameterized Automations

NGC 224
DIY Smart Home Creator
Intro: The Challenge of Repetitive Automations
As your Home Assistant setup grows, you inevitably encounter a common problem: repetitive automations. You might have a dozen motion-activated lights, each with slightly different timings or conditions, leading to a sprawling automations.yaml
file that's hard to manage, update, and debug. Copy-pasting and tweaking individual automations is not scalable, especially for those managing larger smart homes or integrating solutions for clients.
This is where Home Assistant Blueprints shine. Blueprints are a powerful feature that allows you to define a template for an automation, which can then be instantiated multiple times with different parameters. Think of them as functions or classes for your automations: write once, configure many times. They drastically reduce redundancy, improve maintainability, and empower you to share complex automation logic across your smart home or even with the broader Home Assistant community. This guide will take you beyond the basics, demonstrating how to craft sophisticated, parameterized blueprints that solve real-world problems.
Step-by-Step Setup: The Anatomy of an Advanced Blueprint
Before diving into a complex example, let's break down the core components of a Home Assistant Blueprint and set up a foundational understanding. A blueprint is essentially a YAML file with specific metadata, input definitions, triggers, conditions, and actions.
1. Blueprint File Structure
Blueprints reside in your Home Assistant configuration directory under blueprints/automation/
. You can organize them further into subdirectories, but for simplicity, we'll place our example directly here.
homeassistant/
├── blueprints/
│ └── automation/
│ └── my_custom_blueprint.yaml
└── configuration.yaml
└── ...
2. Basic Blueprint Header and Inputs
Every blueprint starts with a header defining its name, description, and required inputs. Inputs are the configurable parameters that make your blueprint reusable.
blueprint:
name: Motion-Activated Light with Advanced Control
description: Turns on a light when motion is detected, with configurable brightness, timeout, and a lux threshold.
domain: automation
input:
motion_sensor:
name: Motion Sensor
selector:
entity:
domain: binary_sensor
device_class: motion
target_light:
name: Target Light
selector:
entity:
domain: light
brightness_level:
name: Brightness Level (0-255)
default: 180
selector:
number:
min: 0
max: 255
mode: slider
timeout_minutes:
name: Timeout (minutes)
default: 5
selector:
number:
min: 1
max: 60
unit_of_measurement: minutes
lux_sensor:
name: Optional Lux Sensor (for daylight)
description: Only activate if ambient light is below this threshold (optional).
default: {}
selector:
entity:
domain: sensor
device_class: illuminance
multiple: false
lux_threshold:
name: Lux Threshold
description: Maximum lux level for activation (only if lux sensor is provided).
default: 100
selector:
number:
min: 0
max: 1000
step: 10
mode: slider
Explanation:
domain: automation
: Specifies this blueprint is for automations.input:
: Defines the parameters. Each input has aname
,description
,default
(optional), and aselector
.selector:
: This is crucial for user experience. It dictates how the input appears in the Home Assistant UI when configuring an automation from this blueprint. Examples:entity
(for picking devices/entities),number
(for numerical values with sliders/steps),boolean
,select
, etc.default: {}
forlux_sensor
: Allows the input to be optional. If not provided, it will be an empty dictionary, which we'll handle in conditions.
3. Triggers, Conditions, and Actions with Inputs
Now, let's integrate these inputs into the actual automation logic.
# ... (blueprint header and inputs from above)
alias: "Motion-Activated Light: {{ blueprint_inputs['target_light'] }}"
trigger:
- platform: state
entity_id: !input motion_sensor
from: "off"
to: "on"
condition:
- condition: template
value_template: >
{% if not blueprint_inputs['lux_sensor'] %}
true # No lux sensor provided, so no lux condition
{% else %}
{{ states(blueprint_inputs['lux_sensor']) | float(0) < blueprint_inputs['lux_threshold'] | float(0) }}
{% endif %}
action:
- service: light.turn_on
target:
entity_id: !input target_light
data:
brightness: !input brightness_level
- delay:
minutes: !input timeout_minutes
- service: light.turn_off
target:
entity_id: !input target_light
Explanation:
!input motion_sensor
: This syntax is how you reference the values provided for your inputs directly within triggers, conditions, or actions.alias: "Motion-Activated Light: {{ blueprint_inputs['target_light'] }}"
: Theblueprint_inputs
variable gives you access to all input values within Jinja2 templates, allowing for dynamic naming.- Conditional Logic with Inputs: The
condition
block demonstrates how to use templating to make parts of your blueprint optional based on input. If nolux_sensor
is provided, the condition always evaluates totrue
. Otherwise, it checks the lux level. - Dynamic Service Calls: The
action
uses!input target_light
for the entity and!input brightness_level
for the service data, making the light and its settings configurable.
4. Loading and Using the Blueprint
Save the above YAML as my_custom_blueprint.yaml
in your blueprints/automation/
folder. Then, go to Settings -> Automations & Scenes -> Blueprints in Home Assistant and click the "Reload Blueprints" button (three dots menu). Your blueprint should now appear under the "Community Blueprints" (or "My Blueprints" if not in the default community paths) section. Create a new automation from it, and you'll see the UI fields generated by your selectors.
Troubleshooting Common Blueprint Issues
Developing blueprints can sometimes be tricky. Here are common pitfalls and how to resolve them:
- Blueprint Not Showing Up:
- Incorrect Path: Ensure your YAML file is in
<config_dir>/blueprints/automation/
. - YAML Syntax Errors: Even a single indentation error can prevent loading. Use an online YAML linter or a good IDE (like VS Code with Home Assistant YAML extension) for validation. Check Home Assistant logs (
home-assistant.log
) for parsing errors. - Missing Reload: Always reload blueprints via Settings -> Automations & Scenes -> Blueprints -> Reload Blueprints.
- Incorrect Path: Ensure your YAML file is in
- Automation Not Triggering/Working:
- Input Mismatch: Double-check that the entity IDs or values selected in the automation configuration match what your triggers/conditions expect.
- Template Errors: Complex templates are prone to errors. Use Home Assistant's Developer Tools -> Template editor to test your Jinja2 templates, especially the conditions and dynamic parts that use
blueprint_inputs
. - Logs, Logs, Logs: The Home Assistant logs are your best friend. Look for errors related to the automation firing or conditions failing. Increase logging level for
homeassistant.components.automation
if necessary. - State Changes: Verify the entities used in triggers are actually changing state as expected (Developer Tools -> States).
- Selector Issues in UI:
- Incorrect Domain/Device Class: If your entity selector isn't showing the right entities, verify the
domain
ordevice_class
specified in the selector. - Missing Default for Optional Inputs: If an input is optional, ensure you provide
default: {}
(for entity selectors) or an appropriate default value to prevent errors when the user doesn't provide input.
- Incorrect Domain/Device Class: If your entity selector isn't showing the right entities, verify the
Advanced Blueprint Configuration & Optimization
Take your blueprints further with these advanced techniques:
1. Complex Input Selectors
Beyond simple entities, leverage more powerful selectors:
target:
for selecting areas, devices, or multiple entities.select:
for predefined options (e.g., HVAC mode: "heat", "cool", "auto").boolean:
for on/off toggles.text:
for custom string inputs.
hvac_mode:
name: HVAC Mode
selector:
select:
options:
- "heat"
- "cool"
- "auto"
- "off"
notification_target:
name: Notification Recipient
selector:
target:
entity:
domain: persistent_notification
device:
integration: mobile_app # e.g., for mobile app notifications
2. Dynamic Actions with Jinja2 Templating
Use templates within your actions for highly flexible behavior. The choose
action is particularly powerful when combined with inputs.
action:
- choose:
- conditions:
- condition: template
value_template: "{{ !input hvac_mode == 'heat' }}"
sequence:
- service: climate.set_hvac_mode
target:
entity_id: !input climate_entity
data:
hvac_mode: "heat"
- conditions:
- condition: template
value_template: "{{ !input hvac_mode == 'cool' }}"
sequence:
- service: climate.set_hvac_mode
target:
entity_id: !input climate_entity
data:
hvac_mode: "cool"
default:
- service: persistent_notification.create
data:
message: "Invalid HVAC mode selected for {{ blueprint_inputs['climate_entity'] }}"
title: "Blueprint Error"
This snippet demonstrates using an !input hvac_mode
to dynamically select which service call to make, adding robust decision-making directly into your blueprint.
3. Version Control for Blueprints
For more complex or shared blueprints, use Git to version control them. Store your blueprints/
folder in a Git repository. This allows you to track changes, revert to previous versions, and collaborate. You can even host your blueprints on GitHub and use them as a source for HACS (Home Assistant Community Store) for broader sharing.
Real-World Example: An Advanced HVAC Zone Controller Blueprint
Let's build a blueprint that allows you to define a "smart zone" for your HVAC system, reacting to temperature sensors, maintaining a target temperature, and optionally adhering to schedules, all from a single, reusable template.
Problem Statement
You have multiple rooms, each with its own temperature sensor and perhaps a smart thermostat or HVAC controller. Manually creating automations for each room to maintain comfort levels, especially with different schedules or setpoints, is tedious and error-prone.
Solution: HVAC Zone Controller Blueprint
This blueprint will take a temperature sensor, a climate entity (e.g., your thermostat), a target temperature, and a heating/cooling mode. It will then automatically adjust the climate entity based on the sensor readings.
blueprint:
name: Advanced HVAC Zone Controller
description: Maintains a target temperature for a specific zone using a sensor and climate entity.
domain: automation
input:
zone_name:
name: Zone Name
description: A unique name for this HVAC zone (e.g., "Living Room").
selector:
text: {}
temperature_sensor:
name: Zone Temperature Sensor
selector:
entity:
domain: sensor
device_class: temperature
climate_entity:
name: Climate Control Entity
description: The thermostat or climate device to control for this zone.
selector:
entity:
domain: climate
target_temperature:
name: Target Temperature
default: 21.0
selector:
number:
min: 15
max: 30
step: 0.5
mode: slider
unit_of_measurement: "°C"
hvac_mode_control:
name: HVAC Mode for Zone
description: Set the desired HVAC mode (heat, cool, auto, off).
default: "auto"
selector:
select:
options:
- "heat"
- "cool"
- "auto"
- "off"
temperature_tolerance:
name: Temperature Tolerance (°C)
description: How much the actual temperature can deviate from target before adjustment.
default: 0.5
selector:
number:
min: 0.1
max: 2.0
step: 0.1
mode: slider
unit_of_measurement: "°C"
alias: "HVAC Zone: {{ blueprint_inputs['zone_name'] }}"
trigger:
- platform: state
entity_id: !input temperature_sensor
not_to:
- "unavailable"
- "unknown"
- platform: state
entity_id: !input climate_entity
attribute: hvac_action # Trigger if thermostat mode changes externally
condition: [] # Conditions are handled within the actions for dynamic mode changes
action:
- variables:
current_temp: "{{ states(blueprint_inputs['temperature_sensor']) | float(0) }}"
target_temp: "{{ blueprint_inputs['target_temperature'] | float(0) }}"
tolerance: "{{ blueprint_inputs['temperature_tolerance'] | float(0) }}"
hvac_mode: "{{ blueprint_inputs['hvac_mode_control'] }}"
- choose:
# Case 1: Heating required
- conditions:
- condition: template
value_template: "{{ hvac_mode in ['heat', 'auto'] and current_temp < (target_temp - tolerance) }}"
- condition: template
value_template: "{{ states(blueprint_inputs['climate_entity']) != 'heat' }}" # Avoid redundant calls
sequence:
- service: climate.set_hvac_mode
target:
entity_id: !input climate_entity
data:
hvac_mode: "heat"
- service: climate.set_temperature
target:
entity_id: !input climate_entity
data:
temperature: "{{ target_temp }}"
- service: persistent_notification.create
data:
message: "{{ blueprint_inputs['zone_name'] }} is too cold ({{ current_temp }}°C). Heating to {{ target_temp }}°C."
title: "HVAC Alert"
# Case 2: Cooling required
- conditions:
- condition: template
value_template: "{{ hvac_mode in ['cool', 'auto'] and current_temp > (target_temp + tolerance) }}"
- condition: template
value_template: "{{ states(blueprint_inputs['climate_entity']) != 'cool' }}" # Avoid redundant calls
sequence:
- service: climate.set_hvac_mode
target:
entity_id: !input climate_entity
data:
hvac_mode: "cool"
- service: climate.set_temperature
target:
entity_id: !input climate_entity
data:
temperature: "{{ target_temp }}"
- service: persistent_notification.create
data:
message: "{{ blueprint_inputs['zone_name'] }} is too hot ({{ current_temp }}°C). Cooling to {{ target_temp }}°C."
title: "HVAC Alert"
# Case 3: Temperature within tolerance, set to off if not auto
- conditions:
- condition: template
value_template: "{{ current_temp >= (target_temp - tolerance) and current_temp <= (target_temp + tolerance) }}"
- condition: template
value_template: "{{ hvac_mode not in ['auto', 'off'] and states(blueprint_inputs['climate_entity']) != 'off' }}"
sequence:
- service: climate.set_hvac_mode
target:
entity_id: !input climate_entity
data:
hvac_mode: "off"
# Case 4: Explicitly set to 'off' if blueprint mode is 'off'
- conditions:
- condition: template
value_template: "{{ hvac_mode == 'off' and states(blueprint_inputs['climate_entity']) != 'off' }}"
sequence:
- service: climate.set_hvac_mode
target:
entity_id: !input climate_entity
data:
hvac_mode: "off"
This blueprint showcases:
- Multiple input types, including a unique zone name.
- Using
variables
within the action to store calculated values, improving readability and reusability. - Complex
choose
action with multiple conditions to handle heating, cooling, and maintaining within tolerance. - Conditional service calls to avoid redundant commands to the climate entity.
- Sending persistent notifications for proactive alerts.
By saving this, you can now create an automation for your "Living Room" by selecting its sensor, thermostat, and setting a target temperature, then another for your "Bedroom" with different parameters, all without duplicating automation logic.
Best Practices & Wrap-up
To truly master Home Assistant Blueprints and build a robust, maintainable smart home, consider these best practices:
- Clear Documentation: Always provide a detailed
description
for your blueprint and comprehensivename
s anddescription
s for each input. This is critical for yourself and anyone else using your blueprint. - Sensible Defaults: Where possible, provide reasonable
default
values for inputs to make the blueprint easier to use out-of-the-box. - Robust Templating & Error Handling: Use Jinja2's
| default()
filter or conditional checks (e.g.,if ... else ...
) in templates to gracefully handle cases where entities might be unavailable or inputs are unexpectedly empty. - Modularity: While powerful, don't try to cram every possible feature into a single blueprint. Keep them focused on a specific problem or use case. If an automation becomes too complex, consider breaking it into multiple, smaller blueprints or helper scripts.
- Testing & Debugging: After creating a blueprint, instantiate it as an automation and thoroughly test all its conditions and actions. Utilize the Developer Tools -> States and Template sections, along with the Home Assistant logs, to debug any issues.
- Version Control: For any blueprint you invest significant time in, store it in a Git repository. This protects against accidental loss and makes sharing and collaboration easier.
- Security Considerations: Be mindful of what information your blueprint might expose if shared publicly. While unlikely for most automations, avoid hardcoding sensitive API keys or credentials directly into a blueprint intended for distribution.
- Community Contribution: Once you've perfected a blueprint, consider sharing it on the Home Assistant Community Forum or contributing it to HACS. The community thrives on shared knowledge and solutions.
Blueprints transform Home Assistant from a powerful home automation platform into an incredibly flexible development environment for your smart home. By leveraging their reusability and parameterization, you can build a more elegant, maintainable, and scalable system, freeing you from the repetitive drudgery of copy-paste automations.

NGC 224
Author bio: DIY Smart Home Creator