Luxus Home Assistant Dashboard wie auf dem Bild – umsetzbar?

Hallo zusammen,

ich möchte mir ein Home-Assistant-Dashboard im Stil des angehängten Bildes bauen. Es soll auf einem Wand-Tablet laufen und optisch sehr hochwertig und minimalistisch aussehen.

Die Hauptseite soll nur die wichtigsten Informationen anzeigen. Beim Antippen einer Kachel sollen sich weitere Steuerungsmöglichkeiten öffnen.

Beispiele:

  • Beleuchtung → Räume und einzelne Lampen steuern.

  • Rolos → Alle Rolos anzeigen und steuern.

  • Müllabholung → Alle kommenden Mülltermine anzeigen.

  • Kameras → Live-Bild in größerer Ansicht öffnen.

  • Haustür/Klingel → Live-Bild, Gegensprechfunktion und Türöffner.

  • Energie/PV → Verbrauchs- und Erzeugungsdaten im Detail anzeigen.

  • Kalender → Termine und Geburtstage anzeigen.

Ziel ist ein elegantes Dashboard mit Pop-ups oder Unterseiten, damit die Hauptansicht übersichtlich bleibt.

Ist so etwas in Home Assistant umsetzbar? Welche Custom Cards oder Themes würdet ihr dafür empfehlen?

2 „Gefällt mir“

Design ist ja immer so ne Sache…

7 „Gefällt mir“

Das sieht wirklich super aus! Hast du das mit Home Assistant gemacht? Könntest du mir verraten, wie du dein Dashboard aufgebaut hast?

Ja, ist mit HA erstellt.
Allerdings habe ich einige Zusätze aus dem HACS installiert.
Zufrieden bin ich nicht, aber momentan bastel ich lieber an Funktionen und Automationen, als am Design…

01 Dashboard-Typ: Sections-View

Die Seite nutzt den modernen Sections-View (type: sections, max_columns: 2), der seit HA 2024.x verfügbar ist. Er erlaubt ein flexibles Grid aus mehreren Abschnitten, die sich auf Mobilgeräten automatisch stapeln.

Meine Hauptseite hat drei Sections:

  • Links: Uhr, Wetter, Status-Buttons
  • Rechts: Raum-Karten (je ein Bereich)
  • Unten (volle Breite, column_span: 2): Meldungen & Aktionen

02 Hintergrund & Glassmorphism-Effekt

Das ist das visuelle Herzstück: Ein Texturfoto (ich habe ein kostenloses Pixabay-Bild verwendet) wird in Einstellungen → Medien → Bilder hochgeladen und als View-Hintergrund gesetzt:

`background:
  image: media-source://image_upload/...
  opacity: 33
  size: cover
  attachment: fixed   # wichtig: Parallax-Effekt`

Jede einzelne Karte bekommt dann dasselbe Foto als background-image, kombiniert mit einer halbtransparenten dunklen Farbe und dem entscheidenden Trick:

`ha-card {
  background-image: url('/api/image/serve/<ID>/512x512');
  background-size: cover;
  background-color: rgba(60, 60, 60, 0.45);
  background-blend-mode: multiply;  # Bild + Farbe verschmelzen
  box-shadow: 0 8px 32px rgba(0,0,0,0.75),
              inset 0 1px 0 rgba(255,255,255,0.18);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 16px;
}`

Warum dasselbe Bild auf jeder Karte? Weil background-attachment: fixed am View nicht auf einzelne Karten vererbt wird. Man täuscht den Effekt nach: Karte und Hintergrund zeigen dasselbe Bild, der Browser rendert es nahezu identisch – der “Glasscheibe vor der Wand”-Eindruck entsteht.

03 Verwendete HACS-Erweiterungen

Alle vier Erweiterungen sind Frontend-only (keine Backend-Integrationen) und über HACS installierbar.

Erweiterung Wofür
card_mod CSS-Anpassungen auf jeder beliebigen Karte – das Glassmorphism-Styling oben läuft komplett darüber
button-card Hausstatus-Karte mit dynamischer Hintergrundfarbe per JavaScript, Gäste-Toggle, Abfahrten-Button
mushroom-cards Meldungs-Karte mit dynamischem Icon und Farbe per Jinja2-Template
browser_mod Popup für den Abfahrtsmonitor – öffnet eine Overlay-Karte ohne Seitenwechsel

04 Die einzelnen Karten erklärt

Uhr & Wetter

Beides sind Standard-HA-Karten (type: clock und type: weather-forecast), die nur durch card_mod das Glassmorphism-Styling bekommen. Kein HACS nötig.

Hausstatus / Gäste / Abfahrten

Ein horizontal-stack mit drei button-cards. Der interessante Teil ist die Hausstatus-Karte: Sie liest einen Template-Sensor und färbt sich dynamisch via JavaScript im styles:-Block:

`styles:
  card:
    - background-color: >
        [[[
          const s = states['sensor.house_status_label'].state;
          if (s === 'Zuhause')  return 'rgba(76,175,80,0.2)';
          if (s === 'Gäste')    return 'rgba(33,150,243,0.2)';
          if (s === 'Abwesend') return 'rgba(255,152,0,0.2)';
          if (s === 'Urlaub')   return 'rgba(156,39,176,0.2)';
        ]]]`

Der Abfahrten-Button öffnet per browser_mod.popup ein Overlay mit Echtzeit-Abfahrtszeiten für Bus und Bahn, befüllt aus einer Custom Integration die eine ÖPNV-API abfragt. Die Tabellen sind einfache Markdown-Karten mit Jinja2-Template.

Raum-Karten

Vier native Area-Karten (type: area, display_type: picture) für die einzelnen Räume. HA zieht sich automatisch Temperatur, Feuchte, Bewegungsmelder und Fensterkontakte aus dem jeweiligen Bereich. Tippen navigiert zum Raum-spezifischen Dashboard.

`type: area
area: wohnzimmer
display_type: picture
alert_classes: [motion, moisture, opening]
sensor_classes: [temperature, humidity]
tap_action:
  action: navigate
  navigation_path: /dashboard-wohnen`

Meldungs-Karte

Eine mushroom-template-card, die zwischen zwei Zuständen wechselt: Ist sensor.warning_level > 0, zeigt sie eine Warnung (z.B. von CO-Melder oder Feuchtigkeitssensor) in Rot/Orange und verlinkt zur Sicherheitsseite. Sonst zeigt sie unauffällig die nächste Müllabfuhr-Leerung. Icon, Farbe und Badge-Farbe werden alle per Jinja2-Template gesetzt.

05 Template-Sensor: Hausstatus

Die Karte liest keinen Input-Select direkt, sondern einen Template-Sensor (sensor.house_status_label), der den internen englischen Wert (home, away…) ins Deutsche übersetzt. Das hält die Automatisierungslogik sauber englisch, während im Dashboard Deutsch angezeigt wird.


Wenn Fragen zu den einzelnen YAML-Blöcken sind, einfach fragen – ich kann Details gerne rausrücken.HA 2026.7.1 · card_mod · button-card · mushroom · browser_mod

5 „Gefällt mir“

Hey, vielen lieben Dank, dass du mir so schnell geholfen hast und dir die Mühe gemacht hast, alles zusammenzustellen. Ich werde mich spätestens morgen daran machen und versuchen, es so hinzubekommen. Tausend Dank – das weiß ich wirklich zu schätzen!

Ich hab bei mir auch ne Weile rumgeschraubt, da ich die platzverschwenderischen Sections zum Würgen finde, bin ich bei der alten Ansicht geblieben, nutze aus dem HACS die Layout-Grid Card,damit kann man die Dashboard-Views komplett neu gestalten.


Die provisorische Halterung ist der Sanierung geschuldet :wink:

Da grad die Wetter-Api kein Bock hat, steht da grad „unbekannt“ statt „Leichte Regenschauer“

Hinter allen Karten verstecken sich Aktionen, so das man beim Tap auf die Wetterkarte dann mehr Wetter bekommt, beim Sonnenspeicher alles zum BKW und so weiter. Auf Pop-Ups etc hab ich bewusst verzichtet, die fressen Ressourcen und sind selten von Stabilität geprägt. Dashboards kann man gut navigieren, und so manche Info und Alarme haben auch ihre View.

Moin, hab mal Farben etwas abgeändert. Kupferpott ausgepackt. Sicher nicht so schick wie dein Bild und Icons nicht bearbeitet, aber immerhin… :joy:

Das Metall-Feeling entsteht durch drei CSS-Schichten: einen warmen Dunkelgradienten als Basis, feine horizontale Pinselstriche als repeating-linear-gradient , und einen mehrstufigen box-shadow der den Bevel-Effekt erzeugt — helle Goldlinie oben, dunkle Schattenlinie unten.

Schritt 1 · Theme-Datei

Datei anlegen: config/themes/industrial_copper.yaml. In configuration.yaml muss stehen: frontend: themes: !include_dir_merge_named themes

themes/industrial_copper.yaml

industrial_copper:
  modes:
    dark:
      primary-color: "#D4924A"
      accent-color: "#E8B86A"
      primary-text-color: "#EDD8A8"
      secondary-text-color: "#C09868"
      state-active-color: "#E8B86A"
      ha-card-background: "rgba(38, 32, 24, 0.97)"
      card-background-color: "rgba(38, 32, 24, 0.97)"
      ha-card-border-color: "rgba(210, 155, 65, 0.65)"
    light:
      primary-color: "#8B5A2B"
      accent-color: "#B87333"
      primary-text-color: "#2D1F0E"
      secondary-text-color: "#6B4A2A"
      state-active-color: "#B87333"

Schritt 2 · Karten stylen

card_mod · Basis-Karte (clock, weather, mushroom …)

Das Metall-Feeling kommt aus dem card_mod-Style. Dieser wird entweder per card_mod global in der Dashboard-Konfiguration oder direkt auf jeder Karte gesetzt.

ha-card:
  background: >
    repeating-linear-gradient(
      180deg,
      transparent 0px,
      rgba(255,190,80,0.020) 0.5px,
      transparent 1px,
      transparent 3px
    ),
    linear-gradient(
      158deg,
      rgba(65,58,48,0.96) 0%,
      rgba(28,21,13,0.99) 38%,
      rgba(22,17,10,0.99) 55%,
      rgba(48,43,36,0.96) 100%
    ) !important
  box-shadow: >
    0 8px 32px rgba(0,0,0,0.85),
    0 2px 8px rgba(0,0,0,0.60),
    inset 0 1px 0 rgba(240,195,110,0.82),
    inset 0 -1px 0 rgba(30,15,5,0.75),
    0 0 28px rgba(190,130,45,0.20)
  border: 1px solid rgba(210,155,65,0.65)
  border-radius: 16px

card_mod · Area-Karten (Raumübersicht mit Chips)

":host":
  --primary-color: "rgba(232,184,106,0.95)"
  --state-active-color: "rgba(240,195,110,1.0)"
  --icon-primary-color: "rgba(232,184,106,0.95)"
  --ha-chip-icon-color: "rgba(232,184,106,0.95)"
  --ha-chip-background-color: "rgba(110,82,40,0.45)"
  color: "rgba(237,216,168,0.95)"

Schritt 3 · Theme anwenden

Das Theme wird nur auf einem einzelnen Dashboard-View aktiviert — alle anderen Dashboards bleiben komplett unverändert.

  • 1 Dashboard öffnen → Bleistift-Icon → View bearbeiten
  • 2 UnterTheme:industrial_copperauswählen
  • 3 Speichern + Browser hard-reload (Strg+Shift+R)

Zurückwechseln: Theme im selben Dialog auf Standard stellen — kein Neustart nötig.

6 „Gefällt mir“

Ich habe etwas mit Claude Code herumexperimentiert indem ich mein Homeassistant mit GitHub verbunden habe und Claude Code wiederum mit GitHub.

So kann man eigentlich quasi alles bauen. Ich bin mir ziemlich sicher dass Claude sehr nah an dein Bild ran kommen wird.

Entweder mit passenden Erweiterungen oder direkt selber gecoded was auch möglich ist.

Dazu gibt es einen Befehl im debug Modus der alle entity’s ausgibt damit Claude alle nötigen Infos hat.

Im Anhang ein Beispiel für ein abgespecktes custom Dashboard für meine Frau im Apple Glass Stil.

1 „Gefällt mir“

Mein tablet Dashboard sieht im Moment so aus.

2 „Gefällt mir“

Anstelles eines nomalen Tablets haben wir eine Wandtablett auf Aliexpress bestellt.

Das Gerät hat keinen Akku, dafür einen Netzwer port. Darüber geht auch poe, um das Gerät zu versorgen.

Das Tablet verfügt zudem über 2 Led Streiffen ( ist als Raum reservations Display gedacht). Mit ein bischen chatgpt lassen sich diese auch via ha steuern (ha sendet artnet, auf dem tablet läuft node red um artnet auf seriel zu konvertieren.

Welches Display nutzt du?

Schaut cool aus. Darf ich fragen woher du die Warnungen hast die rechts eingeblendet sind ? Vorallem geil weil alles auf Schweizerdeutsch ist.

Würde mich auch interessieren.

Lg

Also Designs haue ich ja nur noch in Claude Code rein.

Der zaubert da schon sehr gute Inhalte. Einfach n Export der Entitäten etc oder man gibt im Zugriff auf die Umgebung.

Seit KI ist so was in 5 Minuten erstellt.

Selbstgebastelt, ich hab die AlertSwiss App von Android mir mal „genau angeschaut“ :wink:
Die Json werte ich über einen kleinen Powershell-Docker auf, das ist mit den RestFul Sensoren von HA ein Albtraum, das aufgehübschte JSON kommt dann als Restful-Sensor, die Card ist eine Markdown mit card-mod. Trifft auch auf die Wetter-Card zu. Ist eine Mischung aus „Swiss-Meteo“-App und meiner Wetterstation auch als Markdown mit card-Mod, die Tarifkachel drunter kommt von der EKZ-API

mit der selben Methode geht auch sowas

oder das

Das Schwiizerdütsch ist für den Nachwuchs, hat Textshuttle gemacht :wink:
Supertext – KI und Profis für Übersetzungen, die ankommen

Wetter-Alarm in Powershell

Function Get-SwissMeteoAlerts {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [string]$PLZ,
        [Parameter(Mandatory=$true)]
        [String]$PLZZusatz
        # PLZ und Zusatz -> https://www.geoportal.ch/ch/map/1503
    )

    $JSONBase = [ordered]@{}

    $WeatherAlertTypeList = @{
        "0"  = "Wind"
        "1"  = "Gewitter"
        "2"  = "Regen"
        "3"  = "Schnee"
        "4"  = "Glätte"
        "5"  = "Frost"
        "6"  = "unbekannt"
        "7"  = "Hitze"
        "8"  = "Lawinen"
        "9"  = "Erdbeben"
        "10" = "Waldbrand"
        "11" = "Hochwasser"
        "12" = "Trockenheit"
    }

    $WeatherAlertLevelList = @{
        "1" = "keine oder geringe Gefahr"
        "2" = "mässige Gefahr"
        "3" = "erhebliche Gefahr"
        "4" = "grosse Gefahr"
        "5" = "sehr grosse Gefahr"
    }

    function Convert-UnixTime($unix) {
        if (-not $unix) { return "NA" }
        return (Get-Date 01.01.1970).AddSeconds([double]($unix.ToString().Substring(0, 10))).ToLocalTime().ToString("dd.MM.yy HH:mm")
    }

    $WebClient = New-Object System.Net.WebClient
    $WebClient.Encoding = [System.Text.Encoding]::UTF8
    $WebClient.Headers.Add("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3")
    $WeatherForecast = ($WebClient.DownloadString("https://app-prod-ws.meteoswiss-app.ch/v3/plzDetail?plz=$($PLZ)$($PLZZusatz)") | ConvertFrom-Json)

    $JSONForecast = @()

    if ($WeatherForecast.warnings.Count -gt 0) {
        foreach ($Alert in $WeatherForecast.warnings | Sort-Object validFrom -Descending | Select-Object -First 3) {
            $JSONForecast += [ordered]@{
                warnType        = $Alert.warnType
                warnTypeString  = $WeatherAlertTypeList["$($Alert.warnType)"]
                warnLevel       = $Alert.warnLevel
                warnLevelString = $WeatherAlertLevelList["$($Alert.warnLevel)"]
                validFrom       = Convert-UnixTime $Alert.validFrom
                validTo         = if ($Alert.validTo) { Convert-UnixTime $Alert.validTo } else { "auf Weiteres" }
                htmltext        = $Alert.htmlText
            }
        }
    } else {
        $JSONForecast += [ordered]@{
            warnType        = 999
            warnTypeString  = "NA"
            warnLevel       = 1
            warnLevelString = "keine oder geringe Gefahr"
            validFrom       = "NA"
            validTo         = "NA"
            htmltext        = "keine Warnung ... keine Info"
        }
    }

    $JSONBase["SwissMeteoAlerts"] = $JSONForecast
    return $JSONBase | ConvertTo-Json -Depth 10
}

Alert-Swiss Meldungen

Function Get-AlertSwissData()
{
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)]
        [String]$AlertCanton,
        [Parameter(Mandatory=$true)]
        [String]$AlertLanguage
    )
    
    $JSONBase = [ordered]@{}
    $JSONAlertRaw = New-Object System.Collections.ArrayList
    $JSONAlert = New-Object System.Collections.ArrayList

    $WebClient = New-Object System.Net.WebClient
    $WebClient.Encoding = [System.Text.Encoding]::UTF8
    $WebClient.Headers.Add("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3")

    $AllAlerts = ($WebClient.DownloadString("https://www.alert.swiss/content/alertswiss-internet/de/home/_jcr_content/polyalert.alertswiss_alerts.actual.json") | ConvertFrom-Json)

    foreach ($Alert in ($AllAlerts.alerts | Where-Object { $_.identifier -like "POA-*" }))
    {
        if ($AlertCanton -in $Alert.areas.regions.region)
        {
            $ID = $Alert.identifier
            $HeaderTable = @{ "Accept-Language" = "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"; "Accept-Encoding" = "gzip" }

            try
            {
                $wcXML = New-Object System.Net.WebClient
                $wcXML.Headers.Add("Accept-Language", $HeaderTable["Accept-Language"])
                $wcXML.Headers.Add("Accept-Encoding", $HeaderTable["Accept-Encoding"])

                [byte[]]$data = $wcXML.DownloadData("https://app-prod-static.alertswiss-app.ch/v1/$ID.xml")

                $ms = New-Object System.IO.MemoryStream(,$data)
                $gzipStream = New-Object System.IO.Compression.GzipStream($ms, [IO.Compression.CompressionMode]::Decompress)
                $reader = New-Object System.IO.StreamReader($gzipStream, [Text.Encoding]::UTF8)
                $xmlContent = $reader.ReadToEnd()

                $reader.Close()
                $gzipStream.Close()
                $ms.Close()

                [xml]$XMLSwissAlert = $xmlContent

                $AlertInSpecifiedLang = $XMLSwissAlert.alert.info | Where-Object { $_.language -eq $AlertLanguage }

                $JSONAlertRaw.Add(@{
                    "identifier"   = $ID
                    "category"     = $AlertInSpecifiedLang.category
                    "event"        = $AlertInSpecifiedLang.event
                    "urgency"      = $AlertInSpecifiedLang.urgency
                    "severity"     = $AlertInSpecifiedLang.severity
                    "onset"        = $AlertInSpecifiedLang.onset
                    "headline"     = $AlertInSpecifiedLang.headline
                    "description"  = $AlertInSpecifiedLang.description
                    "instruction"  = $AlertInSpecifiedLang.instruction
                    "eventicon"    = ($AlertInSpecifiedLang.parameter | Where-Object { $_.valueName -eq "EventPictogram" }).Value
                    "areaDesc"     = $AlertInSpecifiedLang.area.areaDesc
                    "polygon"      = $AlertInSpecifiedLang.area.polygon
                }) | Out-Null
            }
            catch
            {
                Write-Warning "Fehler beim Laden oder Parsen des Alerts $($ID): $_"
            }
        }
    }

    if ($JSONAlertRaw.Count -gt 0)
    {
        foreach ($SwissAlert in ($JSONAlertRaw | Sort-Object identifier -Descending | Select-Object -First 1))
        {
            $JSONAlert.Add($SwissAlert) | Out-Null
        }
    }
    else
    {
        $JSONAlert.Add(@{
            "identifier"  = "Nichts"
            "category"    = "Other"
            "event"       = "Anderes Ereignis"
            "urgency"     = "Unknown"
            "severity"    = "Minor"
            "onset"       = $(Get-Date -Format "yyyy-MM-ddTHH:mm:ss+00:00")
            "headline"    = "Keine Alarme im Kanton $($AlertCanton.ToUpper())"
            "description" = ""
            "instruction" = ""
            "eventicon"   = 7300
            "areaDesc"    = ""
            "polygon"     = ""
        }) | Out-Null
    }

    $JSONBase.Add("ActiveAlerts", $JSONAlert)
    return $JSONBase | ConvertTo-Json -Depth 10
}
1 „Gefällt mir“

Ich finde die genial und hat nicht jeder ….

Interessantes Layout, allerdings finde ich leidet die Lesbarkeit ein wenig,
hier mal meine Variante: (hatte vorher ein LCARS gebaut, allerdings war das immer sehr laggy).
Theme: nordic
Recht schlicht so das man es im vorbeigehen noch gut erkennt.

kiosk addon aus dem HACS damit die ganzen leisten weg sind.

kiosk_mode:
  hide_header: true
  hide_sidebar: true

Ansonsten:
weather-forecast-card
calendar-card-pro
mushroom-entity-card
meteoalarm-card → die öffnet einen neuen Reiter und zeigt die Nina Karte
Geräte → öffnet auch einen neuen Reiter mit zwei 3D Drucker Maps und dem Katzen Futterautomaten

1 „Gefällt mir“

Ich zeig auch mal mein dashboard auf dem Tablet in der Küche.

Die letzten Dashboards sehen ganz eindrucksvoll aus, allerdings nicht unbedingt schlicht und edel.

Sitze immernoch am “Metalleffekt”, komme da nicht wirklich weiter. Sieht immer irgendwie flach/matt aus.

Poste mal bitte deine yaml .da lässt sich bestimmt was machen.Ich bin eh gerade dabei den Generator zu testen dann kann ich das auch mit sinnvollen sachen machen.

Mein aktueller stand.