Skip to content

Templates

LCARdS cards support dynamic content through four template syntaxes. You can mix them freely in most string values.


Syntax Overview

1. Token Templates {...}

Simple substitutions for entity state, attributes, theme values, and data source values.

yaml
text:
  label:
    content: "{entity.state}"                          # Entity state
  sublabel:
    content: "{entity.attributes.brightness}"          # Attribute
  title:
    content: "{theme:colors.text.onDark}"              # Theme token
  reading:
    content: "{ds:temp}"                              # DataSource: HA-native (locale-formatted + unit)

Available tokens:

TokenValue
{entity.state}Current entity state string
{entity.attributes.NAME}Any entity attribute by name
{theme:token.path}Theme token value — see Themes

For DataSource values ({ds:...}), see Section 4 below.


2. JavaScript Templates [[[...]]]

For any logic or calculation. Return the final value.

yaml
text:
  label:
    content: "[[[return entity.state === 'on' ? 'Active' : 'Inactive']]]"

  brightness:
    content: "[[[return Math.round(entity.attributes.brightness / 255 * 100) + '%']]]"

  climate_status:
    content: >
      [[[
        const state = entity.state;
        const temp = entity.attributes.current_temperature;
        return state === 'heating' ? `Heating to ${entity.attributes.temperature}°` : `${temp}°`;
      ]]]

Available context:

VariableTypeContents
entityobjectCurrent entity state — entity.state, entity.attributes.*, entity.entity_id, entity.last_changed
hassobjectFull Home Assistant object — hass.states, hass.services, hass.user, hass.themes
configobjectThis card's full config
themeobjectCurrent theme token tree

3. Jinja2 Templates {{...}}

Evaluated server-side by Home Assistant. Supports all HA template functions.

yaml
text:
  label:
    content: "{{ states('sensor.temperature') }}°C"
  status:
    content: "{% if is_state('light.kitchen', 'on') %}On{% else %}Off{% endif %}"
  diff:
    content: "{{ (states('sensor.temp_inside')|float - states('sensor.temp_outside')|float)|round(1) }}°"

NOTE

Jinja2 templates are evaluated asynchronously by HA. There may be a brief delay before values appear after a page load.


4. Data Source Templates {ds:...} / {datasource:...}

For values from a named data source. The {ds:name} shorthand and the {datasource:name} long form are equivalent.

No format specifier → HA-native display: locale-formatted number + unit from entity metadata (e.g. 4,73 °C). Equivalent to HA's haFormatEntityState().

With a format specifier → you own the output. The number is formatted to the spec and returned with no auto-unit — append any suffix you want.

SpecifierExampleResult
(none){ds:temp}4,73 °C — HA-native, locale-formatted + unit
:.Nf{ds:temp:.1f}4,7 — N decimal places, no unit
:int{ds:temp:int}5 — rounded integer, no unit
:.N%{ds:progress:.0%}75% — percentage
:str{ds:label:str}raw string coercion

To access a specific processor buffer, use the long form with a dotted path:

yaml
data_sources:
  temp:
    entity: sensor.temperature
    processing:
      f: { type: convert_unit, from: c, to: f }

text:
  value:
    content: "{ds:temp}"                    # HA-native: "4,73 °C"
    # content: "{ds:temp:.2f} °C"           # explicit precision: "4,73 °C" (no auto-unit)
    # content: "{datasource:temp.f:.0f}"    # processor buffer: "76" (Fahrenheit, no unit)

See Data Sources for declaring and configuring sources.


Where Templates Work

Templates are evaluated in most string-valued config properties:

  • text.*.content — label text
  • style.* — style values, including colours and token references
  • tap_action.service_data.* — action parameters
  • tap_action.navigation_path — dashboard path
  • tap_action.url_path — URL
  • icon — icon name
  • rules.*.when.*.condition — rule condition expressions (JS and Jinja2) — see Rule Conditions

Template Evaluation Order

When a value could match multiple syntaxes, evaluation proceeds in this order:

  1. [[[...]]] — JavaScript (evaluated first)
  2. {token} — Token substitution
  3. {ds:...} / {datasource:...} — data source
  4. {{...}} — Jinja2 (HA server-evaluated, async)

Entity Tracking & Reactivity

LCARdS re-renders a card (and re-evaluates all its templates) whenever a relevant entity changes state.

Automatic tracking

Entity references in Jinja2 templates are detected automatically — no extra config needed:

yaml
text:
  label:
    content: "{{ states('sensor.temperature') }}°C"   # ✅ auto-tracked
  status:
    content: >-
      {% if is_state('binary_sensor.motion', 'on') %}
        Motion detected
      {% endif %}                                       # ✅ sensor tracked automatically

The following Jinja2 call patterns are scanned: states(), state_attr(), is_state(), is_state_attr(), has_value()

Manual tracking with triggers_update

JavaScript templates ([[[...]]]) are opaque to static analysis — LCARdS cannot know which entities they reference. Declare them explicitly:

yaml
type: custom:lcards-button
entity: light.kitchen
triggers_update:
  - binary_sensor.desk_sensor_motion
  - sensor.toronto_temperature

text:
  label:
    content: |
      [[[
        const motion = hass.states['binary_sensor.desk_sensor_motion']?.state;
        const temp   = hass.states['sensor.toronto_temperature']?.state;
        return motion === 'on' ? `Motion (${temp}°)` : 'Clear';
      ]]]

triggers_update also works for token or data source templates whose entity IDs are assembled dynamically and cannot be inferred at parse time.

NOTE

triggers_update is additive — the card's primary entity is always tracked regardless.