Mastering Jinja2 Templating in Home Assistant: Unlocking Dynamic Automations and Dashboards
- #Home_Assistant
- #Jinja2
- #Templating
- #Automation
- #Smart_Home
- #Advanced

Unlocking Dynamic Intelligence: The Power of Jinja2 Templating in Home Assistant
Home Assistant excels at unifying smart devices and enabling automation. However, relying solely on static, pre-defined rules can quickly limit the true potential of your smart home. What if you need an automation to react differently based on the time of day, the exact temperature, or even the attributes of a device? This is where Jinja2 templating becomes indispensable.
Jinja2, a powerful templating language for Python, is the secret sauce behind Home Assistant's most dynamic and intelligent features. It allows you to access real-time entity states and attributes, perform calculations, implement conditional logic, and generate custom text, transforming your smart home from a set of rigid rules into a truly adaptive ecosystem.
What is Jinja2? A Quick Primer
At its core, Jinja2 is a language designed to generate dynamic content. Think of it as a fill-in-the-blanks system where the blanks are filled with live data from your Home Assistant instance. It's extensively used across Home Assistant, from automation conditions and actions to notification messages and Lovelace UI elements.
The key syntax elements you'll encounter are:
{{ expression }}
: Used to output the result of an expression or variable. For example,{{ states('sensor.temperature') }}
will display the current temperature.{% statement %}
: Used for control structures likeif
/else
conditions orfor
loops. This code is executed but doesn't necessarily produce output itself.{# comment #}
: Used for comments within your template, which are ignored during processing.
Core Jinja2 Concepts in Home Assistant
Accessing States and Attributes
The most fundamental use of templating is retrieving information about your entities. Every entity in Home Assistant has a state
and often multiple attributes
.
The living room light is currently: {{ states('light.living_room_light') }}
The brightness is: {{ state_attr('light.living_room_light', 'brightness') }}
{# Alternative (less robust for non-existent entities) #}
Outside temperature: {{ states.sensor.outdoor_temperature.state }}°C
Use states('domain.entity_id')
to get the state and state_attr('domain.entity_id', 'attribute_name')
to get an attribute. These functions are preferred as they handle non-existent entities more gracefully than direct attribute access (states.domain.entity_id.state
).
Filters: Modifying Output
Filters are functions that modify the value of an expression. They are applied using the pipe (|
) symbol.
Rounded temperature: {{ states('sensor.outdoor_temperature') | float | round(1) }}°C
Formatted date: {{ as_timestamp(now()) | timestamp_custom('%Y-%m-%d %H:%M') }}
Default value: {{ states('sensor.non_existent_sensor') | default('unavailable') }}
Common filters include float
, int
(for type conversion), round
, lower
, upper
, title
(for string formatting), datetimeformat
, timestamp_custom
, and the crucial default
filter, which provides a fallback value if the primary value is missing or undefined.
Conditional Logic: if
/ else
Statements
Make your templates react differently based on conditions.
{% if is_state('binary_sensor.front_door', 'on') %}
The front door is open! Consider closing it.
{% elif is_state('binary_sensor.back_door', 'on') %}
The back door is open.
{% else %}
All doors are closed.
{% endif %}
You can use any valid Home Assistant template condition within an if
statement.
Loops: Iterating Over Collections
Loops are powerful for processing lists of entities or attributes.
All Lights Status:
{% for light in states.light %}
- {{ light.name }}: {{ light.state }}
{% endfor %}
This example iterates over all light entities and displays their name and state. You can also loop through lists within entity attributes.
Variables: Improving Readability
Use {% set %}
to define temporary variables within your template, improving readability and avoiding repetitive calculations.
{% set outdoor_temp = states('sensor.outdoor_temperature') | float | round(1) %}
{% set indoor_temp = states('sensor.indoor_temperature') | float | round(1) %}
The outdoor temperature is {{ outdoor_temp }}°C.
The indoor temperature is {{ indoor_temp }}°C.
{% if outdoor_temp > indoor_temp + 5 %}
It's significantly warmer outside!
{% endif %}
Practical Applications and Setup Steps
Dynamic Automations
Templates allow for highly nuanced automation logic.
- Conditional Execution: Use templates in automation conditions (
condition: template
) to trigger based on complex logic.
- alias: 'Notify if living room temperature is too high after 10 PM'
trigger:
- platform: time
at: '22:00:00'
condition:
- condition: template
value_template: "{{ states('sensor.living_room_temperature') | float > 26 }}"
action:
- service: notify.mobile_app_your_device
data:
message: "Living room is still {{ states('sensor.living_room_temperature') }}°C. Consider opening a window."
- Dynamic Service Calls: Use templates in the
data
ordata_template
section of a service call to dynamically set parameters.
# Example: Turn off the light that triggered an event (e.g., motion sensor)
- alias: 'Turn off light after motion if it was turned on by motion'
trigger:
- platform: state
entity_id: binary_sensor.motion_sensor_hallway
to: 'off'
for: '00:05:00'
action:
- service: light.turn_off
target:
entity_id: light.hallway_light
data_template:
transition: 5
brightness_pct: "{{ state_attr('light.hallway_light', 'brightness') | float * 0.5 | round(0) }}" # Fade to half brightness
The trigger
object is invaluable here, providing context about the event that triggered the automation (e.g., trigger.entity_id
, trigger.to_state.state
).
Personalized Notifications
Craft rich, context-aware messages that go beyond simple alerts.
- service: notify.mobile_app_your_device
data:
title: "Smart Home Alert"
message: >
{% set door_state = states('binary_sensor.garage_door') %}
The garage door is currently {{ door_state | lower }}.
{% if door_state == 'on' %}
It has been open for {{ (as_timestamp(now()) - as_timestamp(states.binary_sensor.garage_door.last_changed)) | timestamp_local('%H:%M') }}!
{% endif %}
Lovelace UI Enhancements
The Markdown Card is a powerful way to display dynamic information directly on your dashboard using templates.
type: markdown
content: >
# Welcome Home!
The current outdoor temperature is:
**{{ states('sensor.outdoor_temperature') | float | round(1) }}°C**.
{% set next_alarm = state_attr('sensor.pixel_5_next_alarm', 'Time') %}
{% if next_alarm %}
Your next alarm is set for: {{ as_datetime(next_alarm) | timestamp_custom('%I:%M %p', true) }}
{% else %}
No alarms set.
{% endif %}
Template Sensors
Create new virtual entities based on calculated values or combined states of other entities. This is done via the template
integration in your configuration.yaml
or through the UI via Helpers -> Template.
# In configuration.yaml under 'template:'
- sensor:
- name: "Time Until Sunset"
unique_id: time_until_sunset
unit_of_measurement: "minutes"
state_class: "measurement"
state: >
{% set now = as_timestamp(now()) %}
{% set sunset = as_timestamp(states('sun.sun')) %}
{% if sunset > now %}
{{ ((sunset - now) / 60) | round(0) }}
{% else %}
0 # Sunset has passed
{% endif %}
- binary_sensor:
- name: "Workday Today"
unique_id: workday_today
device_class: "presence"
state: >
{% set weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'] %}
{% if now().strftime('%A') in weekdays and not is_state('binary_sensor.public_holiday', 'on') %}
on
{% else %}
off
{% endif %}
Debugging Your Templates
The single most important tool for working with templates is the **Developer Tools -> Template** section in the Home Assistant UI. Paste your template code here, and it will show you the real-time output based on your current entity states. This allows for rapid prototyping and troubleshooting.
It also provides a list of available states and attributes on the right, which is incredibly useful for discovering what data is available to you.
Best Practices for Reliable Templating
- Always Test in Developer Tools: Before deploying any complex template in an automation or sensor, test it thoroughly in the Developer Tools to catch errors and ensure it behaves as expected.
- Use the
default
Filter: This is critical for robustness. If an entity isunavailable
,unknown
, or an attribute is missing, usingdefault()
prevents your template from throwing an error. For example:{{ state_attr('light.non_existent_light', 'brightness') | default(0) }}
. - Handle Type Conversions: When performing mathematical operations, ensure your values are numbers using
| float
or| int
. Data retrieved from states are often strings. - Check for Null/None: Before performing operations on potentially missing values, check if they are
none
orundefined
. For example:{% if states('sensor.my_sensor') is not none %} ... {% endif %}
- Prioritize Readability: For complex templates, use variables (
{% set %}
) to break down calculations, add comments ({# #}
), and format your code cleanly. - Consider Performance: While Jinja2 is efficient, avoid excessively complex templates that run extremely frequently (e.g., in `value_template` for many fast-changing sensor attributes). If a complex calculation is needed across multiple automations, consider creating a single Template Sensor to pre-calculate and store the value.
- Leverage the
trigger
Object: In automations, thetrigger
object provides invaluable context about the event that fired the automation, making it easy to create generic automations for multiple entities. - Consult Official Documentation: The Home Assistant templating documentation is comprehensive and regularly updated with new functions and filters.
Conclusion
Mastering Jinja2 templating is a significant step in becoming a Home Assistant power user. It liberates you from the confines of static logic, enabling you to build a smart home that truly understands and reacts to its environment and your needs in a dynamic, intelligent, and personalized way. From crafting nuanced automation conditions to delivering rich, informative notifications and building interactive dashboards, templates are the foundation of a truly advanced Home Assistant setup.

NGC 224
Author bio: