A different take on designing a Lovelace UI

Yes, I have this file and the line in my configuration.yaml.

I reuploaded your file, and try it again, but it doesnt work.

Thanks a million for the help, exactly what I needed

err

Is this yours? Are you sure you’ve copied all the templates correctly? diff compare

No, this is my error:

ButtonCardJSTemplateError: TypeError: Cannot read properties of undefined (reading 'state') in 'if (entity) {
      let links = new RegExp('<a href="([^"]+)"', "g"),
          installed = entity...'

So not the same error :stuck_out_tongue:

Cannot read properties of undefined (reading 'state') either means that you don’t have all the sensors needed or you’ve made a typo in the sensor name.

Replace updates_hass with this, open popup and look in your browser console

# button_card_templates/updates.yaml

updates_hass:
  template:
    - updates
    - settings
  state_display: |
    [[[
      function Log(entity_id, state) {
        this.entity_id = entity_id;
        this.state = state;
      }
      var obj = {};
        obj.entity = new Log(`${entity?.entity_id}`, `${entity?.state}`);
        obj.latest = new Log(`${states[variables?.latest]?.entity_id}`, `${states[variables?.latest]?.state}`);
        obj.latest_beta = new Log(`${states[variables?.latest_beta]?.entity_id}`, `${states[variables?.latest_beta]?.state}`);
        obj.release_notes = new Log(`${states[variables?.release_notes]?.entity_id}`, `${states[variables?.release_notes]?.state} ${states[variables?.release_notes]?.attributes?.body}`);
        obj.release_notes_beta = new Log(`${states[variables?.release_notes_beta]?.entity_id}`, `${states[variables?.release_notes_beta]?.state} ${states[variables?.release_notes_beta]?.attributes?.body}`);
        obj.translate_no_updates = new Log(`(variable)`, `${variables?.translate_no_updates}`);
        obj.translate_available = new Log(`(variable)`, `${variables?.translate_available}`);
      console.table(obj);
    ]]]

Oh, you are right. :smiley: Had an other error at the beginning.

It seems im missing some sensors:

But if I look at the dev tools in HA, there is a state for the hass_release_latest_beta:
image

I compared the version_updates.yaml and the button_card_templates/updates.yaml, and I think I have everything. Nad the Version Integration is also there:
image

but my version-sensors are called: sensor.home_assistant_versions and sensor.homea_assistant_versions_beta.

Could this be a problem?

1 Like

Thanks a lot, that was my missing piece.

Hi all,
any suggestion how I can add an if else function in the button_card_templates.yaml ?
I do want to change the color of the circle for the person card in dependence of the teams presence status and the original state home <-> not home.

So far it’s working pretty well:
(Red Circle for in a call)
2022-08-19 11_02_42-Übersicht – Home Assistant und 23 weitere Seiten - Geschäftlich – Microsoft​ Edg

But when not at home and not in a call the circle is not like in the original design from Matthias:
2022-08-19 11_26_31-Übersicht – Home Assistant und 23 weitere Seiten - Geschäftlich – Microsoft​ Edg

This is obivously because of my moddification in the template file as I don’t know how to implent the if else function:

            stroke = states[variables.teams].state == 'Am Telefon' || states[variables.teams].state == 'In einer Besprechung'  
              ? 'red'
              : '#b2b2b2',

E.g. if stroke = states[variables.teams].state == ‘Work’ then ‘none’

Furthermore I try to let the circle (just the circle) blink when I’m in a call. I don’t get it, how to select just the circle himself? With the following modification, the hole SVG (so circle and text) start to blink. Any suggestion how to achieve that, just the circle blinks?

Animation

        circle:
          - animation: >
              [[[
                if (entity) {
                  return states[variables.teams].state == 'Am Telefon'
                    ? 'blink 2s ease infinite'
                    : 'none';
                }
              ]]]
2 Likes

Yeah, doing it that way styles the whole div. You can add a new custom_field to set the styles with js

person:
  custom_fields:
    blink: >
      [[[
        setTimeout(() => {
          let elt = this.shadowRoot,
            circle_stroke = elt.getElementById('circle_stroke');
          if (
            states[variables.teams]?.state == 'Am Telefon' ||
            states[variables.teams]?.state == 'In einer Besprechung'
          ) {
            circle_stroke.style.animation = 'blink 2s ease infinite';
            circle_stroke.style.stroke = 'red';
          } else {
            circle_stroke.removeAttribute('style');
          }
        }, 0);
      ]]]
1 Like

Hi @Mattias_Persson, apologies if this was asked and answered, i might be late to the party on this.

I am trying to updated form the old command_line for udm_unifios that was stored in the secrets file (see old command below) to the new python3 implementation, but the script is not running, i just get an error in the logs “Command failed (with return code 1):” followed by the script (see full error message below), i think i am missing a step but with the move of the file i cant find the commit where this was added.

oh and in this commit, use update entities · matt8707/hass-config@1408d40 · GitHub you forgot to remove the use of udm_upgradable on line 586 in ui-lovelace.yaml

Error Message

Command failed (with return code 1): python3 << EOF import json, yaml, requests from datetime import datetime from urllib3 import disable_warnings disable_warnings() SECRETS_FILE = "/config/secrets.yaml" def get_secret(secret): try: with open(SECRETS_FILE, "r", encoding="utf8") as file: secrets = yaml.full_load(file) for key, value in secrets.items(): if key == secret: return value except FileNotFoundError: print("secrets.yaml not found") exit() IP = get_secret("unifi_host") PORT = get_secret("unifi_port") USER = get_secret("unifi_username") PASS = get_secret("unifi_password") URL = f"https://{IP}:{PORT}" login = requests.request("POST", f"{URL}/api/auth/login", \ headers={"Content-Type": "application/json"}, \ data=json.dumps({"username": USER, "password": PASS}), verify=False) response = requests.request("GET", f"{URL}/proxy/network/api/s/default/stat/device/", \ cookies=login.cookies, verify=False) data = response.json()["data"][0] print(json.dumps({ "cpu": data["system-stats"]["cpu"], "cpu_temp": round(data["temperatures"][1]["value"], 1), "mem": data["system-stats"]["mem"], "disk": round(data["storage"][1]["used"] / data["storage"][1]["size"] * 100, 1), "internet": data["internet"], "uptime": datetime.fromtimestamp(data["startup_timestamp"]).isoformat(), "version": data["displayable_version"] })) EOF

Note: i did update the keys in the script to match what i have in my secrets
unifi_host is just the IP that i use to connect to my UDM
unifi_port is 433 that was the port used in the old script.

Old Command

platform: command_line
name: udm_unifios
command: !secret udm_unifios
value_template: |-
  {% set json = value_json.data[0] %}
  {{ json["system-stats"].cpu }}|
  {{ json.temperatures[1].value | round(1) }}|
  {{ json["system-stats"].mem }}|
  {{ ((json.storage[1].used / json.storage[1].size) * 100) | round(1) }}|
  {{ json.internet }}|
  {{ json.startup_timestamp | timestamp_local }}|
  {{ json.displayable_version }}|
  {{ json.upgradable }}
scan_interval: 120

Hello,

Thanks for this great dashboard! I’m currently trying to create a template for a climate (radiator) card, code shown below. The base template is referenced from the original.

climate:
  template:
    - base
  double_tap_action:
    action: fire-dom-event
    browser_mod:
      command: popup
      title: >
        [[[
          return !entity || entity.attributes.friendly_name;
        ]]]
      style:
        hui-entities-card:
          $: |
            #states {
              padding-top: 0.8em;
            }
      card:
        type: entities
        entities: >
          [[[
            if (entity) {
                let climate = [],
                    id = Boolean(entity.attributes.entity_id)
                        ? [entity.entity_id].concat(entity.attributes.entity_id)
                        : [entity.entity_id];

                for (let i = 0; i < id.length; i++) {
                    climate.push({
                        "type": "custom:mushroom-climate-card",
                        "entity": id[i],
                        "fill_container": false,
                        "primary_info": "name",
                        "secondary_info": "state",
                        "icon_type": "icon",
                        "show_temperature_control": true,
                        "hvac_modes": ["off","auto","heat"],
                        "collapsible_controls": true
                    });
                }
                return climate;
            }
          ]]]
  variables:
    circle_current_temp_input: >
      [[[ {
            const current_temperature = entity.attributes.current_temperature;
            return current_temperature;
        }
      ]]]
    circle_current_temp_unit: "°"
    circle_set_temp_input: >
      [[[ {
            const set_temperature = entity.attributes.temperature;
            return set_temperature;
        }
      ]]]
    circle_set_temp_unit: "°"
  custom_fields:
    circle_current_temp: >
      [[[
        if (entity) {
            let r = 22.1,
                c = r * 2 * Math.PI,
                tspan = '<tspan dx=".2" dy="-.4">',
                domain = entity.entity_id.split('.')[0],
                state = variables.state,
                input = variables.circle_current_temp_input || ' ',
                unit = variables.circle_current_temp_unit || ' ';

           /* * * * * * * * * * * * * * * * * *
            *                                 *
            *             CIRCLE              *
            *                                 *
            * * * * * * * * * * * * * * * * * */

            let circle = (state, input, unit) => {
                return `
                  <svg viewBox="0 0 50 50">
                    <style>
                      circle {
                        transform: rotate(-90deg);
                        transform-origin: 50% 50%;
                        stroke-dasharray: ${c};
                        stroke-width: var(--c-stroke-width);
                        stroke: ${state ? 'var(--c-stroke-color-on-current)' : 'var(--c-stroke-color-off-current)'};
                        fill: ${state ? 'var(--c-fill-color-off-current)' : 'var(--c-fill-color-on-current)'};
                      }
                      text {
                        font-size: var(--c-font-size);
                        font-weight: var(--c-font-weight);
                        letter-spacing: var(--c-letter-spacing);
                        fill: ${state ? 'var(--c-font-color-off)' : 'var(--c-fill-color-on)'};
                      }
                      tspan {
                        font-size: var(--c-unit-font-size);
                      }
                      #circle_value, tspan {
                        text-anchor: middle;
                        dominant-baseline: central;
                      }
                    </style>
                    <circle id="circle_stroke" cx="25" cy="25" r="${r}"/>
                    <text id="circle_value" x="50%" y="52%">${input}${tspan}${unit}</tspan></text>
                  </svg>
                `;
            }

            if (domain === 'climate') {
                return circle(state, input, unit);
            }
        }
      ]]]
    circle_target_temp: >
      [[[
        if (entity.state === "heat") {
            let r = 22.1,
                c = r * 2 * Math.PI,
                tspan = '<tspan dx=".2" dy="-.4">',
                domain = entity.entity_id.split('.')[0],
                state = variables.state,
                input = variables.circle_set_temp_input || ' ',
                unit = variables.circle_set_temp_unit || ' ',
                valve_pos = variables.valve,
                valve_pos_num = valve_pos.slice(0, -1);


           /* * * * * * * * * * * * * * * * * *
            *                                 *
            *             CIRCLE              *
            *                                 *
            * * * * * * * * * * * * * * * * * */

            let circle = (state, input, unit) => {
                return `
                  <svg viewBox="0 0 50 50">
                    <style>
                      circle {
                        transform: rotate(-90deg);
                        transform-origin: 50% 50%;
                        stroke-dasharray: ${c};
                        stroke-dashoffset: ${c - valve_pos_num / 100 * c};
                        stroke-width: var(--c-stroke-width);
                        stroke: ${state ? 'var(--c-stroke-color-on-target)' : 'var(--c-stroke-color-off-target)'};
                        fill: ${state ? 'var(--c-fill-color-on-target)' : 'var(--c-fill-color-off-target)'};
                      }
                      text {
                        font-size: var(--c-font-size);
                        font-weight: var(--c-font-weight);
                        letter-spacing: var(--c-letter-spacing);
                        fill: var(--c-font-color);
                      }
                      tspan {
                        font-size: var(--c-unit-font-size);
                      }
                      #circle_value, tspan {
                        text-anchor: middle;
                        dominant-baseline: central;
                      }
                    </style>
                    <circle id="circle_stroke" cx="25" cy="25" r="${r}"/>
                    <text id="circle_value" x="50%" y="52%">${input}${tspan}${unit}</tspan></text>
                  </svg>
                `;
            }

            if (domain === 'climate') {
                return circle(state, input, unit);
            }
        }
      ]]]
  styles:
    card:
      - --c-stroke-color-on-target: "#b0b0b0"
      - --c-stroke-color-off-target: none
      - --c-stroke-color-on-current: none
      - --c-stroke-color-off-current: none
      - --c-fill-color-on-target: none
      - --c-fill-color-off-target: rgba(255,255,255,0.04)
      - --c-fill-color-on-current: rgba(78,198,110,0.6)
      - --c-fill-color-off-current: rgba(255,255,255,0.04)
      - --c-stroke-width: 2.3
      - --c-stroke-width-current: 0
      - --c-stroke-width-dragging: 4
      - --c-font-color: "#97989c"
      - --c-font-color-off: "#97989c"
      - --c-font-color-on: white
      - --c-font-size: 14px
      - --c-unit-font-size: 10.5px
      - --c-font-weight: 700
      - --c-letter-spacing: -0.02rem
    custom_fields:
      circle_target_temp:
        - display: initial
        - width: 88%
        - margin: -3% 2% 0 0
        - justify-self: end
        - opacity: 1
      circle_current_temp:
        - display: initial
        - width: 88%
        - margin: -3% 14% 0 0
        - justify-self: end
        - opacity: 1
    grid:
      - grid-template-areas: |
          "circle_current_temp  circle_target_temp"
          "n                    n"
          "s                    s"
      - grid-template-columns: repeat(2, 1fr)
      - grid-template-rows: auto repeat(2, min-content)
      - gap: 1.3%
      - align-items: start

This is what i get when the climate entity state is off, no problems. Current temperature is shown in the top left corner:
image

When the climate enitity state is heat, this is what i get, but this is not the way i intended:
image

What i expected is this, with a green fill-color for the circle and the target temperature in the top right corner:
image

If someone could point me in the rigtht direction, it would be much appriciated! :crossed_fingers:

Yeah, that error doesn’t tell much. Test the most basic form locally then if that works add the json paths and lastly the secrets function.

import json, yaml, requests
from datetime import datetime
from urllib3 import disable_warnings
disable_warnings()

IP = " "
PORT = " "
USER = " "
PASS = " "
URL = f"https://{IP}:{PORT}"

login = requests.request("POST", f"{URL}/api/auth/login", \
    headers={"Content-Type": "application/json"}, \
    data=json.dumps({"username": USER, "password": PASS}), verify=False)
response = requests.request("GET", f"{URL}/proxy/network/api/s/default/stat/device/", \
    cookies=login.cookies, verify=False)

print(response.json())

Thanks! 95c6a1f

Hello There
I have a problem with the footer and I have no idea what it can be. The size of the buttons does not adjust automatically. If I change the with from “fit-content” to 100px in footer.yaml, the buttons scale.

#button_card_templates: !include button_card_templates.yaml
button_card_templates:
  !include_dir_merge_named button_card_templates

views:
  - type: custom:grid-layout
    path: 0
    layout:
      #default
      margin: 0
      grid-gap: var(--custom-layout-card-padding)
      grid-template-columns: repeat(4, 1fr) 0
      grid-template-rows: 0 repeat(2, fit-content(100%)) 0fr
      grid-template-areas: |
        "sidebar  .           .       .             ."
        "sidebar  wohnzimmer  flur    schlafzimmer  ."
        "sidebar  media       sonos   home          ."
        "sidebar  footer      footer  footer        ."
      mediaquery:
        #phone
        "(max-width: 800px)":
          grid-gap: calc(var(--custom-layout-card-padding) * 1.7)
          grid-template-columns: 0 repeat(2, 1fr) 0
          grid-template-rows: 0 repeat(5, fit-content(100%)) 0fr
          grid-template-areas: |
            ".  .           .             ."
            ".  sidebar     sidebar       ."
            ".  wohnzimmer  schlafzimmer  ."
            ".  flur        home          ."
            ".  media       sonos         ."
            ".  footer      footer        ."
            ".  .           .             ."
        #portrait
        "(max-width: 1200px)":
          grid-gap: var(--custom-layout-card-padding)
          grid-template-columns: repeat(3, 1fr) 0
          grid-template-rows: 0 repeat(3, fit-content(100%)) 0fr
          grid-template-areas: |
            "sidebar  .           .             ."
            "sidebar  wohnzimmer  schlafzimmer  ."
            "sidebar  flur        home          ."
            "sidebar  media       sonos         ."
            "sidebar  footer      footer        ."
    cards:

      - type: custom:button-card #extra_styles fix
        styles: {card: [display: none]}

      #################################################
      #                                               #
      #                    SIDEBAR                    #
      #                                               #
      #################################################

      - type: vertical-stack
        view_layout:
          grid-area: sidebar
        cards:
          - type: custom:button-card
            entity: sensor.template_sidebar
            template: sidebar

      #################################################
      #                                               #
      #                  Wohnzimmer                   #
      #                                               #
      #################################################

      - type: grid
        title: Wohnzimmer
        view_layout:
          grid-area: wohnzimmer
        columns: 2
        cards:

          - type: custom:button-card
            entity: light.new_york
            name: New York
            template:
              - light
              - icon_hue

          - type: custom:button-card
            entity: light.schnapstrue
            name: Schnapstruhe
            template:
              - light
              - icon_hue

          - type: custom:button-card
            entity: sensor.weather_station_temperature
            name: Temperatur
            tap_action:
              action: more-info
            custom_fields:
              graph:
                card:
                  entities: 
                    - sensor.weather_station_temperature
            template:
              - temperature
              - icon_temp
            variables:
              popup_name: Temperatur


          - type: custom:button-card
            entity: light.salzstein
            name: Salzstein
            template:
              - light
              - icon_hue

      #################################################
      #                                               #
      #                    Schlafzimmer               #
      #                                               #
      #################################################

      - type: grid
        title: Schlafzimmmer
        view_layout:
          grid-area: schlafzimmer
        columns: 2
        cards:

          - type: custom:button-card
            entity: light.schlafzimmer
            name: Ständerlampe
            template:
              - light
              - icon_lamp

          - type: custom:button-card
            entity: fan.luftibert 
            name: "Lüftibert"
            hold_action:
              !include popup/schlafzimmer_fan.yaml
            tap_action:
              action: more-info
            template:
              - base
              - icon_fan



          - type: custom:button-card
            entity: media_player.hauptschlafzimmer
            name: Sonos
            hold_action:
              !include popup/sonos.yaml
            template:
              - base
              - icon_sonos
              - loader

          - type: custom:button-card
            entity: sensor.luftibert_temperature
            name: Temperatur
            tap_action:
              action: more-info
            custom_fields:
              graph:
                card:
                  entities: 
                    - sensor.luftibert_temperature
            template:
              - temperature
              - icon_temp
            variables:
              popup_name: Temperatur



      #################################################
      #                                               #
      #                     MEDIA                     #
      #                                               #
      #################################################

      - type: grid
        title: Media
        view_layout:
          grid-area: media
        columns: 1
        cards:

          - type: custom:swipe-card
            start_card: 1
            parameters:
              roundLengths: true
              effect: coverflow
              speed: 650
              spaceBetween: 20
              threshold: 7
              coverflowEffect:
                rotate: 80
                depth: 300
            cards:

              - type: custom:spotify-card
                account: default
                spotify_entity: media_player.spotify_jan_stager
                playlist_type: discover-weekly
                grid_covers_per_row: '2'
                limit: 4
                country_code: DE
                default_device: Küche
                display_style: grid
                known_connect_devices:
                  - id: d4757ab523224358f9c9052ee4de85ba324c41fa
                    name: Küche
                    entity_id: media_player.kuche

              - type: custom:mini-media-player
                entity: media_player.kuche
                hide:
                  power: true
                  volume: true
                  controls: true
                  source: true
                speaker_group:
                  platform: sonos
                  show_group_count: true
                  entities:
                    - entity_id: media_player.kuche
                      name: Sonos Küche
                    - entity_id: media_player.badezimmer
                      name: Sonos Badezimmer
                    - entity_id: media_player.buro
                      name: Sonos Büro
                    - entity_id: media_player.hauptschlafzimmer
                      name: Sonos Schlafzimmer
                    - entity_id: media_player.balkon
                      name: Sonos Balkon
                entities:
                  - type: custom:mini-media-player
                    entity: media_player.multiroom_player
                    group: true
                    source: icon
                    artwork: cover
                    info: scroll
                    hide:
                      volume: true
                      power_state: true
                  - type: custom:mini-media-player
                    entity: media_player.kuche
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.badezimmer
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.buro
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.hauptschlafzimmer
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.balkon
                    group: true
                    hide:
                      controls: true
                

      #################################################
      #                                               #
      #                    Sonos                      #
      #                                               #
      #################################################
      - type: grid
        title: Sonos
        view_layout:
          grid-area: sonos
        columns: 1
        cards:

          - type: entities
            entities:
              - type: custom:mini-media-player
                entity: media_player.kuche
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.buro
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.badezimmer
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.hauptschlafzimmer
                name: Schlafzimmer
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.balkon
                name: Balkon
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true

      #################################################
      #                                               #
      #                    Flur                       #
      #                                               #
      #################################################

      - type: grid
        title: Flur
        view_layout:
          grid-area: flur
        columns: 2
        cards:


          - type: custom:button-card
            entity: light.group_hall
            name: Hall
            template:
              - light
              - icon_spot

      #################################################
      #                                               #
      #                     Home                      #
      #                                               #
      #################################################

      - type: grid
        title: Home
        view_layout:
          grid-area: home
        columns: 2
        cards:

          - type: custom:button-card
            entity: script.home_leave
            name: Good Bye
            hold_action:
              action: none
            template:
              - base
              - icon_away

          - type: custom:button-card
            entity: script.home_arrive
            name: Welcome
            hold_action:
              action: none
            template:
              - base
              - icon_home

          - type: custom:button-card
            entity: script.good_night
            name: Good Night
            hold_action:
              action: none
            template:
              - base
              - icon_good_night

          - type: custom:button-card
            entity: script.music
            name: Music
            hold_action:
              action: none
            template:
              - base
              - icon_music


      #################################################
      #                                               #
      #                    FOOTER                     #
      #                                               #
      #################################################
      
      - type: horizontal-stack
        view_layout:
          grid-area: footer
        cards:

          - type: custom:button-card
            name: >
              <ha-icon icon="mdi:nas"></ha-icon> NAS
            tap_action:
              !include popup/footer_nas.yaml
            triggers_update:
              - binary_sensor.jan_home_update_available
              - sensor.jan_home_status
              - binary_sensor.jan_home_security_status
              - sensor.disk_use_percent
            variables:
              notify: >
                [[[
                  let id = this._config.triggers_update;
                  if (id.every(e => states[e]))
                      return states[id[0]].state === 'on'
                          ? 1
                          : states[id[1]].state === 'background_scrubbing' ||
                            states[id[2]].state === 'on' ||
                            parseFloat(states[id[3]].state) >= 85;
                ]]]
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="mdi:arrow-up-bold-circle-outline"></ha-icon> Updates
            tap_action:
              !include popup/footer_updates.yaml
            triggers_update:
              - sensor.hacs
              - sensor.docker_hub_beta
              - sensor.docker_hub
            variables:
              notify: >
                [[[
                  let id = this._config.triggers_update;
                  if (id.every(e => states[e])) {
                      let hacs = parseInt(states[id[0]].state),
                          installed = hass.config.version,
                          latest = installed.includes('b')
                              ? states[id[1]].state
                              : states[id[2]].state;

                      if (latest.includes('.') && Number.isInteger(hacs))
                          return hacs + (installed !== latest ? 1 : 0);
                  }
                  return 0;
                ]]]
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="custom:roborock-vacuum"></ha-icon> Buddy
            tap_action:
              !include popup/footer_vacuum.yaml
            triggers_update:
              - sensor.date
            variables:
              notify: >
                [[[
                  let id = states['sensor.morty_last_clean_end'];
                  if (id) return (Date.now() - Date.parse(id.state)) > 6048e5;
                ]]]
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="mdi:chart-line-variant"></ha-icon> Statistik
            tap_action:
              !include popup/footer_history.yaml
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="custom:cupra"></ha-icon> Cupra
            tap_action:
              !include popup/footer_cupra.yaml
            template: footer     

I am grateful for every hint

Hi @Mattias_Persson , first thank you for your setup and help. I did everything as listed in Github Installation Instructions. First I got error:
secret Youtube_token not defined
but I fixed it by commenting it in media.yaml.
But now I get the error:
Secret apexcharts_tibber not defined
I dont know how to fix and I already searched this post but didnt find any solution. I already installed the apexcharts repo via hacs.
Can you please give me a solution?
Thank you!

That’s outdated instructions, there’s no secrets anymore. You’ll have to copy the files from my repo again https://github.com/matt8707/hass-config/blob/00de2dd3ce0f3145e20ae0de5adda518b37b0194/INSTALL.md

Try this #00de2dd

Okay thank you so much I will try it!

Hi so I´m sure this was asked a lot, but can somebody please tell me which files I need to look at for changing text, language, adding my own entities?
Thanks