Skip to content

Repeat Reference

tempus2016 edited this page Oct 28, 2026 · 3 revisions

Repeat Reference

Every key that makes a template repeat, and everything each copy is given, one row each. This page is for looking something up. For how to use them, with longer examples, see Repeating a Template (a card per item), Repeating Sections and Badges (a section, badge or view per item) and List Entries (an entry per item inside a card's own list).

On this page: Sources · Patterns · Filters · Which filters each source reads · Leaving things out · Order and how many · What each copy is given · Which value wins · Keys on the card · Strategies · List entries · When nothing comes out


The two ways to say what to repeat over

Key What it does Example
for_each A copy per item of a list you write out. An item is a mapping of values, and a single mapping counts as a list of one for_each: [{light: light.kitchen_ceiling}, {light: light.hall}]
for_each_from (v1.1.0+) A copy per thing Home Assistant knows about: entities, areas, devices, floors, labels, the dashboard's views, or a list a Jinja template works out for_each_from: {domain: light, area: Kitchen}

When both are set, for_each wins. Both work on a custom:decluttering-card-plus card (the template has to build a card), in a view or dashboard strategy, and inside a card's own lists through repeat:.

type: custom:decluttering-card-plus
template: light_tile
columns: 3
for_each_from:
  domain: light
  area: Kitchen
  sort: name

Sources

A for_each_from needs one of these, or one of the filters on its own (any but include_hidden and entity_category, which only widen a sweep), which then sweeps entities. With none of them it is not a repeat at all, and the card is built once: sort, limit, group_by, include_hidden, entity_category and the other shaping keys do not count.

Key Repeats over Example
entities (v1.1.0+) Entities, by id pattern. true means all of them. This is the source when no other is given. An id written out in full is kept even when hidden (v2.0.0+), and one Home Assistant has a state for but no registry entry (sun.sun) is added after the rest entities: 'sensor.*_temperature'
areas (v1.1.0+) Areas, by id or name areas: true
devices (v1.8.0+) Devices, by id or name (the name you gave it, if you renamed it) devices: 'Hue *'
floors (v1.8.0+) Floors, by id or name floors: true
labels (v1.8.0+) Labels, by id or name. Every label in the registry gets a copy, even one nothing carries labels: 'room_*'
views (v2.0.0+) The views of the dashboard the card is on, by title or path, in the dashboard's order views: true
subviews (v2.0.0+) With views: include subviews, which are left out otherwise subviews: true
template (v2.0.0+) The list a Jinja template renders, worked out once when the card is built template: "{{ states.light | selectattr('state','eq','on') | map(attribute='entity_id') | list }}"
range (v1.2.0+) A fixed number of copies, at most 1000. Only the position values and total are given, and no shaping key applies range: 5

Any value here can hold placeholders (v2.4.0+), filled in from the card's variables before anything is looked up: for_each_from: {area: '[[room]]'}. The same goes for a source a repeat: reads. See Filters built from the card's variables.

If more than one source is written, one is used, in this order: range, template, views, areas, devices, floors, labels, then entities.

A template: source's list can hold entity ids (each copy gets the entity values), mappings (each copy gets the mapping's keys) or anything else (each copy gets item). Until Home Assistant answers, the card shows nothing; a result that is not a list repeats nothing and says why in the browser console.

More: Repeating over what Home Assistant knows.


Patterns

Every source and filter takes a single pattern, a list of them (any may match), or true for everything.

  • * is the only wildcard, and matches any run of characters, none included: sensor.*_temperature, *kitchen*.
  • The whole id or name has to match, not part of it: kitchen matches the area Kitchen, not Kitchen Island. Write kitchen* for both.
  • Case does not matter.
  • Nothing else is special. There is no ?, no [abc], no regular expression: light.a+b matches only light.a+b.
  • unit: is the exception: it is compared exactly, case included, with no wildcard. unit: kWh does not match kwh.

What a pattern is compared with:

Key Compared with
entities the entity id (not its name)
areas, area the area's id or its name
devices the device's id, or its name: the one you gave it if you renamed it, otherwise the original
floors, floor the floor's id or its name
labels, label the label's id or its name
views the view's title or its path
domain the part of the entity id before the dot
device_class the entity's device class
integration the integration that provides it (hue, mqtt, template…)
state_class the entity's state class
category the category's id or its name

Filters

These narrow an entity sweep. Every filter given has to match.

Key Keeps Example
domain (v1.1.0+) Entities of these domains domain: [light, switch]
area (v1.1.0+) Entities in these areas: the entity's own area, or its device's when it has none area: Kitchen
floor (v1.1.0+) Entities on these floors floor: Ground floor
label (v1.1.0+) Entities carrying these labels, on the entity or on its device. An area's labels do not count for what is in it label: night_lights
device_class (v1.2.0+) Entities reporting these device classes device_class: [door, window]
integration (v1.2.0+) Entities from these integrations integration: hue
unit (v2.0.0+) Entities whose state reports this unit, exactly unit: '°C'
state_class (v2.0.0+) Entities with these state classes state_class: total_increasing
category (v2.0.0+) Entities filed under these categories. Each copy also gets category, the name it matched category: Heating
include_hidden (v2.0.0+) Hidden entities too, which a sweep leaves out include_hidden: true
entity_category (v2.0.0+) diagnostic or config entities too (or all, or true), which a sweep leaves out. Adds to the sweep rather than narrowing it entity_category: diagnostic
exclude (v1.2.0+) Everything except these. See below exclude: sensor.fridge_*

include_hidden and entity_category apply to the sweep they are written in. Under an area, device, floor or label source, write them inside with:, since that is where the entities are gathered.


Which filters each source reads

A filter a source does not read is ignored without a warning, so check here before wondering why a filter did nothing.

Source Reads
entities every filter above, plus group_by
areas area, floor, label (the area's own labels), exclude, with
devices area (the device's area), floor, label (the device's labels), exclude as patterns, with
floors exclude as patterns, with
labels exclude as patterns, with
views subviews, exclude as patterns (titles or paths)
template for a list of entity ids: the entity filters and exclude. Otherwise none
range none, and no shaping either

So {devices: true, domain: light} lists every device, and the way to get "devices that have a light" is {devices: true, with: {domain: light}}, which drops the devices with nothing gathered.


Leaving things out: exclude

(v1.2.0+)

Written as Leaves out Example
a pattern, or a list For entities: these entity ids. For areas, devices, floors and labels: these ids or names. For views: these titles or paths exclude: [sensor.fridge_*, sensor.freezer_*]
a mapping For entity and area sources: anything matching every filter in it exclude: {area: Garage, domain: sensor}

A mapping is one test, not a list of them: {area: Garage, domain: sensor} leaves out the sensors in the garage, and keeps the garage's lights and every other room's sensors. To leave out two unrelated things, use two repeats or a pattern list. Other sources read only entities from a mapping. What is excluded always wins over what is included.


Order and how many

These run in this order: overrides, require, sort, reverse, then offset and limit. range ignores all of them.

Key What it does Example
sort (v1.2.0+) Orders the copies. name (the default, except for views and template, which keep their own order), entity or id, area, domain, or floor (for area copies; entity copies have no floor to sort by). Any other word sorts by that value of the copies (v1.3.0+), numbers in number order (decimals and negatives too, v2.4.0+): entity_count, level. attr:<name> sorts by a state attribute (v1.5.0+). A leading - reverses one key, and a list breaks ties (v1.5.0+). none keeps Home Assistant's order (v1.3.0+) sort: [-attr:current_temperature, name]
reverse (v1.2.0+) Turns the whole order round reverse: true
limit (v1.2.0+) At most this many copies limit: 6
offset (v1.5.0+) Skips this many first, so two cards can split one list offset: 6
require (v1.5.0+) Drops a copy whose named values are empty. A name the copies never carry drops them all require: area
overrides (v1.5.0+) Extra values for particular copies, keyed by a pattern matched against what the copy is: an entity's id, an area's id or name, a device's, floor's or label's id or name (v2.4.0+), a group_by group (v2.4.0+), a view's path or title (v2.0.0+), or a template: copy's item (v2.0.0+). range copies cannot be targeted overrides: {light.kitchen_*: {colour: amber}}
group_by (v1.8.0+) Entity sweeps only: one copy per domain, area, floor or label instead of per entity. Any other word gives no copies. An entity with no value for it is left out; with label, an entity is in every group it carries group_by: area
with (v1.2.0+; devices, floors, labels v1.8.0+) For an area, device, floor or label source: the entities to gather for each copy, as a set of filters. Copies with nothing gathered are dropped unless keep_empty: true. Gathered entities are always in name order with: {domain: light}

sort, limit and the like inside with: are ignored; they apply to the copies, not to what each one gathers.

Values read for sorting (a name, an attribute) are read when the card builds. The card builds again when entities, devices, areas, floors, labels or categories change, not on every state change.


What each copy is given

These are the values a copy's placeholders can use, on top of the card's own variables:. Everything Home Assistant supplies is plain text, never read as a placeholder.

Name Given by Is
index (v1.1.0+) every repeat the copy's position, from 1
count (v1.1.0+) every repeat how many copies were built
index0, first, last (v1.2.0+) every repeat the position from 0, and whether this is the first or last copy
total (v1.2.0+) for_each_from how many matched, before limit and offset
entity, name, domain, area, area_id an entity source the entity id, its name, its domain, its area's name and id (empty when it has none). There is no floor
category (v2.0.0+) a source narrowed by category the category's name
area_id, area, area_icon, floor areas the area's id, name, icon (empty when unset) and its floor's name
device_id, device, name, area, area_id, manufacturer, model (v1.8.0+) devices the device, its name (twice), where it is and what it is
floor_id, floor, name, level (v1.8.0+) floors the floor, its name (twice) and its level (empty when unset)
label_id, label, name (v1.8.0+) labels the label and its name (twice)
items, entities, entity_count (v1.2.0+) areas, devices, floors or labels with with what was gathered: items is a list of entity copies (entity, name…), entities the ids, entity_count how many
group, name, items, entities, entity_count (v1.8.0+) group_by the group's value, its name, and what fell into it
name, path, navigation_path, icon, view_index (v2.0.0+) views the view, a link to it, its icon, and its position among all the views from 0
the mapping's keys, or item (v2.0.0+) template what the template listed; a list of entity ids gives the entity values instead
the item's keys for_each whatever each item holds

count and total differ when limit or offset cuts the list, and when a template's required: true declaration drops copies with nothing for that variable: total is what matched, count is what was built.

# Each area, with how many lights are in it
for_each_from:
  areas: true
  with:
    domain: light
# the template can use [[area]], [[area_id]], [[area_icon]], [[floor]],
# [[items]], [[entities]], [[entity_count]], [[index]], [[count]], [[total]]…

Which value wins in a repeat

For each copy, first wins:

  1. the template's let: and any decluttering_let (see Which value wins);
  2. the copy's own values, with its overrides;
  3. the card's variables:;
  4. the position values (index, count…);
  5. the defaults, as for any card.

So a value on the card fills in what a copy does not carry, but cannot change what it does: variables: [{name: Lamp}] on a card repeating over lights leaves every copy its own name. Use overrides to change particular copies, or a different variable name.

In a strategy the order is the item, then the entry's variables, then the strategy's variables, then the position values.


Keys on the card

Beside for_each or for_each_from on a custom:decluttering-card-plus card.

Key What it does Example
columns How many copies side by side. Defaults to 1, a stack columns: 3
min_column_width (v1.1.0+) Pixels. Drops a column rather than letting copies get narrower min_column_width: 160
gap (v1.2.0+) Pixels between copies. Leave it out for Home Assistant's spacing gap: 8
empty (v1.2.0+) A card to show when there are no copies. Used exactly as written: its placeholders are not filled empty: {type: markdown, content: All quiet}
lazy (v2.0.0+) Builds copies only as they come near the screen, after the first few. Off in the editor's preview and while debugging lazy: true
lazy_eager (v2.0.0+) How many copies lazy builds straight away. Defaults to 6 lazy_eager: 9
template_by_domain (v2.0.0+) Lets each copy pick its own template by its entity's domain. Each one has to build a card template_by_domain: {light: light_tile, default: plain_tile}
grid_options (v1.2.0+) The size of the whole repeat in a sections view grid_options: {columns: full}

More than 50 copies on one card logs a warning suggesting lazy: true. See Repeating a Template.


Strategies

A view strategy repeats sections and badges; a dashboard strategy repeats views. Each entry under sections:, badges: or views: either is written out as it should appear, or is a repeat:

Key What it does Example
for_each / for_each_from What to repeat over, exactly as on a card for_each_from: {areas: true}
section / badge / view What each copy is. Its placeholders are filled from the copy, and every templated card inside it is handed the copy's values section: {type: grid, cards: [...]}
variables Values every copy of this entry gets variables: {colour: teal}
empty What to show when nothing matches. Used as written empty: {type: grid, cards: []}

An entry with a repeat but no section:, badge: or view: produces nothing. A views: source inside a dashboard strategy produces nothing either, since there are no views yet. Generated view paths are made safe for a URL (Living Room becomes living-room), and a path someone wrote by hand keeps it.

More: The view strategy, The dashboard strategy, Repeating Sections and Badges.


List entries

(v2.3.0+)

repeat: puts a copy of an entry into a card's own list once per item, rather than repeating the whole card:

entities:
  - '[[row|repeat:lights]]'        # one row per light, spliced into the list
  - type: divider

repeat: reads a list variable, or a variable holding any for_each_from mapping. Each copy gets the item's keys (a plain value is item, and entity too when it looks like an entity id) plus index, index0, count, first and last. Copies that come out empty are dropped (v2.3.2+). A template: source gives no copies here.

More: List Entries, with: and repeat:.


When nothing comes out

Work down this list.

Check Why
Does for_each_from name a source or a filter? sort, limit, group_by, include_hidden, entity_category and the like alone are not a repeat: the card builds once, as if there were no repeat
Is the filter one this source reads? Which filters each source reads: a filter it does not read is ignored, which shows more, not less
Are the entities hidden, or diagnostic or config ones? A sweep leaves those out (v2.0.0+). Add include_hidden: true or entity_category: all (inside with: for area and other sources)
Is the pattern matching the whole id? kitchen is not kitchen_island. Use *
Is group_by one of domain, area, floor, label? Anything else gives no copies
Does require name a value the copies carry? A name nobody carries drops every copy
Does the template declare a variable required: true? Copies with nothing for it are dropped
Is it filtering by category or label names? Those registries are fetched after the page loads; give it a moment
Is it a template: source? It must render a list; the browser console says what it got instead
Is it a views: source in a dashboard strategy? There are no views to list yet

The card editor's match preview shows what a for_each_from matches right now, and debug: console shows every copy's values.


Next

Clone this wiki locally