# config-template-card: running your own JavaScript inside a Lovelace card

> This Home Assistant card exists because YAML cannot express what people actually want to show, and it does that by letting a Lovelace configuration run arbitrary JavaScript against the hass object, with the results fed back into a card, a row or an element.

**iantrich/config-template-card** — 📝 Templatable Lovelace Configurations

- Repository: https://github.com/iantrich/config-template-card
- Stars: 568 · Forks: 68
- Language: TypeScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/iantrich-config-template-card

## Why a card that runs JavaScript exists

The card is for Lovelace on Home Assistant, and it allows you to use pretty much any valid JavaScript on the hass object in your configuration. That is the whole premise, and it exists because the standard dashboard configuration language cannot express everything a user wants.

Home Assistant's Lovelace configuration is YAML, and YAML describes structure rather than behaviour. The common workaround is a Jinja template, which can compute a string but cannot easily restructure a card or choose between two different card types based on a condition. The card exists to fill that gap: you write the logic in JavaScript, and the card renders whatever your code produces.

The audience is therefore a Home Assistant user with a dashboard that has outgrown what templates can do, rather than a developer building a component library. The maintainer is Ian Richardson, the project is MIT licensed, and the primary language is TypeScript. The repository carries a HACS default badge, which is the distribution mechanism most Home Assistant custom card users already have installed, along with badges for releases, maintenance, commits and community.

There is a version floor to know about. Home Assistant version 0.110.0 or higher is required as of release 1.2.0 of the card, so on an old instance this is not an option.

## Installing it through HACS or as a Lovelace resource

There are two documented installation routes, and the second one is the one worth understanding because it explains how the card actually runs.

The recommended route is HACS, the Home Assistant Community Store, or the Lovelace plugins guide that the readme links to. That route handles the download and places the file where Home Assistant expects it.

The alternative is to add the card as a Lovelace resource yourself, which is a short entry in the resources list of your Lovelace configuration.

```yaml
resources:
  - url: /local/config-template-card.js
    type: module
```

The resource is loaded as an ES module from the local directory, which is why the entry needs the module type. The card then appears in the dashboard editor as a custom card, and the documentation lists its type as custom:config-template-card.

One thing the readme does not spell out is where the file itself comes from in this route, since the path is local. In practice that is what the HACS route and the Lovelace plugins guide are for, and the resource entry is the step that makes the browser load it.

For a first use, the quickest sanity check is to add a card with the custom type and a single entity, and see it render. Everything else in the card is an extension of that.

## The options: entities to watch, variables to compute, and what to render

The option table is small, and each option has a specific role in how the card decides what to draw.

The type option is required and is the string custom:config-template-card. The entities option is also required, and it is a list of entity strings that should be watched for updates, with templates allowed in the list. That is the trigger mechanism: the card re-runs when one of the listed entities changes, which is what makes a computed card feel live rather than static.

The variables option is optional and is a list of variables, which can themselves be templates, usable in the config and indexed using vars or by name. The card, row and element options are each optional and take a card, row or element configuration, and the documentation is explicit that one of them must be provided, since something has to be rendered. The style option is optional and takes a style configuration.

The three rendering options, card, row and element, are the interesting design decision. The same card can therefore replace a whole card, sit inside a row, or be an element inside a larger card. That is what lets it be used inside a picture-elements card, where a single element on a picture needs its own icon, its own position and its own state logic, which no amount of YAML can express.

The style option is described in the same way for each of the three levels, and the readme explains that the style object on the element configuration is applied to the element itself, with a separate note for the config-template-card level. In other words, styling is per level, which is consistent with how the card composes into the surrounding dashboard.

## The template scope: hass, states, user and your own vars

The variables available inside the template are listed in a table, and they determine what a card can actually do.

this.hass gives you the hass object, states gives you the states object, and user gives you the user object. Those three are the standard Home Assistant frontend data structures, and the readme links to the developer documentation for each. In practice, states is the one that matters, since it is how a template reads the current value of an entity.

The fourth is vars, and it is the one the card adds. The documentation is specific about its two shapes. If variables in the configuration is a YAML list, then vars is an array starting at the 0th index as your firstly defined variable. If variables is an object in the configuration, then vars is a string-indexed map, and you can also access the variables by name without using vars at all.

That dual behaviour is the practical part. A named object gives you readable code, where a template refers to a variable by its name, and a list gives you positional access, which is what the templated entities example uses, indexing vars[0] to reach the first entry.

So the mechanism for a computed card is: put your expressions in the variables option, watch the entities that those expressions depend on, and then use the results inside the card, row or element configuration.

## The example configurations, and what they show

The readme gives three examples, and together they cover the shapes a user actually needs.

The first is the general case, with variables bound to entity states and then used inside a card configuration.

```yaml
type: 'custom:config-template-card'
variables:
  LIGHT_STATE: states['light.bed_light'].state
  GARAGE_STATE: states['cover.garage_door'].state
entities:
  - light.bed_light
  - cover.garage_door
  - alarm_control_panel.alarm
  - climate.ecobee
card:
  type: "${LIGHT_STATE === 'on' ? 'glance' : 'entities'}"
  entities:
    - entity: alarm_control_panel.alarm
      name: "${GARAGE_STATE === 'open' && states['alarm_control_panel.alarm'].state === 'armed_home' ? 'Close the garage!' : ''}"
```

The card type itself is computed, so the same card shows a glance view or an entities view depending on the light state, and an entity name is computed from two other entities at once.

The second example is the templated entities case, where the entity to display is itself the result of a template.

```yaml
type: 'custom:config-template-card'
variables:
  - states['sensor.light']
entities:
  - '${vars[0].entity_id}'
card:
  type: light
  entity: '${vars[0].entity_id}'
  name: "${vars[0].state === 'on' ? 'Light On' : 'Light Off'}"
```

The third is the picture-elements case, where the card is used as an element inside a picture with its own icon and its own positioning, and the style block sets a CSS custom property for the icon colour.

Between them, the examples show a computed card type, a computed entity, and a computed element, which are the three things a YAML dashboard cannot do.

## Where config-template-card is the wrong tool

Four limits, and they are honest limits of a small community card rather than of the idea.

The first is that Home Assistant's own template language is often enough, and the card adds a debugging surface in exchange. Your logic now lives in JavaScript evaluated in the browser rather than in a template evaluated in the backend, so an error shows up in the browser console and the dashboard simply does not render, and the state of the page is harder to inspect. For a simple derived name, a Jinja template is easier to maintain.

The second is the rendering surface. The card can produce a card, a row or an element, but it does not change what those things are capable of. If you want a chart or a custom card with its own editor, the card cannot conjure it, and the three examples in the documentation all work with built-in Lovelace card types.

The third is the version floor and the release shape. The card needs Home Assistant 0.110.0 or newer, and the 2.x line is published as betas, with 2.0.0-b1 in March 2026 and 2.0.0-b2 in May 2026 fixing issue 190. The manifest version in the package file is 1.3.1 while the release tags are on 2.0.0, which tells you the version fields are not being kept in step with the published releases. A beta line in a dashboard component means the configuration you write may need adjusting when you move to the next beta.

The fourth is the dependency on a pre-release library. The card depends on lit at a release candidate version, and on the Home Assistant websocket client, which is fine for a self hosted dashboard and less fine if you need the card to keep working across a Home Assistant major upgrade.

## Licence, packaging and what to check before you install it

The licence is MIT, with a LICENSE.md in the repository, so the code can be used, modified and redistributed with the notice kept. This is not legal advice, and it is a permissive grant for a piece of code you are about to run inside your own dashboard.

The packaging is a standard modern web build. The manifest names the package config-template-card, with the built bundle as config-template-card.js, and the build is Rollup with TypeScript, Babel and terser, plus ESLint with the Airbnb base config and Prettier. There is a separate development Rollup config that starts a watcher, and the scripts are minimal: lint runs ESLint over the TypeScript sources, build runs lint and then Rollup, and rollup runs the production build.

The runtime dependencies are four: deep-clone-simple, custom-card-helpers, the Home Assistant JavaScript websocket client, and lit. The custom-card-helpers dependency is the one to know about, because that is the library that gives a Home Assistant custom card its editor and its behaviour contract, and it is where a card like this inherits most of its behaviour conventions.

The repository also carries hacs.json, which is the manifest the HACS integration reads to list the card, along with a devcontainer configuration, editor configuration files and a yarn lockfile.

For an adopter the practical checks are short. Confirm the Home Assistant version is new enough, install through HACS so the file lands where the resource entry expects it, then write one simple card that echoes a single entity state. If that works, the templating will work, because the complexity is in your JavaScript and not in the card.

## Conclusion

config-template-card is the right tool for a Home Assistant user whose dashboard needs logic that YAML cannot express, such as swapping a card type on a state change or composing an entity name from other entities, and it installs in minutes through HACS. It is the wrong tool for a dashboard that only needs standard cards, for a Home Assistant instance older than 0.110.0, and for anyone who wants a stable API, since the 2.x line is still published as betas and the manifest version does not match the release tags. Before adopting, check which Lovelace card types you need to drive and confirm they are supported, and read the style section of the documentation, since the style object is applied to the element and to the card separately.

## FAQ

### What does the config-template-card Home Assistant card do?

It is a Lovelace card for Home Assistant that allows you to use pretty much any valid JavaScript on the hass object in your configuration, so you can compute things that a YAML template cannot express, such as choosing a card type based on an entity state.

### How do I install the config-template-card?

Use HACS or follow the Lovelace plugins guide that the readme links to. The card is then added to your Lovelace resources as a module loaded from the local path /local/config-template-card.js, and the card itself is used with the type custom:config-template-card.

### What do the entities and variables options do in config-template-card?

Entities is a required list of entity strings that are watched for updates, with templates allowed, and it is what makes the card re-run. Variables is an optional list of variables, which can be templates, usable in the configuration and reachable through vars or by name, and vars is an array if variables is a YAML list or a string-indexed map if it is an object.

### What is the minimum Home Assistant version for config-template-card?

Home Assistant version 0.110.0 or higher is required, and that requirement has applied since release 1.2.0 of the card. The recent releases are on the 2.x line and are published as betas, including 2.0.0-b2 in May 2026.

## Sources

- [iantrich/config-template-card on GitHub](https://github.com/iantrich/config-template-card)
- [Issues](https://github.com/iantrich/config-template-card/issues)
- [License: MIT](https://github.com/iantrich/config-template-card/blob/master/LICENSE)
- [README](https://github.com/iantrich/config-template-card/blob/master/README.md)
- [Releases](https://github.com/iantrich/config-template-card/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/iantrich-config-template-card
