A modern mobile-friendly dashboard for Home Assistant. Inspired by the Homio dashboard by @iamtherufus, Hemma is rebuilt and extended with new layouts, cards, and a streamlined setup process.
The dashboard is fully YAML-based and designed for:
- Desktop, tablet, and mobile (portrait + landscape)
- Light/Dark mode styling
- Flat card design with glass accents
- Badges for climate, lights, presence, media, security, and energy
- Clean navigation with desktop/tablet top navbar
Hemma ships as two dashboards: the desktop/tablet dashboard (hemma.yaml) and dedicated mobile dashboard (hemma_mobile.yaml) inspired by Apple Home. Phones are automatically routed to the mobile dashboard (and everything else back to desktop) by the included redirect script.
- Light/dark mode with dynamic background images
- Layouts + spacing logic for scaling across different devices
- Hemma theme (
hemma.yaml) β flat card design with glass accents - Demo room images included β eight pre-made day/night backgrounds to get started without your own photos
- Custom Popups for button cards
- Custom navigation and Scene support
- Motion detection built into navigation menu
- Badges (shown in the hero section of each room card)
- Climate group badge β temperature range, HVAC state, humidity, air quality
- Light group badge
- Presence + sensor badges
- Active media player badge
- Energy group badge β per-room or per-device power, usage, and cost
- Security group badge β locks, alarm panel, door/window sensors, cameras
- Now Playing β a full media panel showing every active source at once, with controls, progress, and pinnable media chips
- Button-cards
- Thermostat, media, lock, camera, network, motion, cover, energy, presence, vacuum, Plex Recently Added, and more.
- Popups
- Climate/air quality, energy usage, network, light control (multi-room + scenes), lock/security group, cover/shades group, plant monitor, battery monitor, system updates, Plex stream, and Plex Recently Added.
A dedicated phone experience inspired on the Apple Home app:
- Filter badge pills (Climate / Lights / People / Media / Security / Energy) β tap a pill and a full-screen popup slides up with every matching card from your rooms, auto-collected (no per-popup configuration)
- Room popups β tap a room's section header for a popup with all of that room's cards, plus a room-scoped sensor chip row (temperature / humidity / air quality / lights / motion) that deep-links into the matching popups
- Collapsing header with a frosted glass bar that fades in as you scroll
- Now Playing row of full-width media tiles
- Smart sections β active cards sort first, sections and popups stay in sync automatically
- Always opens on Home β the dashboard resets to the home view on every fresh load
- Lovelace dashboards enabled, and keep Lovelace in
storagemode (so you can still use the UI editor for other dashboards). - A time sensor β the clock on each room's hero card reads
sensor.time, which is not part ofdefault_config. Either add it under Settings β Devices & Services β Add Integration β Date & time (enable the "Time" sensor), or use thesensor.current_timetemplate sensor included in this repo'ssensors.yamland pointhemma_timeat it withtime_entity: sensor.current_time. Without one of the two, the clock renders blank. - Packages enabled β
packages/hemma_helpers.yamlis loaded viahomeassistant: packages: !include_dir_named packagesinconfiguration.yaml.
Install via HACS (recommended) unless noted:
- button-card (RomRider)
- layout-card (Thomas LovΓ©n) β Hemma uses a modified version included in this repo (don't install via HACS).
- lovelace-navbar-card (Jose Luis Γlvarez) - required for navigation + media badge
- browser_mod (Thomas LovΓ©n) - required for custom popups
- uix (Lint Free Technology) - required for popup card styling (replaces card-mod; don't install card-mod alongside it)
- apexcharts-card (RomRider) - required for the graphs in the climate, energy, and network popups
- kiosk-mode (NemesisRE) - Optional but highly recommended (the dashboard looks best with no header/sidebar)
- lovelace-swipe-card (Bram Kragten) - Required for the Plex Recently Added popup carousel
- plex_recently_added (NemesisRE) - Required for the Plex Recently Added card and
sensor.plex_recently_added_count
Everything in this repo is meant to live under /config in your Home Assistant installation.
Example layout:
/config
βββ configuration.yaml # Register the Hemma dashboards here
βββ dashboards/
β βββ hemma/
β β βββ hemma.yaml # Desktop/tablet dashboard (created from example)
β β βββ hemma.yaml.example # Example desktop dashboard with placeholders
β β βββ hemma_mobile.yaml # Mobile dashboard (created from example)
β β βββ hemma_mobile.yaml.example # Example mobile dashboard with placeholders
β βββ templates/
β βββ button_cards/ # Button-card templates
β β βββ badges/ # Hero-card badges (climate, lights, presence, media, energy, security)
β β βββ base/ # Shared base templates (hemma_entity, hemma_default, hemma_time, etc.)
β β βββ cards/ # Individual device cards (thermostat, media, lock, cover, energy, Plex, etc.)
β β βββ mobile/ # Mobile dashboard scaffolding (header, badge row, chips, Now Playing row)
β β βββ now_playing/ # Now Playing panel (primary tile, rail chips, artwork, transport, header)
β β βββ popups/ # browser_mod popup content (climate, energy, network, light, lock,
β β # cover, plant, battery, updates, Plex, recently-added)
β βββ includes/ # Layout + navigation includes
β βββ hemma_screen_layout.yaml
β βββ hemma_mobile_layout.yaml
β βββ hemma_navbar_tablet.yaml
β βββ hemma_navigation.yaml
βββ themes/
β βββ hemma/
β βββ hemma.yaml # Hemma theme
βββ packages/
β βββ hemma_helpers.yaml # Helpers required by the dashboards
βββ www/
βββ hemma/
βββ fonts/ # UI fonts
βββ icons/ # UI icons
βββ rooms/ # Room/background images (*-demo.jpg variants included)
βββ weather/ # Weather icons
βββ scripts/ # JavaScript resources
βββ layout-card-modified.js # Modified Layout Card build
βββ navbar-popup-caret.js # Add dropdown icon to navbar
βββ layout-offsets.js # Navbar/hero offsets track sidebar visibility
βββ swipe-card-patch.js # Plex Recently Added carousel
βββ smart-row.js # Smart entity row with active-card sorting
βββ filter-overlay.js # Mobile filter/room popups + collapsing header
βββ hemma-icons.js # Inline icon map (load first)
βββ hemma-core.js # Shared card helpers + Now Playing collector + mobile wallpaper
βββ hemma-redirect.js # Phone β mobile dashboard routing (on by default)
Make a full Home Assistant backup/snapshot before you start. YAML dashboards + themes are easy to roll back, but you'll be happier if you can restore quickly if something goes sideways.
Copy these folders/files from this repo into your HA /config:
dashboards/hemma/β/config/dashboards/hemma/dashboards/templates/β/config/dashboards/templates/(merge if you already have templates)themes/hemma/β/config/themes/hemma/packages/hemma_helpers.yamlβ/config/packages/www/hemma/β/config/www/hemma/
In Settings β Dashboards β Resources, add:
Add these two first β the others read their icons and shared entity tables from them:
/local/hemma/scripts/hemma-icons.js(from this repo)/local/hemma/scripts/hemma-core.js(from this repo, required β shared card helpers, the Now Playing collector, and the mobile wallpaper: it samples your home photos to derive the colors the mobile background fades into)
Then the rest, in any order:
/local/hemma/scripts/layout-card-modified.js(from this repo)/local/hemma/scripts/navbar-popup-caret.js(from this repo)/local/hemma/scripts/layout-offsets.js(from this repo)/local/hemma/scripts/swipe-card-patch.js(from this repo, required for Plex Recently Added popup)/local/hemma/scripts/smart-row.js(from this repo, required for Smart Row)/local/hemma/scripts/filter-overlay.js(from this repo, required for the mobile dashboard)/local/hemma/scripts/hemma-redirect.js(from this repo, recommended β routes phones to the mobile dashboard and back)/local/hemma/fonts/hanken-grotesk.css(from this repo)/hacsfiles/button-card/button-card.js(should already be present if installed via HACS)/hacsfiles/lovelace-navbar-card/navbar-card.js(should already be present if installed via HACS)
Add (or verify) in your configuration.yaml:
lovelace:
mode: storage
dashboards:
dashboard-hemma:
mode: yaml
title: "Hemma"
icon: mdi:home
show_in_sidebar: true
filename: dashboards/hemma/hemma.yaml
dashboard-hemma-mobile:
mode: yaml
title: "Hemma Mobile"
icon: mdi:cellphone
show_in_sidebar: false
filename: dashboards/hemma/hemma_mobile.yamlThe mobile dashboard is hidden from the sidebar on purpose. With hemma-redirect.js installed, phones are sent to it automatically and everything else goes back to the desktop dashboard, so nobody has to pick. Without the script, reach the mobile dashboard by its URL.
The redirect is on by default (input_boolean.hemma_dashboard_redirect). Left off, a phone opening the desktop Hemma dashboard gets desktop content rendered with the mobile CSS, which looks like a broken mobile dashboard rather than a desktop one. The redirect is only active when using the Hemma dashboard, and it can be disabled entirely by turning the helper off.
Point the theme at your own pair of photos and everything below them follows automatically:
hemma-mobile-hero-img-day: url("/local/hemma/rooms/my-home.jpg")
hemma-mobile-hero-img-night: url("/local/hemma/rooms/my-home-night.jpg")hemma-core.js reads both images and derives the gradient and mesh colors the
photo dissolves into, per mode, so the bottom of the screen blends with whatever
house is at the top. The hex values in the theme are only fallbacks for the demo
photos, and if that script is missing they paint instead, silently, and your
wallpaper ends up carrying the demo house's colors. Serve the photos from
/local/ so the sampling stays same-origin.
Restart Home Assistant.
In /config/dashboards/hemma/:
- Copy or rename
hemma.yaml.exampleβhemma.yaml - Copy or rename
hemma_mobile.yaml.exampleβhemma_mobile.yaml - Open each and replace all placeholders (search for
YOUR_)
These are the only files you edit to map Hemma to your devices/entities β all behavior lives in the shared templates.
- Settings β Appearance β Themes β choose Hemma (You may need to reload themes or restart after copying.)
- Room images live in:
/config/www/hemma/rooms/- Example:
home.jpg(light) andhome-night.jpg(dark) - Eight demo room images are included (
*-demo.jpg/*-demo-night.jpg) so you can get started without your own photos
- Example:
- Icons live in:
/config/www/hemma/icons/
You'll configure most of Hemma by editing your dashboard file:
/config/dashboards/hemma/hemma.yaml
Each view typically contains:
hemma_room(this is the main hero card)- Mobile navbar include (desktop/tablet navigation menu)
- Entity grid include
The climate group badge aggregates temperature, HVAC activity, humidity, and air quality into a single tappable badge on the hero card. Tap to expand sub-badges for temperature range, humidity, and air quality.
Dependency: The expand/collapse behavior for all badge groups (climate, lights, presence, media, energy, security) is driven by
input_select.hemma_expanded_row. This entity is defined inpackages/hemma_helpers.yamlβ make sure you have copied that file and reloaded HA (or restarted) so the entity exists before using any badge. Without it, tapping a badge group will throw a service-call error and the sub-badge row will not expand.
Badges are enabled by their entities. As of 2.0 there are no
show_*switches for the badge rows β a badge appears as soon as you give it something to show and stays hidden otherwise. The climate badge appears when any ofclimate_entity_1,temp_sensor_1,humidity_sensor, orquality_sensoris set.
| Variable | Description |
|---|---|
climate_entity_1 β climate_entity_3 |
Climate/thermostat entities β used to detect active HVAC and animate the fan icon |
temp_sensor_1 β temp_sensor_5 |
Temperature sensors β if multiple are provided, the badge shows a minβmax range |
humidity_sensor |
Humidity sensor (shown in expanded sub-badges) |
quality_sensor |
Air quality sensor (shown in expanded sub-badges) |
temp_unit |
'F' or 'C' β controls comfort label thresholds |
show_climate_inline |
true to show temp/humidity/air-quality as individual badges on the top row instead of one expandable group badge |
The light group badge shows the combined state of your room lights and lets you tap to toggle them. It appears when either light_entity_1 or light_group_entity is set.
| Variable | Description |
|---|---|
light_group_entity |
A light group covering the whole room/home |
light_entity_1 β light_entity_10 |
Light group or individual light entities |
If the group you point at sits inside a larger one, the popup opens on that larger group with a pill per room and this room selected. light_group_entity picks what the badge shows; popup_group on a hemma_light card overrides what its popup opens, and popup_group: none keeps the popup to that card's own lights.
Shows a grouped presence badge on the hero card. Tap to expand individual person badges.
Set one presence_entity_1 for a single person badge; set two or more and you get the expandable group badge instead.
| Variable | Description |
|---|---|
presence_entity_1 β presence_entity_4 |
Person status sensors |
Hemma includes a compact weather widget for both desktop and mobile/tablet views.
The widget appears when weather_entity is set.
| Variable | Description |
|---|---|
weather_entity |
Your HA weather entity |
weather_temp_sensor |
(optional) A separate sensor for outdoor temperature |
temp_unit |
'F' or 'C' β controls comfort thresholds and labels |
Template: hemma_weather
(See dashboards/templates/button_cards/.../hemma_weather.yaml for full template code.)
Media badges appear on the hero card and show what's currently playing. They auto-hide when nothing is active, and auto-show when a player becomes active (including recently paused).
They appear when media_player_1 is set β unless show_now_playing: true, in which case the Now Playing panel (documented in the next section) takes over and the badge row is suppressed so the same session can't show twice.
| Variable | Description |
|---|---|
media_player_1 β media_player_10 |
Media player entity IDs |
pause_timeout_minutes |
Minutes before a paused player is considered inactive (default: 5) |
Example home view with all badge types enabled:
- type: custom:button-card
template: hemma_room
name: Home
variables:
image: home
image_position: center center
# Climate badge β appears because climate/temp/humidity/quality entities are set
climate_entity_1: climate.living_room
climate_entity_2: climate.bedroom
temp_sensor_1: sensor.home_temperature
temp_sensor_2: sensor.living_room_temperature
humidity_sensor: sensor.average_humidity
quality_sensor: sensor.air_quality
temp_unit: 'F'
# Light badge β appears because a light entity is set
light_entity_1: light.living_room
light_entity_2: light.bedroom
# Weather widget β appears because weather_entity is set
weather_entity: weather.your_weather
weather_temp_sensor: sensor.your_outdoor_temp
# Presence badge β two entities, so the expandable group badge is used
presence_entity_1: sensor.person_one_status
presence_entity_2: sensor.person_two_status
# Media badges β appear because media_player_1 is set.
# Add `show_now_playing: true` instead to use the Now Playing panel,
# which replaces this badge row and reuses the same entities.
media_player_1: media_player.spotify
media_player_2: media_player.living_room_apple_tv
media_player_3: media_player.kitchen
media_player_4: media_player.bedroom_apple_tv
# Energy badge β appears because energy_power_entity is set
energy_power_entity: sensor.home_current_consumption
# Security badge β appears because a lock or security entity is set
security_entity_1: lock.front_door
security_label_1: Front DoorNotes: badge rows are enabled by their entities, not by show_* flags β a badge with no entities stays hidden, so there is nothing to switch off. Media badges additionally only appear when a player is actually active (playing, buffering, or recently paused within pause_timeout_minutes).
The Now Playing panel is an alternative to the media badge row. Where the badges surface one player at a time, the panel shows every active source at once: a primary tile with artwork, title, subtitle, progress bar, and transport controls, plus a rail of compact chips for everything else.
Set show_now_playing: true on a room card. hemma_room suppresses the media badge row automatically when the panel is on, so the same session never appears twice β there's nothing to switch off. The panel reuses the media_player_N entities you've already configured.
| Variable | Default | Description |
|---|---|---|
show_now_playing |
false |
true to use the panel instead of the media badge row |
now_playing_panel |
'0' |
'0' = tiles float free, right-aligned, no container. '1' = tiles wrapped in a glass panel with a collapsible "Now Playing" header |
media_player_1 β media_player_10 |
β | Standard media player entities |
plex_stream_1 β plex_stream_2 |
β | Plex/Tautulli session sensors β these tiles open the Plex popup rather than more-info |
psn_1 β psn_2 |
β | Game-activity sensors (e.g. PlayStation), shown as activity sources |
pause_timeout_minutes |
5 |
Minutes before a paused source drops out of the panel |
Interaction: tap a rail chip to promote it to the primary slot; hold to pin it there (stored in input_text.hemma_now_playing_pinned). With now_playing_panel: '1', the header collapses the panel, tracked by input_boolean.hemma_now_playing_minimized.
Requires: hemma-core.js registered as a Lovelace resource, which holds the source collector both dashboards read. The mobile dashboard's Now Playing row uses the same collector and the same tile templates.
The energy group badge adds an expandable row of value badges to the hero card. Each energy_entity_N gets one badge (up to 6). On the Home view these are typically per-room figures; on a room it's usually a single badge showing that room's running cost.
| Variable | Description |
|---|---|
energy_power_entity |
Current consumption, shown in this view's energy popup |
energy_usage_today / energy_usage_month |
Daily / monthly consumption for the popup |
energy_cost_today / energy_cost_month |
(optional) Cost sensors for the popup |
energy_entity_1 β energy_entity_6 |
The sensor behind each sub-badge |
energy_label_N |
Badge title β falls back to the entity's friendly name |
energy_unit_N |
auto (W, switching to kW above 1000), kwh, or cost |
energy_cost_N |
(optional) Cost sensor appended to the value as Β· $1.23. Two numbers on one badge is hard to read at a glance; prefer unit: cost |
normal_threshold / heavy_threshold / extreme_threshold |
Watt breakpoints for the usage tier. Defaults 200 / 1000 / 3000 |
high_threshold |
Watts at which the Energy card promotes itself to its active state. Default 500 |
release_threshold |
(optional) Watts at which it drops back. Defaults to 80% of high_threshold |
Cost over kWh. A kWh figure is hard to judge at a glance, so the badges read better pointed at a cost
sensor with energy_unit_N: cost. The gauge ring keeps coloring itself from the power sensor, so the icon
still tracks live draw while the number shows the period. Currency follows your Home Assistant setting, in
both the ring glyph and the text. kWh values round to a whole number at 10 and above.
Usage tiers. The group badge, each sub-badge, the Energy card and the energy popup all read the same
breakpoints, so their colors always agree: green when idle, yellow at Normal, orange at Heavy, red at
Extreme. The Energy card uses a separate, higher high_threshold to decide whether it is prominent enough
to sort to the front of a smart row, with hysteresis so a sensor hovering at the line does not reshuffle
the row on every crossing.
By default a sub-badge opens this view's own energy popup. To point a badge at a different room's popup β as the Home view does for its per-room badges β set the matching energy_popup_*_N keys:
energy_entity_1: sensor.bedroom_monthly_consumption_cost
energy_label_1: Bedroom
energy_unit_1: cost
energy_popup_name_1: Bedroom
energy_popup_power_1: sensor.bedroom_current_consumption
energy_popup_today_1: sensor.bedroom_daily_consumption
energy_popup_month_1: sensor.bedroom_monthly_consumption
energy_popup_cost_today_1: sensor.bedroom_daily_consumption_cost
energy_popup_cost_month_1: sensor.bedroom_monthly_consumption_costThe security group badge expands into one badge per security entity. A single template handles every type, picking its icon and wording from the entity's domain:
| Domain | States shown |
|---|---|
lock.* |
Locked / Unlocked |
alarm_control_panel.* |
Armed Home / Armed Away / Disarmed / Triggered |
binary_sensor.* (door, window, garage, opening) |
Open / Closed |
camera.* |
Live / Idle |
cover.* (garage) |
Open / Closed |
| Variable | Description |
|---|---|
security_entity_1 β security_entity_8 |
Any mix of the domains above |
security_label_N |
Badge title β falls back to the entity's friendly name |
Aggregated Locks badge (Home view). Rather than one badge per lock, security_locks collapses them all into a single "Locks" badge that opens the shared lock group popup β the way the Lights badge aggregates lights. Rooms below keep using individual security_entity_N badges.
security_lock_entity: lock.front_door
security_locks:
- lock.front_door
- lock.back_door
security_lock_batteries:
lock.front_door: sensor.front_door_lock_battery # optional
security_door_sensors:
lock.front_door: binary_sensor.front_door # optionalCameras badge. security_cameras collapses every camera into a single badge that opens a shared
camera popup. The sub-line reads "No Alerts" at rest, a count when a camera goes offline,
and the most recent motion or doorbell event when there is one. The badge only appears when the room
already has a lock or a security_entity_N set.
security_cameras:
- camera.front_door
- camera.backyard
security_cameras_label: Cameras # optional, defaults to "Cameras"The popup opens on a grid of tiles: a still snapshot per camera with its name and a relative age stamp ("11s", "2m", "3h"). A small accent dot marks a camera with activity in the last few minutes. Tapping a tile zooms it into a single-camera view and starts the live stream; the chevron in the corner goes back.
Opened with only one camera there is nothing to choose between, so the grid is skipped entirely and the popup lands directly on the live view, with no chevron.
| Gesture | Result |
|---|---|
| Tap a tile | Zooms into that camera and starts the live stream |
| Hold a tile | Opens Home Assistant's own more-info dialog for it |
| Tap the title in the detail view | Opens more-info |
| Tap the full screen button | Full screen, and again to leave it |
The feed itself is deliberately inert. Full screen is the button's job alone, so you can point at the picture without triggering anything.
The detail view keeps the controls under the feed. Each has a label on hover, and the labels say what the next tap will do rather than what the state is, so the mute button reads "Unmute" while muted:
| Control | Behavior |
|---|---|
| Mute | Starts muted. The stream is mounted unmuted so audio is negotiated, then held silent until you ask for it. If the camera really has no audio track the header says so rather than leaving a dead button |
| Last recording | Lights up while the clip plays and drops back to live on a second tap, when the clip ends, or if there is no recording to fetch. The clip loads behind the live stream, so a missing recording never blanks the frame |
| Zoom | Toggles between filling the frame and fitting the whole sensor. Starts filled every time the popup opens |
| Siren | Only for cameras with an onboard siren. A bare glyph until tapped, then it expands to "Sound siren?" and needs a second tap within five seconds |
Full screen. A small button fades in over the top-left of the feed on hover, matching where Home Assistant puts its own, and stays permanently visible on touch where there is no hover to reveal it. Its glyph flips between the outward and inward arrows to match the current state, and it follows the browser rather than its own clicks, so leaving full screen with Escape or a system gesture still flips it back.
On Android it also requests landscape. iOS has no orientation API, so there the video's own native player takes over instead, which fills the screen and follows the device as you turn it.
Sizing. The popup is 1040 px wide on desktop, clamped to 92vw so it never overflows a narrow window, and the feed is capped at 52vh so the whole detail view stays on screen on a shorter laptop.
Cameras are read from the registry when cameras is empty, so most setups need nothing beyond the list
above. Using hemma_popup_camera directly gives you the rest:
| Variable | Description |
|---|---|
cameras |
List of camera entity_ids. Empty auto-discovers every camera in the registry |
camera_names |
entity_id: name overrides. Ring's trailing "Live view" is stripped automatically |
activity_entities |
entity_id: sensor overrides for the age stamp, if the device's own last-activity sensor is not found |
exclude |
Entity_ids to leave out of auto-discovery |
columns |
Tile columns. Defaults to 2 on desktop, 1 on mobile |
room_name |
Heading above the grid |
accessory_entities |
entity_id: [entity_ids] to place beside a camera's feed. Defaults to the camera's own siren |
alert_window_minutes |
How recent an event has to be to count as an alert. Default 5 |
Camera tiles. Two card templates front the same popup:
| Template | Use |
|---|---|
hemma_camera |
One camera as an entity tile. Opens straight onto its live view, since there is no grid to pick from. Hold for more-info |
hemma_cameras |
A list of cameras as one tile. Opens the grid. This is what mobile uses, having no security sub-row |
- type: custom:button-card
template: hemma_camera
entity: camera.front_door
name: Front Doorhemma_camera was previously called hemma_doorbell. That name still works as an alias, so existing
dashboards need no change, but it will be removed in a future major version. The tile was never
doorbell-specific, and it now opens the camera popup rather than a bare more-info dialog.
hemma-smart-row is a custom Lovelace card that replaces a static list of entity cards with a self-sorting row. On desktop, any card that becomes active automatically slides to the front of the row using a FLIP animation. On mobile portrait and landscape the cards render in a fixed grid β no reordering.
Requires: smart-row.js registered as a Lovelace resource (included in this repo).
Replace a plain list of button-card entries with a single hemma-smart-row card and nest your cards inside:
- type: custom:hemma-smart-row
cards:
- type: custom:button-card
template: hemma_light
entity: light.living_room
name: Living Room
- type: custom:button-card
template: hemma_thermostat
entity: climate.living_room
name: Thermostat
- type: custom:button-card
template: hemma_media
entity: media_player.apple_tv
name: Apple TV| Variable | Default | Description |
|---|---|---|
cards |
required | Array of card configs (same format as any Lovelace card list) |
sort |
true |
Set to false to disable active-card sorting and render in config order |
- Active state is detected via
--hemma-active-overlay-opacity: 1on each card's shadow DOM (works with all Hemma templates including plant thresholds and numeric conditions). - When a card becomes active it moves to the front of the row after a short 2.5 s delay β long enough to avoid flickering on transient states.
- On page load, active cards are pre-sorted before the entry animation plays so the sweep order always matches the sorted order.
- Respects
prefers-reduced-motionβ reorders instantly without animation when enabled.
hemma_entity_actions extends hemma_entity with up to two action buttons in a rail down the right side of the card. Each button is a flat capsule that fills with its domain's accent color when its entity is on, dims when the entity is unavailable, and disappears entirely when disabled or left without an entity. Turn both off and the rail collapses so the card reflows to normal padding.
Originally contributed by @hostand.
- type: custom:button-card
template: hemma_entity_actions
entity: sensor.fridge_status
name: Fridge
variables:
icon: fridge
action_1_entity: switch.fridge_mode
action_1_icon: mdi:fridge-outline
action_1_action: toggle
action_2_entity: switch.fridge_super_cool
action_2_icon: mdi:snowflake
action_2_action: toggleReplace N with 1 or 2.
| Variable | Default | Description |
|---|---|---|
action_N_entity |
β | Entity the button acts on and reads state from. Required β no entity, no button |
action_N_enabled |
true |
Set to false to hide this button |
action_N_icon |
entity's own icon, then mdi:help-circle |
mdi:*, a bare Hemma SVG name, or a full /local/β¦, http(s)://β¦, or .svg/.png/.webp path |
action_N_active_color |
domain accent | CSS color for the active fill, overriding the domain default |
action_N_action |
more-info |
more-info Β· toggle Β· navigate Β· call-service |
action_N_navigation_path |
β | Path for the navigate action |
action_N_service |
β | domain.service for the call-service action |
action_N_service_data |
{} |
Service data map. entity_id defaults to action_N_entity |
svg_path |
/local/hemma/icons |
Base path used to resolve bare SVG icon names |
The tile's own active state follows its entity: as usual, and the buttons light up independently. If the tile points at a passive sensor that never reads as active, hand the job to the action entities instead:
variables:
active_entities:
- switch.fridge_mode
- switch.fridge_super_cool
active_entities_mode: all # all = every entity on; any (default) = at least oneThese are listed explicitly rather than inferred from action_N_entity, so a card can key off entities that aren't buttons β and a tile with a meaningful status sensor can keep using it.
hemma_plex_recently_added is a standard entity card that shows how many items Plex added in the last 7 days. It goes active (gold icon) when the count is above zero. Tapping opens the hemma_popup_recently_added swipe-card carousel with poster art, title, year, and release date for each recently added movie or episode.
Requires:
plex_recently_addedHACS integration β providessensor.recently_added_moviesandsensor.recently_added_tvlovelace-swipe-cardHACS card β powers the popup carouselswipe-card-patch.jsregistered as a resource (included in this repo) β syncs pagination bullet color to content type
The sensor.plex_recently_added_count template sensor is defined in packages/hemma_helpers.yaml.
Everything is configured in one file: /config/dashboards/hemma/hemma_mobile.yaml (created from hemma_mobile.yaml.example, which documents every block inline). The file is entities-only β filters, popups, the collapsing header, and room chips are all driven by the shared templates.
Top-to-bottom structure:
| Block | What you edit |
|---|---|
BACKGROUND |
Nothing β the time-of-day wallpaper is automatic |
HEADER |
Weather entity + outdoor temp sensor |
BADGE ROW |
The entities behind each filter pill β pills with no entities hide β template hemma_mobile_filter_badges |
FILTERS |
Nothing β category popups auto-collect matching cards from your rooms |
ROOM POPUPS |
One entry per room; room: must match the section header name |
SUB BADGE ROW |
Home climate chips + per-room chips (room_chips:) β template hemma_mobile_sensor_chips |
NOW PLAYING |
Media players, Plex streams, and activity sensors for the media tile row β template hemma_mobile_now_playing |
FAVORITES / rooms |
Your cards β same button-card templates as the desktop dashboard |
Section headers use the hemma_mobile_header template, and the large dashboard title + weather widget at the top uses hemma_mobile_weather.
Adding a room β everything keys off the section header's name:, so there's only one identifier to get right:
-
Copy a section header + smart-row pair and give the header a unique
name:(e.g.Guest Room). -
Add a matching
hemma-filter-overlaywithroom:set to that exact name β nothing else:- type: custom:hemma-filter-overlay room: Guest Room
-
Make sure the room's slug is an option on
input_select.hemma_mobile_filterinpackages/hemma_helpers.yaml. The slug is the name lowercased with all non-alphanumerics stripped,room_prefixed βGuest Roomβroom_guestroom,Kid's Roomβroom_kidsroom.room_livingroom,room_kitchen,room_bedroom, androom_officeship pre-seeded, so those four need no edit at all. Any other room name does β without its slug in the list the section header still renders, but tapping it won't open anything. Unused pre-seeded options are harmless; leave them in place.
Optionally add a room_chips: entry for its sensor chips, and set mobile_filter_categories: on the header to control which filter pills the room's cards appear under.
Step 3 is the only place you type the slug, and the only step that can't be automated: Home Assistant helpers can't be created from a dashboard file, and the filter needs a real input_select state to hold the active room. The section header and the overlay both derive the key from the room's name themselves.
room_key: on the header remains available as an override for the rare case where a display name shouldn't drive the key β two rooms whose names slug identically, or a name containing an emoji. Setting it also overrides the overlay if you pass filter_category: explicitly there.
Wallpaper: nothing to configure here. The mobile background reuses the same room photo the desktop dashboard loads from www/hemma/rooms/, with the gradient beneath it colored by sampling that photo β there is no separate set of mobile wallpapers. To point it at your own pair of images, see Your own wallpaper above.
This repo is intended as a starting point:
- Swap out room/background images in
www/hemma/rooms/. - Tweak theme colors, shadows, and typography in
themes/hemma/hemma.yaml. - Adjust layouts (
hemma_screen_layout.yaml, etc.) to match your devices and preferences.
Hemma is designed for edge-to-edge screens. If you are using the HA iOS Companion app, please ensure to enable Edge to edge display found in Settings β Companion app β General β Edge to edge display
To add additional button card icons, you can download them from the links below and place the icons in the www/hemma/icons/ folder:
Apple Icons - Set Background to Dark and Color to Primary
Google Material Icons - Weight 300 is recommended, file type: svg
Hemma also keeps an inline copy of every icon inside hemma-icons.js (window.HEMMA_ICONS) so icons paint in the same frame as the card rather than arriving over the network a beat later. A new SVG dropped into www/hemma/icons/ still works without any further steps β it just falls back to loading from that path. To give it the same instant paint as the built-in icons, regenerate the map with the snippet in the comment above window.HEMMA_ICONS and paste the result back in.
You can switch from 12hr to 24hr time by switching the variables in hemma_time.yaml, example below:
hemma_time:
template:
- hemma_default
variables:
time_entity: sensor.time
# Whether to convert to 12h with AM/PM
use_12h: false
# Optional label after the time, e.g. "UHR", "HRS"
time_suffix: "UHR"- Original Homio concept and base implementation: iamtherufus/Homio
- Original climate/air quality card design: jerahmeel-sudo
- Big thanks to SH1FT-W for helping build out the custom pop up cards
- Hemma customization and ongoing tweaks: @willsanderson