Skip to content

Migrating from Streamline card

tempus2016 edited this page Oct 27, 2026 · 1 revision

Migrating from Streamline card

Streamline card started life as a fork of the original decluttering-card, so most of a Streamline template carries straight over. You rename the templates key and the card type, and the template itself stays as it is. The one real difference is the _javascript keys, which this card does not run. Most of what they were used for can be done another way, covered below.


The two can run side by side

The two cards use different type names and different keys, so neither gets in the other's way. You can install this card, move one template across, check it, and carry on, leaving the rest on Streamline until you get to them. Remove Streamline once nothing uses custom:streamline-card any more.

What to change

Streamline Decluttering Card Plus
streamline_templates: decluttering_templates:
type: custom:streamline-card type: custom:decluttering-card-plus
template:, variables:, default: Unchanged
[[name]] placeholders Unchanged
card: and element: in a template Unchanged
!include_dir_named in a YAML dashboard Unchanged
A streamline_templates.yaml file in /config/www/ A library dashboard, see below
*_javascript keys See below

variables: and default: can be a list or a single mapping, as in Streamline. Quoting works the same way too: a placeholder that is the whole value keeps the type of what you pass, so columns: '[[cols]]' with cols: 6 gets the number 6.

An example

This Streamline template and card:

streamline_templates:
  light_template:
    default:
      - icon: mdi:ceiling-light
    card:
      type: tile
      entity: '[[entity]]'
      name: '[[name]]'
      icon: '[[icon]]'
      tap_action:
        action: toggle
      hold_action:
        action: more-info
type: custom:streamline-card
template: light_template
variables:
  - name: Living Room Light
  - entity: light.living_room

become:

decluttering_templates:
  light_template:
    default:
      - icon: mdi:ceiling-light
    card:
      type: tile
      entity: '[[entity]]'
      name: '[[name]]'
      icon: '[[icon]]'
      tap_action:
        action: toggle
      hold_action:
        action: more-info
type: custom:decluttering-card-plus
template: light_template
variables:
  - name: Living Room Light
  - entity: light.living_room

Only the first line of each changed.

Two light tiles from the converted template, a tile whose icon follows the light's state, and a button-card coloured by JavaScript

The converted light template twice, then the two _javascript replacements from the next section: an icon picked by the light's state, and a button-card coloured by its own JavaScript.

For picture elements it is the same change: an elements: entry of type: custom:streamline-card becomes type: custom:decluttering-card-plus, with style: positioning it as before. See Elements.


Replacing _javascript keys

In Streamline, a key ending _javascript is run as JavaScript and its result put under the plain key. This card does not run JavaScript from a template. A _javascript key left in is handed to the card underneath unchanged, which does not know it, so nothing happens and the plain key is simply missing. Each one needs replacing. Which way to go depends on what it did.

Let the card do it

Check first whether the card underneath already does it. A tile card colours itself by the entity's state, and shows the entity's own state icon when you do not give it one, so an icon_javascript that only swapped between two bulb icons can often just be deleted.

A value picked from the entity's state

When the value really does depend on a state, read the state with |state and pick from a table. The card has to say which entity it follows with rebuild_on:, and builds itself again whenever that entity's state changes.

Streamline:

streamline_templates:
  light_state_icon:
    card:
      type: tile
      entity: '[[entity]]'
      icon_javascript: |
        return states['[[entity]]'].state === 'on' ? 'mdi:lightbulb-on' : 'mdi:lightbulb-outline';

Decluttering Card Plus:

decluttering_templates:
  light_state_icon:
    default:
      - icons:
          'on': mdi:lightbulb-on
          'off': mdi:lightbulb-outline
    card:
      type: tile
      entity: '[[entity]]'
      icon: [[icons.[[entity|state]]]]'
type: custom:decluttering-card-plus
template: light_state_icon
rebuild_on: light.living_room
variables:
  - entity: light.living_room

on and off are quoted so they stay text: some YAML readers, Home Assistant's own for YAML-mode dashboards among them, read them as true and false. rebuild_on: goes on the card, not in the template. A state from an entity the card does not list is left as written, and the console says so. See Following an entity's state and Looking a value up by another variable.

Anything worked out from other variables

Arithmetic, text tidying, conditions on other variables and "this or else that" are all placeholder options, so a _javascript key that only combined variables usually becomes a single placeholder:

Streamline JavaScript did Here
variables.room.toLowerCase() [[room|lower]]
variables.size * 2 [[size|mul:2]]
variables.name || 'Unnamed' [[name|default:Unnamed]]
Only when another variable is set [[value|if:other]]
A value several keys need let: in the template
areas[...] for an entity's area [[entity|area]], [[entity|area_icon]]

The full list is in Variables.

Showing a card to some people only

user.name and user.is_admin were mostly used to hide things. Use a visibility: condition with condition: user instead, which Home Assistant checks itself. See Visibility.

Real JavaScript

If you need code that runs on every state change, such as styles worked out from an attribute, put it in a card that runs JavaScript itself, such as button-card's [[[ ... ]]]. This card passes it through untouched:

decluttering_templates:
  weather_button:
    card:
      type: custom:button-card
      entity: '[[entity]]'
      name: '[[name]]'
      show_state: true
      styles:
        card:
          - background-color: |
              [[[
                const t = entity.attributes.temperature;
                return t < 0 ? 'var(--info-color)' : t > 30 ? 'var(--error-color)' : 'var(--primary-color)';
              ]]]

Variables work inside that code as anywhere else. If one goes inside a quoted string in the code, write [[name|json]] rather than '[[name]]' so a quote in the value cannot break it. card-mod's Jinja, {{ states('sensor.x') }}, works the same way for styles.


Templates kept in a file

Streamline reads streamline_templates.yaml from /config/www/ and every dashboard sees it. The equivalent here is a library dashboard. Make a dashboard with the URL path decluttering-templates, put the templates under its decluttering_templates: key, and every other dashboard can use them without naming it. If you want to keep them in files, make that a YAML-mode dashboard and pull them in with !include_dir_named as before. See Sharing Templates Between Dashboards.


→ Installation · Troubleshooting

Clone this wiki locally