Liquid helpers
Every Liquid tag home-assistant.io adds on top of Markdown, from My links and glossary tooltips to text boxes and reusable snippets.
home-assistant.io is built with Jekyll, which uses Liquid for templating. On top of plain Markdown, the site adds a set of Liquid tags for things Markdown cannot do: links into the reader's own Home Assistant, glossary tooltips, icons, text boxes, and more.
Use them where they help the reader, not because they are there. Tags that wrap content, like text boxes, have a matching closing tag that starts with end:
{% tip %}
This text is inside the tag.
{% endtip %}A My link opens a page in the reader's own Home Assistant installation. Use one whenever you send the reader to a place in the interface, so they can jump straight there instead of searching through menus:
Go to {% my integrations title="**Settings** > **Devices & services**" %} and select your integration.The first word after my is the name of the page. The title is the link text. Write it as the UI path, in bold with > between the steps, the same as any UI path.
These are the My links you will need most:
- {% my areas title="**Settings** > **Areas, labels & zones**" %}
- {% my automations title="**Settings** > **Automations & scenes**" %}
- {% my backup title="**Settings** > **System** > **Backups**" %}
- {% my general title="**Settings** > **System** > **General**" %}
- {% my integrations title="**Settings** > **Devices & services**" %}
- {% my labs title="**Settings** > **System** > **Labs**" %}
- {% my logs title="**Settings** > **System** > **Logs**" %}
- {% my network title="**Settings** > **System** > **Network**" %}
- {% my profile title="**User profile**" %}Open the page in Home Assistant and press m on your keyboard. Home Assistant shows the My link for that page, if there is one. The name is the last part of the link: for https://my.home-assistant.io/redirect/logs/, it is logs.
The My link creator lists every My link, with the parameters it takes.
Most My links only need a title. A few more options exist for special cases:
badgeshows the link as a My badge image instead of text. A badge cannot have atitle.domainsets the integration for pages that need one, likeconfig_flow_start, which starts setting up a specific integration.addon,blueprint_url,brand,repository_url, andservicepass the app, blueprint, brand, repository, or action that the page should open.
{% my config_flow_start badge domain="hue" %}
{% my blueprint_import badge blueprint_url="https://example.com/blueprint.yaml" %}Without a title, the link falls back to a default text. That default does not always follow the style guide, so add a title for links in running text.
Home Assistant has its own vocabulary: entities, devices, integrations, areas, and many more. The glossary explains them. Mark a term on your page, and readers see its definition in a tooltip, often with a link to learn more:
{% term <term> [<text>] %}Some examples:
{% term integration %}
{% term entity %}
{% term "configuration.yaml" %}
{% term "Home Assistant Operating System" %}- Quote terms with spaces or dots. A single word can go without quotes.
- Aliases work too. Each glossary entry can list aliases, like a plural form. So
automationsworks as well asautomation. Matching ignores capitalization. - The term must exist. The build fails when a term is not in the glossary, so the Deploy Preview catches typos for you.
By default, the tooltip shows the term itself as the text. To put the tooltip on different words, add the text after the term:
I used an {% term automation "automation to turn on the lights" %} at sunset.You do not need to mark every occurrence of a term. Mark it the first time it appears on the page, or where a reader is most likely to stumble over it.
Missing a term, or found a definition that could be clearer? Edit source/_data/glossary.yml. Entries are sorted alphabetically, and each one can have these keys:
term: the term itself. Required.definition: the full explanation, shown on the glossary page. Required.excerpt: a shorter version for the tooltip. Add one when the definition is long.link: a page where the reader can learn more.aliases: other forms of the term that should match, like the plural.
- term: Scene
definition: >-
Scenes capture the states you want certain entities to be. For example, a
scene can specify that light A should be turned on and light B should be
bright red.
link: /integrations/scene/
aliases:
- scenesThe glossary on this site is a different one. It explains the terms used when contributing to Home Assistant.
To point at an icon in the interface, show it inline. The icons come from the Material Design Icons set on Iconify, the same set Home Assistant uses:
Select the three dots {% icon "mdi:dots-vertical" %} menu.The icon gets a tooltip based on its name. To set your own, add a title:
{% icon "mdi:dots-vertical" title="Three dots menu" %}The icons you will need most:
- Three dots menu: {% icon "mdi:dots-vertical" %}
- Hamburger menu: {% icon "mdi:menu" %}
- Edit: {% icon "mdi:edit" %}
- Revert: {% icon "mdi:restore" %}
- Eye: {% icon "mdi:eye" %}
- Trash: {% icon "mdi:trash" %}
- Cog: {% icon "mdi:cog" %}
- Cog outline: {% icon "mdi:cog-outline" %}
- Drag: {% icon "mdi:drag" %}
- Move cursor: {% icon "mdi:cursor-move" %}
- Arrow left: {% icon "mdi:arrow-left-bold" %}
- Arrow right: {% icon "mdi:arrow-right-bold" %}
- Checkbox list: {% icon "mdi:order-checkbox-ascending" %}
- Upload network: {% icon "mdi:upload-network" %}
- Security network: {% icon "mdi:security-network" %}
- Routes: {% icon "mdi:routes" %}To find the name of any other icon, search for it on Iconify, and put mdi: in front of the name.
A details block hides content until the reader opens it. Use it for content most readers can skip, like how to get credentials from a vendor, or a list of troubleshooting problems where each reader only needs one:
{% details "Generate a client ID and client secret" %}
1. Register your account as a developer account at the vendor's developer portal.
2. Create a new application.
3. Enter an **Application name** of your choice, for example **Home Assistant**.
{% enddetails %}- The title is required, in quotes. Write it so the reader knows what is inside without opening it. For troubleshooting, use the symptom or error message.
- Markdown works in the title, like backticks for code.
- Add an icon in front of the title with the
iconoption, likeicon="mdi:information". - Leave blank lines after the opening tag and before the closing tag, so the Markdown inside renders properly.
Use the Liquid details block, not the HTML <details> element. The Liquid version matches the look of the site.
Text boxes make information stand out from the text around it. They only work when they are rare: a page full of boxes has nothing that stands out. Before you add one, ask yourself if a plain sentence would do.
There are six kinds. Pick the one that matches the message:
- Tip: a recommendation that makes something easier or better. Nothing goes wrong if the reader skips it.
- Note: extra information that helps, but is not part of the main flow.
- Important: something the reader must not miss to succeed, like a requirement.
- Caution: an action that can cause data loss, unexpected behavior, or other results that are hard to undo.
- Warning: a risk to the security or integrity of the system, or of physical harm. The strongest box. Save it for when it is really needed.
- Labs: marks a feature that is a Labs preview feature, and tells the reader how to turn it on.
{% tip %}
Group your lights in an area, so you can turn them all off with one action.
{% endtip %}
{% note %}
The integration updates the data every 5 minutes.
{% endnote %}
{% important %}
Your device needs firmware version 2.0 or later.
{% endimportant %}
{% caution %}
Removing the integration also removes all its entities from your automations.
{% endcaution %}
{% warning %}
Disconnect the power before you open the device.
{% endwarning %}
{% labs %}
Requires the **Feature name** Labs preview feature. Enable it at {% my labs title="**Settings** > **System** > **Labs**" %}.
{% endlabs %}Each box shows its kind as a heading, like Tip. To add to that heading, use title. To replace the default icon, use icon:
{% note title="Older devices" icon="mdi:router-wireless" %}
Devices from before 2020 need a firmware update first.
{% endnote %}That box shows Note: Older devices as its heading.
The example block shows an automation, script, template, or other code with a label above it, and with glossary tooltips and syntax highlighting built in. Use it for examples readers are meant to understand and adapt, rather than a plain code block.
The content is YAML. Its first key sets the label, and the code goes below it as a block with |:
{% example %}
automation: |
alias: "Match fan to ceiling light"
triggers:
- trigger: light.brightness_changed
target:
entity_id: light.living_room_ceiling
options:
threshold: 10
actions:
- action: fan.set_percentage
target:
entity_id: fan.living_room
data:
percentage: >-
{{ state_attr('light.living_room_ceiling', 'brightness_pct') | int }}
{% endexample %}These keys set the kind of input, and the label shown above it. They are defined in plugins/example.rb:
actionautomationconditionscripttemplatetrigger
Use one of them per block. Three optional keys add more:
outputshows the result of the code below it, with an arrow in between. This is especially useful for templates.typenames the kind of result, shown next to the output label. For example,stringornumber.titleadds a short description to the label, like Template: Format a temperature.
{% example %}
template: |
{% from 'formatter.jinja' import format_entity %}
{{ format_entity('sensor.outdoor_temperature') }}
{{ format_entity('sensor.indoor_temperature') }}
output: |
Outdoor temperature: 22.5
Indoor temperature: 21.0
{% endexample %}The 80 character limit for code blocks applies here too. Break long templates over multiple lines with >-, like in the first example.
Some text appears on many pages, like the steps to add an integration. Instead of copying it, include a shared snippet from source/_includes:
{% include integrations/config_flow.md %}The path is relative to source/_includes. When the shared text changes, every page that includes it changes with it.
Some snippets take parameters. Check the snippet file to see which ones it reads: anything written as include.<name> in the file is a parameter.
{% include integrations/wwha.md url="https://www.eltako.com" name="Eltako" %}Snippets you will see often on integration pages:
integrations/config_flow.md: how to add an integration through the UI.integrations/option_flow.md: how to change the options of an integration after setup.integrations/remove_device_service.md: how to remove the integration.integrations/supported_brand.md: for brands supported through another integration.
Integration pages describe their options with the configuration_basic block, for options set in the UI, and the configuration block, for YAML options. Both are covered in Integration page.