Custom cards and more
Build cards, card features, badges, views, dashboard strategies, and panels that people load into their own Home Assistant, without changing the frontend.
The built-in cards cover a lot, but not everything. You can add your own building blocks to the interface without touching the frontend repository: write a JavaScript file, load it into Home Assistant, and use it like a built-in one. Thousands of community cards are made this way.
| What | Where it shows up | Page |
|---|---|---|
| Card | On a dashboard, next to the built-in cards | Custom cards |
| Card feature | Inside a tile card, or another card that supports features | Custom card features |
| Badge | At the top of a view | Custom badges |
| Strategy | Generates a whole dashboard, a view, or a section from code | Custom strategies |
| View layout | Arranges the cards of a view in your own way | Custom views |
| Panel | A full page of its own, with a link in the sidebar | Custom panels |
Every one of them is a custom element: a JavaScript class registered under a tag name. Home Assistant creates the element, sets properties on it, like hass and the configuration, and puts it on the page. What the element renders is up to you.
- Write the element in a JavaScript module, and register it with
customElements.define(). - Load the module into Home Assistant as a dashboard resource. Panels are loaded by their own configuration instead.
- Use it in a dashboard with the
custom:prefix, liketype: custom:my-card.
To make it easy to find, you can also register your element so it shows up in the card picker, the feature picker, or the new dashboard dialog, with a visual editor for its options.
You can use any library that produces a standard custom element, or none at all. The examples on these pages use plain JavaScript, so you can copy them and see them work without a build step.
For anything bigger, Lit is a good choice: it is what the frontend itself uses, so the patterns on the architecture pages carry over. Bundle your own copy of Lit, or any other library, into your module.
The frontend has no public component library for custom cards. Nothing in the frontend repository lists ha-* elements as supported, or promises that they stay the same. They are loaded only when the frontend needs them, and they can change in any release. If your card depends on one, it can break without warning.
ha-card is the one exception in practice, not on paper. It is the container of the built-in cards, it takes the card theme variables like --ha-card-background and --ha-card-border-radius, and most custom cards wrap their content in it, as the custom card example does. Use it so your card fits in, but know it carries the same lack of promise as the rest. For anything else, like a picker or a form field, build or bundle your own. To show a built-in card or one of the standard dialogs inside your card, use the card helpers, which the frontend loads for custom cards on purpose.
hass: the object with the full state of Home Assistant. Your element gets a new one on every change. The hass object reference lists what is in it.setConfig(config): called with the YAML configuration of your card, badge, or feature. Throw an error when the configuration is invalid, and Home Assistant shows it to the user.- The
custom:prefix: separates your elements from the built-in ones. Your elementmy-cardis used astype: custom:my-card.
A custom card looks best when it fits in with the built-in ones. Use the theme variables, like --card-background-color and --primary-text-color, so your card follows the theme and dark mode of the user. The dashboard pages of the Design area explain how the built-in cards are designed, and why.
To publish what you built, so others can install it from the Marketplace, see dashboard cards and plugins.
Think your card belongs in the frontend itself? The project recommends that you publish a new card in the Marketplace first. You gain experience, and you can iterate faster. Once it has matured and has a user base, reach out to the maintainers, for example in the #frontend channel on Discord, to see whether it should ship built in.