Here’s my mushroom-style Home Summary Page. Still very much a work in progress (as always), but I’m very happy with how it’s looking.
(Special thanks to @rhysb and @dimitri.landerloos for putting the work into making the animated icons with card_mod!)
Weather Warnings: 4 separate conditional cards pulling data from my weather integration (Environment Canada) that only show when there is an active weather alert.
type: vertical-stack
cards:
- type: conditional
conditions:
- entity: sensor.thermal_comfort_frost_risk
state: high
card:
type: custom:mushroom-template-card
primary: Frost Alert
secondary: >-
Frost likely to occur when tempearature reaches {{
states('sensor.thermal_comfort_frost_point') | round(1) }}°C
icon: mdi:snowflake-alert
entity: sensor.thermal_comfort_frost_risk
icon_color: red
tap_action:
action: more-info
- type: conditional
conditions:
- entity: sensor.WEATHERENTITY_statements
state: '1'
card:
type: custom:mushroom-template-card
primary: '{{ state_attr(''sensor.WEATHERENTITY_statements'', ''alert_1'') }}'
secondary: >-
{{ state_attr('sensor.WEATHERENTITY_statements', 'alert_time_1')
}}
icon: mdi:alert-circle
entity: sensor.WEATHERENTITY_statements
icon_color: blue
tap_action:
action: url
url_path: ## YOUR URL PATH HERE
badge_icon: ''
fill_container: false
- type: conditional
conditions:
- entity: sensor.WEATHERENTITY_advisory
state: '1'
card:
type: custom:mushroom-template-card
primary: '{{ state_attr(''sensor.WEATHERENTITY_advisory'', ''alert_1'') }}'
secondary: '{{ state_attr(''sensor.WEATHERENTITY_advisory'', ''alert_time_1'') }}'
icon: mdi:alert
entity: sensor.WEATHERENTITY_advisory
icon_color: amber
tap_action:
action: url
url_path: ## YOUR URL PATH HERE
fill_container: false
- type: conditional
conditions:
- entity: sensor.WEATHERENTITY_watches
state: '1'
card:
type: custom:mushroom-template-card
primary: '{{ state_attr(''sensor.WEATHERENTITY_watches'', ''alert_1'') }}'
secondary: '{{ state_attr(''sensor.WEATHERENTITY_watches'', ''alert_time_1'') }}'
icon: mdi:alert
entity: sensor.WEATHERENTITY_watches
icon_color: orange
tap_action:
action: url
url_path: ## YOUR URL PATH HERE
fill_container: false
- type: conditional
conditions:
- entity: sensor.WEATHERENTITY_warnings
state: '1'
card:
type: custom:mushroom-template-card
primary: '{{ state_attr(''sensor.WEATHERENTITY_warnings'', ''alert_1'') }}'
secondary: '{{ state_attr(''sensor.WEATHERENTITY_warnings'', ''alert_time_1'') }}'
icon: mdi:alert
entity: sensor.WEATHERENTITY_warnings
icon_color: red
tap_action:
action: url
url_path: ## YOUR URL PATH HERE
fill_container: false
card_mod:
style: |
ha-state-icon {
animation: pulse 3s ease-in-out infinite;;
}
@keyframes pulse {
100% {opacity: 0;}
}
- type: conditional
conditions:
- condition: state
entity: sensor.WEATHERENTITY_endings
state: '1'
card:
type: custom:mushroom-template-card
primary: '{{ state_attr(''sensor.WEATHERENTITY_endings'', ''alert_1'') }}'
secondary: '{{ state_attr(''sensor.WEATHERENTITY_endings'', ''alert_time_1'') }}'
icon: mdi:clock-check
entity: sensor.WEATHERENTITY_endings
icon_color: grey
tap_action:
action: url
url_path: ## YOUR URL PATH HERE
fill_container: false
Garbage Collection: template card using custom schedule sensors
type: custom:mushroom-template-card
primary: Garbage Collection
secondary: |-
{% if states('sensor.garbage_collection') == '0' %}
Today between 8-9AM
{% elif states('sensor.garbage_collection') == '1' %}
Tomorrow between 8-9AM
{% else %}
in {{ states('sensor.garbage_collection') }} days
{% endif %}
icon: |-
{% if states('sensor.garbage_collection') == '0' %}
mdi:trash-can
{% else %}
mdi:trash-can-outline
{% endif %}
entity: sensor.garbage_collection
icon_color: |-
{% if states('sensor.garbage_collection') == '0' %}
green
{% elif states('sensor.garbage_collection') == '1' %}
amber
{% else %}
disabled
{% endif %}
tap_action:
action: more-info
hold_action:
action: more-info
visibility:
- condition: numeric_state
entity: sensor.garbage_collection
below: 2
Weather Summary: The actual summary is provided by my weather integration (Environment Canada), but I imagine you could create something similar with a template.
For this card, I also created 2 separate template sensors: "sensor.weather_icon_colour" which provides a colour value for the card icon based on the weather condition, and "sensor.weather_condition_easy" which makes the current condition more “grammatically correct” for the card (see the primary text on the card). The icons are also animated (check the forum for more animation options), and there’s several conditional chips for different information (the chips will also scroll horizontally when they won’t fit in the card width).
type: custom:stack-in-card
cards:
- type: custom:mushroom-template-card
primary: >-
Its currently {{ states('sensor.WEATHERENTITY_temperature') | round(0)
}}°C outside and {{ states('sensor.weather_condition_easy') }}.
secondary: '{{ states(''sensor.WEATHERENTITY_summary'') }}'
icon: |-
{% if is_state('weather.WEATHERENTITY_forecast', 'clear-night') %}
mdi:weather-night
{% elif is_state('weather.WEATHERENTITY_forecast', 'partlycloudy') %}
{% if is_state('sun.sun', 'below_horizon') %}
mdi:weather-night-partly-cloudy
{% else %}
mdi:weather-partly-cloudy
{% endif %}
{% else %}
mdi:weather-{{ states('weather.WEATHERENTITY_forecast') }}
{% endif %}
multiline_secondary: true
tap_action:
action: navigate
navigation_path: /mu-main/weather
icon_color: '{{ states(''sensor.weather_icon_colour'') }}'
card_mod:
style: |
{% set weather_code = states('weather.WEATHERENTITY_forecast') %}
{% if weather_code == 'clear-night' %}
ha-state-icon {
animation: moon 10s linear infinite, stars 5s linear infinite;
}
@keyframes moon {
0%, 100% { transform: rotate(12deg); }
30% { transform: rotate(-6deg); }
45% { transform: rotate(8deg); }
75% { transform: rotate(-10deg); }
}
@keyframes stars {
0%, 3.1%, 14.1% { clip-path: inset(0 0 0 0); }
3% { clip-path: polygon(1% 1%, 0% 99%, 99% 100%, 99% 62%, 68% 62%, 62% 44%, 76% 34%, 100% 34%, 99% 0%); }
14% { clip-path: polygon(1% 1%, 0% 99%, 99% 100%, 100% 25%, 51% 45%, 38% 34%, 36% 0); }
}
{% elif weather_code == 'partlycloudy' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, sun 2s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
{% elif weather_code == 'cloudy' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, sun 2s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
{% elif weather_code == 'pouring' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, rain 1s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
@keyframes rain {
0%, 50%, 100% { clip-path: inset(0 0 0 0); }
25% { clip-path: polygon(0 0, 100% 0, 100% 83%, 54% 83%, 62% 47%, 47% 46%, 38% 83%, 0 83%); }
75% { clip-path: polygon(0 0, 100% 0, 100% 70%, 75% 70%, 80% 48%, 63% 48%, 54% 94%, 32% 94%, 46% 46%, 30% 46%, 23% 72%, 0 72%); }
}
{% elif weather_code == 'rainy' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, rain 1.5s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
@keyframes rain {
50% { clip-path: polygon(0 0, 100% 0, 100% 73%, 71% 73%, 50% 39%, 29% 73%, 0 73%); }
}
{% elif weather_code == 'snowy' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, snow 4s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
@keyframes snow {
50% { clip-path: polygon(0 0, 100% 0, 100% 100%, 65% 100%, 76% 73%, 57% 49%, 34% 56%, 26% 79%, 37% 100%, 0 100%); }
51% { clip-path: inset(0 0 0 0); }
}
{% elif weather_code == 'fog' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, fog 4s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
@keyframes fog {
0%, 26%, 76%, 100% { clip-path: inset(0 0 0 0); }
25% { clip-path: polygon(0 0, 100% 0, 100% 59%, 60% 59%, 60% 74%, 100% 74%, 100% 100%, 0 100%); }
75% { clip-path: polygon(0 0, 100% 0, 100% 100%, 26% 100%, 26% 76%, 0 76%); }
}
{% elif weather_code == 'windy' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite;
transform-origin: 15% 50%
}
@keyframes cloudy {
0%, 100% { transform: scaleX(1.2); }
30% { transform: scaleX(0.9); }
45% { transform: scaleX(1.1); }
75% { transform: scaleX(0.8); }
}
{% elif weather_code == 'sunny' %}
ha-state-icon {
animation: spin 6s ease-in-out infinite alternate;
}
{% elif weather_code == 'lightning' %}
ha-state-icon {
animation: cloudy 10s ease-in-out infinite, lightning 4s infinite;
}
@keyframes cloudy {
0%, 100% { transform: translateX(3px); }
30% { transform: translateX(-1px); }
45% { transform: translateX(1.5px); }
75% { transform: translateX(-3.2px); }
}
@keyframes lightning {
10%, 15% { clip-path: polygon(0 0, 100% 0, 100% 100%, 47% 100%, 69% 55%, 66% 40%, 48% 39%, 24% 100%, 0 100%); transform: scale(1.1); }
10.1%, 15.1% { clip-path: inset(0 0 0 0); transform: scale(1); }
}
{% else %}
{% endif %}
}
- type: custom:mushroom-chips-card
chips:
- type: conditional
conditions:
- condition: state
entity: sun.sun
state: below_horizon
chip:
type: entity
entity: sensor.sun_next_rising
icon: mdi:weather-sunset-up
icon_color: orange
use_entity_picture: false
- type: conditional
conditions:
- condition: state
entity: sun.sun
state: above_horizon
chip:
type: entity
entity: sensor.sun_next_setting
icon: mdi:weather-sunset-down
icon_color: deep-orange
- type: entity
entity: sensor.WEATHERENTITY_humidity
icon_color: cyan
icon: mdi:water-opacity
- type: conditional
conditions:
- condition: state
entity: sensor.WEATHERENTITY_chance_of_precipitation
state_not: unknown
chip:
type: entity
entity: sensor.WEATHERENTITY_chance_of_precipitation
tap_action:
action: more-info
hold_action:
action: more-info
icon: mdi:weather-rainy
icon_color: light-blue
- type: conditional
conditions:
- condition: state
entity: sensor.WEATHERENTITY_wind_chill
state_not: unknown
chip:
type: template
entity: sensor.WEATHERENTITY_wind_chill
icon: mdi:weather-windy-variant
icon_color: cyan
content: '{{ states(''sensor.WEATHERENTITY_wind_chill'') }}°C Wind Chill'
- type: conditional
conditions:
- condition: or
conditions:
- condition: state
entity: sensor.thermal_comfort_frost_risk
state: high
- condition: state
entity: sensor.thermal_comfort_frost_risk
state: probable
chip:
type: template
entity: sensor.thermal_comfort_frost_risk
icon: mdi:snowflake-alert
icon_color: blue
content: Frost Risk
- type: conditional
conditions:
- condition: numeric_state
entity: sensor.WEATHERENTITY_wind_speed
above: 0
chip:
type: template
entity: sensor.WEATHERENTITY_wind_speed
icon: mdi:weather-windy
icon_color: grey
content: >-
{{ states('sensor.WEATHERENTITY_wind_speed') }}km/h {{
states('sensor.WEATHERENTITY_wind_direction') }}
tap_action:
action: more-info
- type: conditional
conditions:
- condition: numeric_state
entity: sensor.WEATHERENTITY_aqhi
above: 4
chip:
type: template
entity: sensor.WEATHERENTITY_aqhi
icon: mdi:air-filter
icon_color: |-
{% set aqhi = states('sensor.WEATHERENTITY_aqhi') | int %}
{% if aqhi >= 8 %}
red
{% elif aqhi >= 6 %}
orange
{% elif aqhi > 3 %}
amber
{% else %}
green
{% endif %}
content: |-
{% set aqhi = states('sensor.WEATHERENTITY_aqhi') | int %}
{% if aqhi >= 8 %}
AQHI Very High
{% elif aqhi >= 6 %}
AQHI High
{% elif aqhi > 3 %}
AQHI Moderate
{% else %}
AQHI Low
{% endif %}
({{ states('sensor.WEATHERENTITY_aqhi') }})
- type: conditional
conditions:
- condition: state
entity: sun.sun
state: above_horizon
- condition: numeric_state
entity: sensor.WEATHERENTITY_uv_index
above: 4
chip:
type: template
entity: sensor.WEATHERENTITY_uv_index
icon: mdi:sun-wireless
icon_color: |-
{% set uv_index = states('sensor.WEATHERENTITY_uv_index') | int %}
{% if uv_index >= 8 %}
red
{% elif uv_index > 6 %}
orange
{% elif uv_index > 3 %}
amber
{% else %}
green
{% endif %}
content: |-
{% set uv_index = states('sensor.WEATHERENTITY_uv_index') | int %}
{% if uv_index >= 8 %}
UV Very High
{% elif uv_index > 6 %}
UV High
{% elif uv_index > 3 %}
UV Moderate
{% else %}
UV Low
{% endif %}
({{ states('sensor.WEATHERENTITY_uv_index') }})
alignment: left
card_mod:
style: |
ha-card {
margin: -10px 12px 10px;
--chip-border-width: 0;
--chip-box-shadow: 0;
--chip-background: #9E9E9E20;
}
ha-card > .chip-container {
flex-wrap: nowrap;
overflow-x: scroll;
}
ha-card > .chip-container > * {
flex-shrink: 0;
}
Climate Summary: First, I made a “HVAC Action” template sensor to record the current action of the thermostat (I think this is redundant, but I was planning on using it for other things and wanted it to be readily available):
{{ state_attr('climate.nest_thermostat_name', 'hvac_action') }}
Then, I made the following Historical Stats sensors in my configuration.yaml (can’t make these in the UI yet):
##History Stats
- platform: history_stats
name: Climate Heat Today
entity_id: sensor.hvac_action
state: "heating"
type: time
start: "{{ now().replace(hour=0, minute=0, second=0) }}"
end: "{{ now() }}"
- platform: history_stats
name: Climate Cool Today
entity_id: sensor.hvac_action
state: "cooling"
type: time
start: "{{ now().replace(hour=0, minute=0, second=0) }}"
end: "{{ now() }}"
- platform: history_stats
name: Climate Heat Yesterday
entity_id: sensor.hvac_action
state: "heating"
type: time
start: "{{ now().replace(hour=0, minute=0, second=0) - timedelta(days=1) }}"
end: "{{ now().replace(hour=0, minute=0, second=0) }}"
- platform: history_stats
name: Climate Cool Yesterday
entity_id: sensor.hvac_action
state: "cooling"
type: time
start: "{{ now().replace(hour=0, minute=0, second=0) - timedelta(days=1) }}"
end: "{{ now().replace(hour=0, minute=0, second=0) }}"
With the 4 sensors created, I made 2 conditional template cards (one for Cooling and one for Heating) as below which will display “Heated (or Cooled) for __ hours and __ minutes” as the primary and “__hours and __ minutes more/less than yesterday” - if the heating/cooling time is less than yesterday, it will display a badge with a leaf otherwise it will display an up arrow:
(The conditional cards are set to only show the cards if the heating/cooling time is above “0”):
type: vertical-stack
cards:
- type: conditional
conditions:
- condition: numeric_state
entity: sensor.climate_heat_today
above: 0
card:
type: custom:mushroom-template-card
primary: '{{ states(''sensor.climate_heat_time_summary'') }}'
secondary: '{{ states(''sensor.climate_heat_yesterday_summary'') }}'
icon: mdi:home-thermometer-outline
entity: sensor.climate_heat_today
icon_color: red
tap_action:
action: more-info
badge_icon: >-
{% set total_minutes_today = states('sensor.climate_heat_today') | float
* 60 %}
{% set total_minutes_yesterday = states('sensor.climate_heat_yesterday')
| float * 60 %}
{% if total_minutes_today < total_minutes_yesterday %}
mdi:leaf
{% else %}
mdi:chevron-up
{% endif %}
badge_color: >-
{% set total_minutes_today = states('sensor.climate_heat_today') | float
* 60 %}
{% set total_minutes_yesterday = states('sensor.climate_heat_yesterday')
| float * 60 %}
{% if total_minutes_today < total_minutes_yesterday %}
green
{% else %}
red
{% endif %}
multiline_secondary: true
- type: conditional
conditions:
- condition: numeric_state
entity: sensor.climate_cool_today
above: 0
card:
type: custom:mushroom-template-card
primary: '{{ states(''sensor.climate_cool_time_summary'') }}'
secondary: '{{ states(''sensor.climate_cool_yesterday_summary'') }}'
icon: mdi:home-thermometer-outline
entity: sensor.climate_cool_today
icon_color: blue
tap_action:
action: more-info
badge_icon: >-
{% set total_minutes_today = states('sensor.climate_cool_today') | float
* 60 %}
{% set total_minutes_yesterday = states('sensor.climate_cool_yesterday')
| float * 60 %}
{% if total_minutes_today < total_minutes_yesterday %}
mdi:leaf
{% else %}
mdi:chevron-down
{% endif %}
badge_color: >-
{% set total_minutes_today = states('sensor.climate_cool_today') | float
* 60 %}
{% set total_minutes_yesterday = states('sensor.climate_cool_yesterday')
| float * 60 %}
{% if total_minutes_today < total_minutes_yesterday %}
green
{% else %}
red
{% endif %}
multiline_secondary: true
Calendar: Weekly Planner Card by FamousWolf (GitHub - FamousWolf/week-planner-card: Custom Home Assistant card displaying a responsive overview or multiple days with events from one of multiple calendars)
(NOT SHOWN) Vacation Mode and Guest Mode Cards: Conditional Template cards that indicate if Vacation/Guest Mode is on and what it means for certain schedules or routines (this is for the day my household inevitably decides to use Home Assistant… some day lol).
I would love to know your thoughts and feedback!!