How to Make a Dashboard for Your Home Assistant

How to Make a Dashboard for Your Home Assistant

Home Assistant is a multi-functional smart home solution that lets you link all of your smart home gadgets. However, if you want to control them or gain insight into your smart home, you'll need to create a Home Assistant Dashboard.

This is the third instalment of a three-part series on how I built my Smart Home dashboard with Home Assistant. I showed how to use and mount a FireHD tablet as a smart home dashboard in the first article. In the second article, we'll go through how to set up Home Assistant as well as MQTT. And we're going to make a Home Assistant Dashboard in this article.


It's good to know that I'm utilising Homey to operate my smart home. The interactive dashboard is the sole thing that Home Assistant is utilised for. It makes no difference if HA or Homey is your controller for the dashboard.

Good to know

I'm not a specialist with Home Assistant, but I've seen dashboards with a lot of advanced (and good) features that are also difficult to create. My goal with this dashboard was to gain insight into my smart home and make it simple for my family to modify the scenes in the house.

Home Assistant is set up using Yaml files, and I've written pretty much everything in the ui-lovelace.yaml file to keep things simple. However, it is preferable to break it into multiple files with greater configurations.

You can't just copy and paste setups from other users with HA. For your environment, you should truly develop your own configuration files. I'll try to explain how buttons, functions, and layouts are built and how they interact in this article. In order for you to be able to develop them for your smart home devices.

Because Homey handles almost everything automatically, I haven't implemented any automations or scripts. At night, we only need to press the button once to turn out the lights. However, there are instances when you want to change lighting scenes, such as when playing a board game, and this is where the tablet comes in.

Homey and Home Assistant are linked together.

MQTT has been used to connect Homey and Home Assistant. As a result, all of my Homey devices are also available as entities in HA. With the help of the programme Better Logic, I was able to construct trigger variables in Homey (Homey app).

These triggers can then be uploaded to Homey as a button (device), which becomes an entity in HA. The button can start a flow in Homey, therefore we can use Home Assistant to start flows in Homey.

Creating a Dashboard for the Home Assistant

I'll walk you through the process of creating the dashboard step by step. Please leave a remark below if you have any questions. The dashboard's layout and aesthetics are based on Dejan Markovic's design.

We'll employ a variety of Home Assistant plugins. I'll rename them when necessary, but make sure you have the following plugins installed

  • Weather Card
  • Button-Card
  • Config Template Card
  • Mini Media Player
  • Mini Graph Card
  • Kiosk Mode
  • Button Text Card
  • Card Mod
  • Layout Card
  • State Switch
  • Atomic Calendar Revive

The plugins are easiest to install via HACS (Home Assistant Community Store). As a result, double-check that this has been implemented in your HA setup.

Making the Grid for the Dashboard

The initial step is to make the dashboard's grid. On our home assistant dashboard, the grid specifies where we may position the various buttons, charts, and other material. We'll need the Layout-Card plugin to make our custom grid.

To install the plugin into your HA installation, follow the installation instructions. For this, I recommend that you use HACS.

I made a grid with 5 columns and 3 rows. A cell with a width of 160px and a height of 160px serves as the foundation. Only the first row and the last column are taller and wider than the rest.


Use the file editor in Home Assistant (see step 2 in this article) or FTP to open the ui-lovelace.yaml file.

We've set the type of the first card to the custom:grid-layout plugin and defined our main view as home.

"# Background color

background: rgb(248,250,251)

# Views

views:

  - title: Home

    id: home

    type: 'custom:grid-layout'

    layout:

      max_cols: 5

      # Define the width of the columns

      grid-template-columns: 160px 160px 160px 160px 280px

      # Define the height of the rows

      grid-template-rows: 220px 160px 160px"

I've set a maximum of 5 columns, as well as the width and height of each column and row. I've also changed the backdrop colour to a light grey/off-white.

Increasing the number of buttons on our HA Dashboard

I used the custom button card plugin for the buttons, which you can also get through HACS. The benefit of the custom button card is that it allows you to design your own button layout and use custom templates.

We'll also make use of the Card Mod plugin. This enables us to utilise custom card styling.

Because the dashboard is based on cards, we must first establish a cards section in our newly built view (dashboard). Add cards to the section below the layout:

"# Views

views:

  - title: Home

    id: home

    type: 'custom:grid-layout'

    layout:

      max_cols: 5

      # Define the width of the columns

      grid-template-columns: 160px 160px 160px 160px 280px


      # Define the height of the rows

      grid-template-rows: 220px 160px 160px

    # Cards (buttons) section

    cards:"

It's critical to keep an eye on your indents while using Yaml. There should be two spaces between them. Your configuration will not function if you add one more or fewer.

We'll start with a simple button that will turn an entity on or off. To make a button, add the following:

Note

YAML files can grow pretty big, to keep the article readable I will only show relevant parts. You can see where I left with the comment sections ( in this case # Cards (buttons) section )

"    # Cards (buttons) section

    cards:

    # Simple button

    - type: 'custom:button-card'

      template:

        - base  # Used for styling of the card

        - quick-action  # Additional styling of the card

      entity: light.kitchen # entity to light

      name: Kitchen lights  # Name on the card

      icon:  mdi:lightbulb-outline # Icon on the card

      show_state: false  # Show state of the entity (true of false)

      show_header_toggle: false 

      view_layout:

        grid-column: 1  # column position, first column

        grid-row: 2 # row position, second row

      styles:

        icon:

        - color: rgb(255,213,113) # icon color"

As you can see we have positioned the card in column 1 on the second row. If you want to create a card that is two rows width, you can simply set the grid-column to 1 / 3. It will start at position 1 and end before position 3.

The majority of the icons on materialdesignicons.com can be used.

Templates for button cards

The button card plugin enables you to build button templates. You can quickly style your button cards this way. I made two templates: a foundation for all cards and a quick-action template for the second row's buttons.

To use the templates, place the following code below the background colour and above the views we prepared earlier in your ui-lovelace.yaml file.

"# Templates

button_card_templates:

  base:

    styles:

      card:

        - height: 100%          

        - padding: 15px

        - background-color: rgba(255, 255, 255, 1);

      name:

        - color: rgb(24, 24, 24);

        - justify-self: start;

        - font-weight: 400

        - font-family: "LatoWeb"

      state:

        - color: rgb(117,124,136);

        - justify-self: start

        - font-weight: 400

        - font-family: "LatoWeb"

        - font-size: 14px

        - margin-top: -10px

    style: |

      ha-card {

        background-color: rgba(255, 255, 255, 1);

        border: 1px solid rgba(0, 0, 0, 0.05);

        border-radius: 3px;

        box-shadow: none !important;

        transition: width ease-in-out 0.5s,height ease-in-out 0.5s,border ease-in-out 0.2s,transform ease-in-out 0.2s !important;

      }

      #icon {

        width: 25px !important;

        margin-right: 8px;

        margin-top: -20px;

      }

      #container{

        margin: -10px 0;

      }

  quick-action:

    styles:

        card:

        - paddding: 15px;

        grid:

        - grid-template-areas: '"i" "n" "s"'

        - grid-template-columns: 1fr

        - grid-template-rows: 2fr 1fr 1fr

        img_cell:

        - align-self: start

        - text-align: start

        - justify-content: start

        name:

        - font-size: 17px

        - justify-self: start

        - color: #213953;

        - margin-top: 10px;

        state:

        - font-size: 13px

        - align-self: left

        - justify-self: start

        - color: rgb(170,171,175)


# Views"

The web typeface I'm using is Lato. You'll need to get this font from Google Fonts and save it to your /www/fonts/Home Assistant installation folder.

"body, html {

    font-family: "LatoWeb", sans-serif;

}"

The web typeface I'm using is Lato. You'll need to get this font from Google Fonts and save it to your /www/fonts/Home Assistant installation folder.

The final step is to change the configuration.yaml file to use the custom font. Make that the last two lines of the resources list are included.

lovelace:

  mode: yaml

  resources:

    [ { url: /hacsfiles/lovelace-card-mod/card-mod.js,                             type: module },

      { url: /hacsfiles/lovelace-layout-card/layout-card.js,                       type: module },

      { url: /hacsfiles/mini-graph-card/mini-graph-card-bundle.js,                 type: module },

      { url: /hacsfiles/mini-media-player/mini-media-player-bundle.js,             type: module },

      { url: /hacsfiles/atomic-calendar-revive/atomic-calendar-revive.js,          type: module },

      { url: /hacsfiles/weather-card/weather-card.js,                              type: module },

      { url: /hacsfiles/config-template-card/config-template-card.js,              type: module },

      { url: /hacsfiles/button-card/button-card.js,                                type: module },

      { url: /hacsfiles/lovelace-state-switch/state-switch.js,                     type: module },

      { url: /hacsfiles/kiosk-mode/kiosk-mode.js,                                  type: module },

      { url: /local/style.css,                                                     type: css },

      { url: /local/latofonts.css,                                                 type: css }]""

Keep in mind that you'll have to restart Home Assistant to see your changes in the configuration file take effect.


If you've adjusted the fonts and added the templates, you should see something like this:

Changing the status of the buttons

As you can see, the state of the kitchen lights is now on, but the icon does not reflect this. The state switch plugin comes in handy here. It allows you to swap out cards based on an entity's current condition.

The standard card button can display multiple icons depending on the status of the entity, but my buttons must cause Homey to activate a different entity (switch). As a result, I needed to update not just the appearance of the button, but also its functioning.

The kind of custom-button card has been replaced by custom:state-switch. You'll need to use an entity on which you want to update the status for the entity. A collection of lights in this example.

"    cards: 

    # Simple button

    - type: custom:state-switch # Set the card to custom:state-switch type

      entity: light.lampen_woonkamer  # Entity to base state on

      default: off

      view_layout:

        grid-column: 1

        grid-row: 2

      states:

        "on": # When the state of the entity light.lampen_woonkamer = on      

          # BUTTON WHEN LIGHTS ARE ON

          type: 'custom:button-card'  # Show our custom button card

          template:

          - base

          - quick-action

          entity: switch.lampen_uit_knop  # entity to trigger

          name: Room

          icon:  mdi:lightbulb-on # Icon

          show_state: true

          show_header_toggle: false

          state_display: "Turn off all lights"  # I like to display the action of the button

          styles: # Some custom styling

            icon:

            - color: rgb(255,213,113)

            style: |

                .button-card-main{

                    height:148px !important;

                    border: 1px solid rgba(0, 0, 0, 0.05);

                }

                #icon {

                    width: 25px !important;

                    margin-right: 8px;

                    margin-top: -20px;

                }

                #container{

                    margin: -10px 0;

                }

        "off":  # When the state of the entity light.lampen_woonkamer = off

          # BUTTON WHEN LIGHTS ARE OFF

          type: 'custom:button-card'

          template:

          - base

          - quick-action

          entity: switch.lampen_aan_knop

          name: Room

          icon:  mdi:lightbulb-outline

          show_state: true  

          show_header_toggle: false

          state_display: "Turn on all lights"

          styles:

            icon:

            - color: rgb(255,213,113)

            style: |

                .button-card-main{

                    height: 148px !important;

                    border: 1px solid rgba(0, 0, 0, 0.05);

                }

                #icon {

                    width: 25px !important;

                    margin-right: 8px;

                    margin-top: -20px;

                }

                #container{

                    margin: -10px 0;

                }"

This state switch is pretty straightforward. If the state of the entity light.lampen_woonkamer is on, display the first button (# BUTTON WHEN LIGHTS ARE ON). Otherwise, display the other custom button card.

Home Assistant has a custom button.

Entities aren't always on or off, and you might wish to update the button based on an entity's value. We can utilise a state template to accomplish this:

Home Assistant makes use of the Jinja2 templating engine, which can be a little confusing at first. Using the Developer Tools in Home Assistant to test your templates is a fantastic idea. Select the Template tab from the developer tools (left menu, directly above the get settings icon).


On the right side of the screen, you can try out your templates and view the outcomes (in the grey area)

How to Make Chart Cards

I have three charts on the dashboard's bottom row. These graphs show data about the house, such as temperature, humidity, and solar panels.

We'll utilise the tiny graph chart plugin for Home Assistant to make the charts. Download it through HACS once more.

"        # Humidity

        - type: 'custom:mini-graph-card'  # mini graph card type

          name: Humidity

          icon: 'mdi:water'

          entities:

            - entity: sensor.tado_humidity  # Entity to display

              show_legend: false

              show_state: true

              show_fill: false # Set fill to false for line chart

          show_state: true

          show_header_toggle: true

          view_layout:  # position on the grid

            grid-column: 2

            grid-row: 3

          hours_to_show: 12  # Show only last 12 hours

          points_per_hour: 2 # Show 2 data points per hour

          line_width: 8 # line thickness

          height: 140 # height of the chart

          animate: true # animate on reload of the screen

          upper_bound: 80 # Set upper limit of the chart (height possible value)

          lower_bound: 40 # Set lower limit of the cart

          align_icon: left

          align_header: left

          color_thresholds:  # Colors of the line, based on the value

            - value: 50

              color: "#00B4DB"

            - value: 70

              color: "#0083B0"

          show:

            labels: false

          style: |  # Styling of the card

            ha-card, :host{

                font-family: "LatoWeb";

                background-color: rgba(255, 255, 255, 1) !important;

            }

            ha-card{

                border: 1px solid rgba(0, 0, 0, 0.05) !important;

                border-radius: 3px !important;

                box-shadow: none !important;

                transition: width ease-in-out 0.5s,height ease-in-out 0.5s,border ease-in-out 0.2s,transform ease-in-out 0.2s !important;

            }

            .name > span {

                color: rgb(170,171,175);

                font-weight: 400 !important;

                font-size: 13px !important;

                font-family: "LatoWeb";

                opacity: 1 !important;

                width: 100px !important;

            }

            .icon {

                margin-right: 0px !important;

                color: rgb(170,171,175) !important;

                margin-left: -5px !important;

            }

            .header.flex .icon {

                --mdc-icon-size: 20px;

              }

            .states{

                font-size: 16px !important;

                font-weight: 400;

                color: #213953;

                font-family: "LatoWeb"

            }

            .state__value{

                font-size: 24px !important;

                font-weight: 400;

                color: #213953;

                font-family: "LatoWeb"

            }

            .state__uom{

                color: rgb(117,125,135) !important;

                font-size: 14px !important;

                font-family: "LatoWeb";

                opacity: 1 !important;

            }

            .graph {

                padding: 0 15px !important;

                margin-top: -10px !important;

            }"

The timeline, number of data points, and constraints are all critical settings for displaying good graphs:

"hours_to_show: 12

points_per_hour: 2

line_width: 8

height: 140

upper_bound: 80

lower_bound: 40"

A 12-hour timeline with two markers per hour would be ideal for temperature or humidity. However, you may wish to use extra points each hour for solar.

The upper and lower boundaries also aid in the creation of a pleasant, consistent graph. Take, for example, solar panels. On one day, you might be able to generate up to 4000 watts, but on another day, you might only be able to generate 500 watts.


As you can see, without any limitations, it appears that we have reached our maximum performance today.

Audio/Video Player

I first linked Sonos straight to Home Assistant for the media player. Add your Sonos (or other media player) to HA by going to configuration > integrations.

The media player card is simple to set up; simply add the Sonos system as an entity and set the artwork to Cover in my instance.

"- type: 'custom:mini-media-player'

          noPadding: true

          entity: media_player.sonos  # Your media player entity (Sonos in my case)

          artwork: cover # Display artwork, cover the whole card

          icon: mdi:play

          view_layout: # Position on the grid

            grid-column: 5  

            grid-row: 3

          hide:  # Hide what we don't need

            icon: true

            volume: true

            power: true

            prev: true

            next: true

            source: false

            controls: false

            mute: false

          style: |

            :host{

                font-family: "LatoWeb";

                background-color: rgba(255, 255, 255, 1) !important;

                --mini-media-player-base-color: #213953;

                --mini-media-player-overlay-base-color: #213953;

                --mini-media-player-overlay-accent-color: #213953;

            }

            ha-card{

                height: 100%;

                padding: 15px;

                border: 1px solid rgba(0, 0, 0, 0.05) !important;

                border-radius: 3px !important;

                box-shadow: none !important;

                transition: width ease-in-out 0.5s,height ease-in-out 0.5s,border ease-in-out 0.2s,transform ease-in-out 0.2s !important;

            }

            .ratio {

                padding-bottom: 70%!important;

            }

            .title-controls { 

                width: 100%; 

                height: 100%; 

            }

            ha-card.--has-artwork .cover{

                opacity: 0.3 !important; # Change the artwork opacity

                filter: grayscale(80%);  # Change the artwork color

            }

            ha-icon-button{

                color: #333 !important;

            }

            .mmp__bg{

                -webkit-filter: invert(1);

                filter: invert(1);

            }

            .entity__info__name{

                color: rgb(117,125,135) !important;

                font-weight: 400 !important;

                font-size: 16px !important;

            }"

The only adjustment I did was to apply a custom style to help the artwork mix in better with the dashboard's layout. By using an opacity of 0.3 and a grayscale of 80 percent.


Card of the Weather

After finishing the bottom rows, we'll go on to the weather card, which is the largest item on the home assistant dashboard.

I utilised icons created by Lai Ming and customised the Weather Card plugin for this. My GitHub repository has the custom icons and modified plugin.


First, install the Weather Card plugin through HACS and then upload the files from my Github repository to the /www/community/weather-card folder in your Home Assistant installation.

To get weather data, I'm utilising the Meteorologisk institutt (Met.no) integration. You can also use the DarkSky API or the OpenWeather Map. Simply follow the plugin's installation instructions.

"        #

        # Weather card

        #

        - type: custom:weather-card

          entity: weather.home # Weather entity

          icons: "/local/community/weather-card/icons/"  # load custom icons

          current: true  # Show current weather

          details: false

          forecast: true

          hourly_forecast: false

          number_of_forecasts: 3 # 3 days for case

          view_layout:

            grid-column: 1 / 5  # Span over the 4 colums

            grid-row: 1

          style: |  # Custom styling

            ha-card, :host{

                font-family: "LatoWeb";

                background-color: rgba(255, 255, 255, 1) !important;

            }

            ha-card{

                border: 1px solid rgba(0, 0, 0, 0.05) !important;

                border-radius: 3px !important;

                box-shadow: none !important;

                transition: width ease-in-out 0.5s,height ease-in-out 0.5s,border ease-in-out 0.2s,transform ease-in-out 0.2s !important;

                grid-template-columns: 1fr 2fr;

                grid-template-rows: 1fr;

                display: grid;

            }

            .current{

                width: 200px;

                margin-bottom: 0 !important;

                grid-template-columns: 1fr 1fr 1fr;

                grid-template-rows: 50px 30px 30px;

                display: grid;

            }

            .current .icon.bigger, .current .temp, .current .tempc {

                position: inherit;

            }

            .currentWeather{

                font-size: 18px !important;

                grid-column-start: 2;

                grid-column-end: 2;

                grid-row-start: 2;

                margin-top: 15px;

                color: rgb(114,114,114);

                text-align: left;

            }

             .current .temp {

                color: #213953;;

                font-size: 40px;

                grid-column-start: 1;

                grid-row-start: 1;

                justify-self: right;

                margin-top: 15px;

                opacity: 0.8

            }

            .current .tempc {

                color: rgb(170,171,175);

                opacity: 0.6;

                font-size: 20px;

                grid-column-start: 2;

                justify-self: left;

                grid-row-start: 1;

                margin-top: 8px !important;               

            }

            .current .icon{

                grid-column-start: 1;

                grid-column-end: 3;

                grid-row-start: 2;

                width: 50px !important;

                height: 50px !important;

                margin-top: 0px !important;

                text-indent: 0 !important;


                text-align: right;

                line-height: 50px;

            }

            .forecast .highTemp{

                color: #213953;

            }

            .forecast .precipitation{

                color: rgb(170,171,175);

            }

            .forecast .dayname{

                color: #213953;

            }"

A calendar has been added to the dashboard.

The calendar will be the final piece (card) that we will add. The Atomic Calendar Revive plugin will be used for this. You'll need to link your Google Calendar account to your Home Assistant setup. You can do so by following HA's official guide.

The calendar card now has some custom flair and the scrollbar has been hidden. You may now scroll through the future events without having to display the scrollbar.

"        #

        # Upcoming Events

        #

        - type: custom:atomic-calendar-revive

          entities:

          - entity: calendar.family  # Calendar name in Google

            titleColor: #213953;

            maxEventCount: 5  # Show max 5 events

          language: nl 

          europeanDate: true

          noEventsForNextDaysText: Geen afspraken komende dagen

          noEventsForTodayText: Geen afspraken vandaag

          untilText: tot

          fullDayEventText: Hele dag

          refreshInterval: 300

          dateFormat: LL

          locationLinkColor: rgb(170,171,175);

          showProgressBar: false

          view_layout:  # Position on the grid

            grid-column: 5 / 6

            grid-row: 1

          style: |

            ::-webkit-scrollbar {

                display: none;  # Remove the scrollbar

            }

            ha-card, :host{

                font-family: "LatoWeb";

                background-color: rgba(255, 255, 255, 1) !important;

            }

            ha-card{

                border: 1px solid rgba(0, 0, 0, 0.05) !important;

                border-radius: 3px !important;

                box-shadow: none !important;

                transition: width ease-in-out 0.5s,height ease-in-out 0.5s,border ease-in-out 0.2s,transform ease-in-out 0.2s !important;

            }

            .event-titleRunning {

                color: #213953;

            }

            .cal-card {

                padding: 0;

            }

            .cal-eventContainer{

                padding-top: 15px !important;

            }

            .event-title{

                color: #213953;

            }

            .daywrap {

                border-top: 10px solid rgb(248,250,251);

            }

            .hoursHTML, .relativeTime{

                color: rgb(170,171,175);

            }"

Kiosk Mode

When viewing the dashboard on the tablet, the final step is to remove the header and sidebar from Home Assistant. We're utilising the Kiosk mode plugin for this. Simply add the following code to your ui-lovelace.yaml, directly above the views, after you've installed the plugin.

"kiosk_mode:

  mobile_settings:

    hide_header: true

    hide_sidebar: true

    ignore_entity_settings: true

    custom_width: 1320 # Set this to the max width (or slightly higher) then the width of your tablet

# Views"

On the tablet, we merely want to remove the header and sidebar. As a result, we only use it on mobile devices with a screen size of less than 1320px.

Final Thoughts

It can be difficult to create your own personalised dashboard with Home Assistant. The HA community forums provide a wealth of information and tips, but most presume you already know something about HA.

I hope this tutorial was helpful in designing your own Home Assistant dashboard; if you have any questions, please leave a comment below.