Open-source project
Nerwyn/universal-remote-card avatar
Nerwyn/universal-remote-card

universal-remote-card: one Home Assistant remote for every streaming box

A completely customizable universal remote card for Home Assistant. Supports multiple platforms out of the box.

612 stars37 forksTypeScriptApache-2.0

At a glance

What is it?
The Universal Remote Card is a Home Assistant dashboard card that drives a long list of media platforms from one configurable interface, with buttons, circlepads, touchpads and sliders, per-platform default key lists, template support and a visual editor. It suits a Home Assistant user with several TV boxes and streaming devices, and it is the wrong tool if you want a remote for a device Home Assistant cannot talk to.
Who is it for?
universal-remote-card fits a Home Assistant household with several media devices that each have their own integration and its own default key list, since the card ships per-platform defaults and lets you override them, and the visual editor means a remote can be laid out without hand-editing YAML.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

From the Android TV Card to a general remote

The Universal Remote Card is described as a completely customizable universal remote card for Home Assistant that supports multiple platforms out of the box, and it is described as iterating on the work of several other projects.

The name history explains a lot. The readme notes it was formerly called Android TV Card, and the repository keywords still list androidtv, android, googletv, google, tvcard, remote, tv and television. The platform list has grown well past that origin, but the design idea has not: one card, one layout, and a set of keys that means the same thing on every device.

The feature list is the substance of the project. There is a configuration user interface, so a remote can be built in the browser rather than in YAML. Out of the box support covers many platforms with default key and source lists: Android TV, Sony BRAVIA, Fire TV, Apple TV, Roku, LG webOS, Samsung TV, Kodi, Unified Remote for Windows, macOS and Linux, Philips TV, Denon AVR, Yamaha YNCA, Jellyfin, Unfolded Circle, and a generic Remote option.

The elements are not just buttons. The card supports multiple buttons, circlepads, touchpads and sliders, each using default or user defined actions, and it has complete support for Home Assistant actions, plus keyboard and search dialog actions for most platforms.

The rest is presentation. Template support for almost all fields using ha-nunjucks, accessibility keyboard controls for all components, toggleable haptics, a user configurable layout, icons and labels for every element, custom SVG icon support, and CSS style options for all sub-elements.

The four-tab editor, and how the general tab cascades

The card now has a fully featured configuration user interface. You install the project using HACS, then go to a dashboard and create a universal remote card or edit an existing one, and the editor has four tabs: General, Layout, Elements, and Icons.

The General tab is where the cascade logic lives, and it is the part to understand before you touch the other tabs. You select your media platform, then your device using the Config Entry ID field, and the latter will autofill the remote and media player ID fields if they are available for that config entry. The platform, entity ID and timing fields set in the general tab are used for default keys and sources.

The inheritance rules are more specific than that, and they are the sort of detail that produces support questions. If you do not set these fields for custom elements, they also use the general tab's fields. But if you explicitly set one of these fields in a custom element, it will not be overwritten when you change the matching general field, until you clear the field in the custom element. And to completely clear toggle fields, you must remove them from the config using the code editor, which is a real limitation of a purely visual editor and worth knowing before you rely on the GUI alone.

The readme also documents the media platform and entity IDs table, which lists per platform which of the fields are required: Remote ID, Media Player ID, Keyboard ID, Config Entry ID, Remote/Device Name and MAC Address. Some platforms require custom integrations or carry additional configuration notes, and the table links to the relevant Home Assistant integration for each platform.

Where the key lists come from, and the platform differences

The interesting engineering in the card is not the layout, it is knowing which key to send to which device.

The platform table shows how much the platforms diverge. Android TV has default keys, sources, keyboard and search, a default slider for the media player, and uses the ADB remote or media player integration for keyboard and search. Sony BRAVIA has default keys, and uses ADB for keyboard and search. Fire TV has default keys, keyboard and search, and its default sources, slider, keyboard and search. Apple TV has default keys and default sources and slider, and its keyboard comes from the config entry rather than an integration. Roku has default keys and keyboard. Every platform that supports a keyboard also has a keyboard entry, and in most cases the keyboard and search actions run through the corresponding Home Assistant remote or media player entity.

That is the trade the card is making. Rather than trying to abstract away that Android TV and Apple TV reach the keyboard through completely different mechanisms, it keeps the platform concept in the configuration and gives you a sensible default for each one.

The ADB-based platforms are worth calling out, because they need a little more setup and the readme links the relevant integration documentation for each of them. A BRAVIA television reaching the user through the Android TV remote integration, for instance, is the kind of arrangement that works but surprises people.

The card also supports the Unified Remote application for Windows, macOS and Linux, which is a different model again, since that is a server on your own machine that the card talks to rather than a device on the network.

The build, and a project that ships a built card

The repository is a TypeScript project built with rspack, and the published artefact is the bundled file. The package main is ./dist/universal-remote-card.min.js, and the build script is:

json
	"build": "npx rspack && gzip -fk dist/universal-remote-card.min.js",

So the card is distributed as a minified, gzipped bundle that Home Assistant loads directly, rather than as source that is compiled in the user's installation. That is the normal shape for a Home Assistant custom card, and it has a consequence for the rest of the workflow: the dist/ directory is checked in, so the repository contains a built artefact as well as the source that produces it.

The runtime dependencies are three and all of them are specific. lit at 3.3 or newer is the web component library the card is built on, ha-nunjucks at 1.7 or newer provides the template support, and js-yaml at 5.4 or newer handles the YAML configuration. Everything else in the dependency list is development tooling: the rspack CLI and core, TypeScript and ts-loader, eslint with the typescript-eslint plugin, prettier with the organise-imports plugin, lint-staged, lit-css-loader and a loader that minifies HTML literals, plus home-assistant-js-websocket as a development dependency for working against the Home Assistant API.

The scripts reflect a straightforward workflow. The build script produces the bundle. The lint script runs eslint with the project's own config, and a prelint step runs tsc with no emit, so type errors fail the lint. A build-css script uses tcm to handle the styles, and a setup script configures the git hooks path and installs the npm dependencies. The test script is a placeholder that exits with an error, which is the one part of the package that is not doing anything yet, and is worth knowing before you assume the card has an automated test suite.

Where universal-remote-card is the wrong choice

The first limitation is that the card is a front end for whatever Home Assistant already exposes. It does not speak to a television directly. Every key it sends is an action on a media player or remote entity, so a platform that Home Assistant cannot drive is a platform the card cannot drive. The generic Remote entry is a special case of that, and its usefulness depends on the generic remote integration you pair it with.

The second is the visual editor ceiling. The card has a full configuration user interface, and the readme is honest about the one thing it cannot do: completely clearing toggle fields requires removing them from the config using the code editor. For a card that advertises itself as super customizable, having a YAML escape hatch is reasonable, but it does mean the editor is not the whole story.

The third is the platform list as a maintenance surface. Fifteen or more platforms, each with its own default key list, its own source list and its own keyboard path, and some of them reached through a different integration than you would expect, such as BRAVIA through the Android TV integration. Every one of those defaults has to keep matching how the device and the integration behave, and a device firmware update that changes a key name breaks a default that the card cannot detect.

The fourth is that keyboard and search are not uniform. Most platforms support them and some do not, and the Apple TV row in the table has its keyboard coming from the config entry rather than from an integration. So a layout that assumes a search button works on one television will not work on the next.

The fifth is the release rhythm and the size of the platform surface. The recent tags are 4.12.1 from 2026-10-18, 4.11.5 from 2026-07-12 and 4.11.4 from 2026-07-11, so the project ships often and the version numbers track a lot of platform churn. The last push was on 2026-10-18, the same day as the 4.12.1 release, and the release title for 4.12.1 mentions custom attributes, a reworked autofill and a reversion of Android TV global search to ADB, which is a good illustration of how much of the work is tracking upstream behaviour rather than adding features.

Editorial conclusion

universal-remote-card fits a Home Assistant household with several media devices that each have their own integration and its own default key list, since the card ships per-platform defaults and lets you override them, and the visual editor means a remote can be laid out without hand-editing YAML. It is the wrong choice for a single device that Home Assistant already exposes well, and it is the wrong choice for a platform the card does not list, since the underlying action is whatever the integration exposes. Before installing it, check the platform and entity ID table for your device, install it through HACS, and note that the last push was on 2026-10-18 with version 4.12.1 released the same day.

Frequently asked questions

What platforms does the Universal Remote Card support?

Out of the box support with default key and source lists covers Android TV, Sony BRAVIA, Fire TV, Apple TV, Roku, LG webOS, Samsung TV, Kodi, Unified Remote for Windows, macOS and Linux, Philips TV, Denon AVR, Yamaha YNCA, Jellyfin, Unfolded Circle and a generic Remote option, each with the fields it requires listed in the platform and entity IDs table.

How do I install the Universal Remote Card in Home Assistant?

Install the project using HACS, then go to a dashboard and create a universal remote card or edit an existing one. The editor has four tabs: General, Layout, Elements and Icons.

What controls does the Universal Remote Card offer?

Multiple buttons, circlepads, touchpads and sliders using default or user defined actions, with complete support for Home Assistant actions, keyboard and search dialog actions for most platforms, template support for almost all fields using ha-nunjucks, accessibility keyboard controls for all components, toggleable haptics, a user configurable layout, custom SVG icons and CSS style options for all sub-elements.

How do the general tab settings interact with custom elements?

The platform, entity ID and timing fields from the general tab provide the defaults for keys and sources, and custom elements use them if they do not set those fields themselves. A custom element that does set one keeps its own value until the field is cleared, and clearing toggle fields completely requires removing them from the config using the code editor.

What licence is the Universal Remote Card released under?

Apache-2.0, with the licence file at the root of the repository. The last push was on 2026-10-18 and the newest release is 4.12.1 from the same day, following 4.11.5 in July 2026.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Nerwyn/universal-remote-card on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nerwyn-universal-remote-card.svg)](https://hysenlabs.com/projects/nerwyn-universal-remote-card)

Was this useful?