# lovelace-thermostat-dark-card: a round dial thermostat for Home Assistant

> This Home Assistant Lovelace card draws a thermostat as an SVG dial you drag to set the temperature, supporting single and dual setpoints, preset icons and light, dark and transparent themes. It is a front end only, and it writes changes back to a climate entity through the Home Assistant websocket.

**ciotlosm/lovelace-thermostat-dark-card** — 🌡 Thermostat card with a round and black feel to it

- Repository: https://github.com/ciotlosm/lovelace-thermostat-dark-card
- Stars: 749 · Forks: 182
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/ciotlosm-lovelace-thermostat-dark-card

## A thermostat drawn as an SVG dial

lovelace-thermostat-dark-card is a Home Assistant Lovelace card, and the project describes it as a Nest-style thermostat card with a round dial interface, offering single and dual heat/cool setpoints, preset modes and multiple themes. The repository description calls it a thermostat card with a round and black feel to it.

The rendering approach is the first thing to understand, because it explains the rest. The card is pure SVG rendering, with no images, which the README describes as lightweight and optimized for low bandwidth. A dial built from vector primitives scales to any card size without a second asset, and a dashboard full of thermostats does not carry the weight of a set of raster images.

The interaction model is a ring drag. You drag on the tick ring to set the temperature, and there are also chevron controls, where tapping the up and down arrows gives precise adjustments for when a drag is too coarse. Long-press on mobile or right-click on desktop opens the Home Assistant more-info dialog for the entity, so the card is a view onto the entity rather than a replacement for it.

The card is MIT licensed, written in TypeScript, the default branch is main, and the release history shows 2.5.0 and 2.6.0 both on 2026-06-25 followed by 2.6.1 on 2026-07-13, with the last push on 2026-10-17.

One detail worth noting for a Home Assistant audience. The README is available in English, in Simplified Chinese and in Slovenčina, and the card is marked as a HACS default.

## The options table, split by who is allowed to set them

The configuration is documented in three tiers, and the tiering is the design decision that makes the card usable for people who do not want to read YAML.

The first tier is what the visual card editor exposes. The entity is required, and the name can be a string or false to hide the card title, with a separate hide_name boolean. The theme accepts dark, light, transparent or glassy, and the default is dark. There is a step override for celsius, a readonly flag that disables all interaction for a display-only card, an ambient_temperature option pointing at an external sensor entity, a status_entity whose state is shown as text above the temperature, toggles for a power button and a preset indicator, and a pending value that is the number of seconds before a temperature change is committed, defaulting to 3.

The second tier is advanced options that are YAML only, described as fine tuning behaviour rather than being exposed in the interface. There is an idle_zone, the minimum gap between low and high targets in dual mode, range_min and range_max overrides, a colors object for custom disc colours, and a preset_icons object mapping preset names to icons.

The third tier is the expert options, and the warning is the point: these are internal rendering parameters, and changing them may break the dial appearance. The diameter is the SVG viewBox size at 400, all proportions are relative to it, num_ticks is 150, tick_degrees is the 300 degree arc span of the tick marks, and show_ticks toggles them.

The tiering is a good sign of a mature custom card. A new user touches the first table, an installer fine tunes with the second, and the third is there for anyone who wants to change the physical proportions of the dial.

## The YAML you actually need, and how the card gets installed

The minimum configuration is two lines:

```yaml
type: custom:thermostat-dark-card
entity: climate.living_room
```

The type prefix of custom: is what tells Home Assistant to look for a Lovelace custom card rather than a built-in one, and the entity is the climate entity the card controls.

Installation has three routes. The recommended one is HACS, the Home Assistant Community Store, and the badge on the README links straight to the repository listing in the store. The manual HACS route is to open HACS inside Home Assistant, search for Thermostat Dark Card, install it, and restart Home Assistant. The third route skips the store entirely: download thermostat-dark-card.js from the latest release, place it in config/www/, and add it as a resource in Settings then Dashboards then Resources, with the URL set to /local/thermostat-dark-card.js and the type set to JavaScript Module.

That last step is the one to get right. A Home Assistant custom card has to be loaded as a JavaScript module rather than a plain script, and the file has to sit under the www directory to be served at the /local/ path. Both details are in the README and both are the usual reason a hand-installed card does not appear.

The card supports three themes by default. The dark theme is a black or dark grey background, the light theme is a light grey background with dark text, and the transparent theme has no disc background so it can be used with card-mod for custom backgrounds. The README gives the card-mod example with a room photo behind the card.

## Dual setpoints, idle zone, and the predictive disc colour

The dual mode is the part that separates this from a simple thermostat widget. The card adapts automatically based on the entity attributes, and in dual mode it shows a low and a high target with an idle zone between them.

The idle_zone option is the minimum gap between the low and high targets in dual mode, and it defaults to 0. That default is worth a second look, because a zero gap means the two targets can be set to the same value, and in a heat and cool system that is a configuration where the two stages are fighting each other. The option exists, and it is YAML only, so a user who wants a sensible separation has to edit the configuration rather than use the editor.

The predictive feedback is the other distinctive behaviour. The disc colour fades to show the predicted heating or cooling state while you are editing, before the change is committed. With a pending value of 3 seconds by default, the dial shows what the system is about to do rather than what it is currently doing, which is a nicer read than a card that only updates after the thermostat has reacted.

The colours involved can be overridden in YAML, with heating, cooling, idle and off each taking a colour value. The default palette is dark, and the override keys are named after the state rather than after a visual role, which is the more useful naming when you are deciding what a heating disc should look like.

## Preset icons, external sensors, and the icon vocabulary

Preset modes get their own indicator, which shows an eco leaf, a home icon, a sleep moon and others, and the mapping is a fixed list of built-in names. The available icon names are eco, away, home, sleep, boost, comfort and activity, and the built-in mappings take eco and away to a leaf, home to a house, sleep to a moon, boost to a flame, comfort to a sun and activity to a person.

The preset_icons option lets you map your own preset names to those icons, and the example uses a thermostat entity with custom names. It is the bridge for integrations that name their presets differently.

An unknown preset shows no icon unless it is mapped through preset_icons, which is worth knowing because some integrations expose their own preset vocabulary and the card will silently show nothing for them.

The ambient_temperature option lets the display use a separate sensor instead of the climate entity's own built-in sensor, which matters when the temperature you want to see is the room sensor rather than the thermostat's reading.

The status_entity option is a smaller feature with a clear use. It points at an entity whose state is shown as text above the temperature, so a card can show a heating mode label, a status word or a value from a related entity without a separate card.

## How the project is built and released

The package manifest describes a Vite build of a lit based custom card, and the runtime dependencies are just two: home-assistant-js-websocket at version 9.7.1 and lit at 3.3.2.

The websocket client is how the card reads the entity and writes the temperature back, and lit is the rendering library the card is written against. The Node requirement is 24 or newer, which is a high floor and worth checking against your build environment.

On the tooling side, the project uses Biome for everything, with a biome.json at the root and scripts for check, format, lint and their fix variants, plus a typecheck script running tsc with noEmit. Terser handles minification and Vite does the bundling, with the build script also copying the demo page into the dist directory. The dev script is a Vite build in watch mode, and the preview script serves on port 4000 bound to 0.0.0.0.

There is a demo page in the repository, with an index.html in the demo directory, and a start:hass script that runs a Home Assistant container with podman, mapping port 8123 and mounting the .hass_dev directory as the configuration. That gives a local Home Assistant to develop the card against, which is a sensible setup for a project whose output has to be tested inside a real Home Assistant instance rather than in a browser.

The release process is automated with release-please, and the repository carries a .release-please-manifest.json, a release-please-config.json and a CHANGELOG.md, so version bumps and changelog entries are generated from conventional commits rather than written by hand.

## Conclusion

Adopt this card if you want your Home Assistant dashboard to have a proper dial thermostat instead of the default tile, since it is pure SVG with no images and scales to any card size. Keep away if you need more than a climate control surface, because it renders one climate entity and the rest of the integration work is still yours. Before you install it, check that your climate entity exposes the attributes the card reads, and note that the build requires Node 24 or newer, with the runtime dependencies being lit and the Home Assistant websocket client, and the latest release being 2.6.1 from 2026-07-13.

## FAQ

### How do I install the thermostat dark card in Home Assistant?

The recommended route is HACS, the Home Assistant Community Store, using the repository link on the README. You can also open HACS inside Home Assistant, search for Thermostat Dark Card, install it and restart, or download thermostat-dark-card.js from the latest release into config/www/ and register it as a resource with the URL /local/thermostat-dark-card.js and the type JavaScript Module.

### What does the thermostat dark card need in its YAML configuration?

Two lines are enough: type: custom:thermostat-dark-card and entity: climate.living_room. The theme, step, readonly flag, ambient temperature sensor, status entity and the power and preset indicator toggles are all available in the visual card editor, while idle_zone, range overrides, colours and preset icons are YAML only.

### How do I set a custom colour or a custom preset icon on the card?

Colours are overridden in YAML with a colors object giving values for heating, cooling, idle and off. Preset icons are mapped with a preset_icons object that names your preset and gives the built-in icon to use, from the list eco, away, home, sleep, boost, comfort and activity. An unmapped preset shows no icon.

### Is the thermostat dark card still being developed?

The last push was on 2026-10-17, and releases have been frequent: 2.5.0 and 2.6.0 both on 2026-06-25 and 2.6.1 on 2026-07-13. The project is MIT licensed, and the card supports English, Simplified Chinese and Slovenčina.

## Sources

- [ciotlosm/lovelace-thermostat-dark-card on GitHub](https://github.com/ciotlosm/lovelace-thermostat-dark-card)
- [Issues](https://github.com/ciotlosm/lovelace-thermostat-dark-card/issues)
- [License: MIT](https://github.com/ciotlosm/lovelace-thermostat-dark-card/blob/main/LICENSE)
- [README](https://github.com/ciotlosm/lovelace-thermostat-dark-card/blob/main/README.md)
- [Releases](https://github.com/ciotlosm/lovelace-thermostat-dark-card/releases)

---

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