Use when: creating or editing Home Assistant Lovelace dashboards, choosing card types, structuring views, applying CSS styling, or using HACS custom cards. Covers dashboard layout patterns, built-in and custom cards, actions, and modern best practices.
Scanned 9/1/2026
Install to Claude Code
npx -y skills add jimmybish/homelab --skill homeassistant-dashboards --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Homeassistant Dashboards?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jimmybish-homeassistant-dashboards)More formats (shields.io, HTML) on the badges page.
---
name: homeassistant-dashboards
description: 'Use when: creating or editing Home Assistant Lovelace dashboards, choosing card types, structuring views, applying CSS styling, or using HACS custom cards. Covers dashboard layout patterns, built-in and custom cards, actions, and modern best practices.'
---
# Dashboard Guide
Patterns and decisions for designing Home Assistant Lovelace dashboards.
## Table of Contents
- Dashboard Structure
- View Types
- Built-in Cards
- Features
- Actions
- Custom Cards
- CSS Styling
- HACS Integration
- Complete Example: Multi-View Dashboard
- Common Pitfalls
- Modern Best Practices (2024+)
- Visual Iteration Workflow
---
## Priorities
1. Start with `sections` views and `tile` cards unless the use case clearly needs something else.
2. Prefer built-in cards first, then HACS cards, then fully custom cards.
3. Add CSS or card-mod styling only after the dashboard structure and card choices are working.
## Dashboard Structure
```json
{
"title": "My Home",
"icon": "mdi:home",
"config": {
"views": [
{
"title": "Overview",
"path": "home",
"type": "sections",
"max_columns": 4,
"sections": [
{"title": "Climate", "cards": [...]},
{"title": "Lights", "cards": [...]}
]
}
]
}
}
```
**url_path rules:**
- New dashboards must contain a hyphen: `my-dashboard` (not `mydashboard`)
- Use `lovelace` to target the built-in default dashboard
- `dashboard_id`: internal identifier (returned on create, used for update/delete)
- `url_path`: URL identifier (user-facing, used in dashboard URLs)
---
## View Types
| Type | Use for |
|------|---------|
| `sections` | Most dashboards (RECOMMENDED) — grid-based, responsive |
| `panel` | Full-screen single cards (maps, cameras, iframes) |
| `sidebar` | Two-column layouts with primary/secondary content |
| `masonry` | Legacy — auto-arranges cards, less control |
### View Configuration
```json
{
"title": "View Name",
"path": "unique-path",
"type": "sections",
"icon": "mdi:icon",
"max_columns": 4,
"sections": [...],
"subview": false,
"badges": ["sensor.entity_id"],
"background": {"image": "url(/local/background.jpg)", "opacity": 0.3}
}
```
---
## Built-in Cards
| Category | Cards |
|----------|-------|
| **Modern Primary** | tile, area, button, grid |
| **Container** | vertical-stack, horizontal-stack, grid |
| **Logic** | conditional, entity-filter |
| **Display** | sensor, history-graph, statistics-graph, gauge, energy, calendar |
| **Legacy Control** | entity, entities, light, thermostat (use tile instead) |
**Default:** Use `tile` card for most entities. Use `references/dashboard-cards.md` to look up all 37 card types or fetch card-specific docs.
### Tile Card
```json
{
"type": "tile",
"entity": "climate.bedroom",
"name": "Master Bedroom",
"icon": "mdi:thermostat",
"features": [
{"type": "target-temperature"},
{"type": "climate-hvac-modes", "style": "dropdown"}
],
"tap_action": {"action": "more-info"}
}
```
### Grid Card
```json
{
"type": "grid",
"columns": 3,
"square": false,
"cards": [
{"type": "tile", "entity": "light.kitchen"},
{"type": "tile", "entity": "light.dining"},
{"type": "tile", "entity": "light.hallway"}
]
}
```
---
## Features
Quick controls available on tile, area, humidifier, and thermostat cards.
| Domain | Feature types |
|--------|--------------|
| Climate | `climate-hvac-modes`, `climate-fan-modes`, `climate-preset-modes`, `target-temperature` |
| Light | `light-brightness`, `light-color-temp` |
| Cover | `cover-open-close`, `cover-position`, `cover-tilt` |
| Fan | `fan-speed`, `fan-direction`, `fan-oscillate` |
| Media | `media-player-playback`, `media-player-volume-slider` |
| Other | `toggle`, `button`, `alarm-modes`, `lock-commands`, `numeric-input` |
Feature `style` options: `"dropdown"` or `"icons"`
---
## Actions
```json
{
"tap_action": {"action": "toggle"},
"hold_action": {"action": "more-info"},
"double_tap_action": {"action": "navigate", "navigation_path": "/lovelace/lights"}
}
```
Action types: `toggle`, `call-service`, `more-info`, `navigate`, `url`, `none`
### Visibility Conditions
```json
{
"visibility": [
{"condition": "user", "users": ["user_id_hex"]},
{"condition": "state", "entity": "sun.sun", "state": "above_horizon"}
]
}
```
---
## Custom Cards
Use custom JavaScript cards when built-in cards don't support your visualization.
### Minimal Custom Card
```javascript
class MyCard extends HTMLElement {
setConfig(config) {
if (!config.entity) throw new Error("Please define an entity");
this.config = config;
}
set hass(hass) {
if (!this.content) {
this.innerHTML = `<ha-card header="${this.config.title || 'My Card'}">
<div class="card-content"></div>
</ha-card>`;
this.content = this.querySelector(".card-content");
}
const state = hass.states[this.config.entity];
this.content.innerHTML = state ? `State: ${state.state}` : "Entity not found";
}
getCardSize() { return 2; }
}
customElements.define("my-card", MyCard);
window.customCards = window.customCards || [];
window.customCards.push({ type: "my-card", name: "My Card", description: "A custom card" });
```
Usage: `{"type": "custom:my-card", "entity": "sensor.temperature"}`
For isolated styling, use Shadow DOM (`this.attachShadow({ mode: "open" })`) and scope CSS inside the shadow root.
### Hosting
Use the HA dashboard resource API to convert inline code to a hosted URL, then register as a dashboard resource. Size limit: ~24KB source code.
### Custom Card Workflow
1. Write the card JavaScript class (see Minimal Custom Card above)
2. Register it as a dashboard resource via the HA REST API (`/api/config/lovelace/resources`) with `resource_type: "module"`
3. Use the card in your dashboard config with the `custom:` prefix
```json
{
"type": "custom:quick-status-card",
"entity": "sensor.temperature",
"name": "Living Room"
}
```
---
## CSS Styling
### Theme Overrides
```css
:root {
--primary-color: #03a9f4;
--ha-card-background: rgba(26, 26, 46, 0.9);
--ha-card-border-radius: 16px;
--ha-card-box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
```
### Card-mod (Per-Card Styling)
Requires the `card-mod` HACS component:
```yaml
type: entities
card_mod:
style: |
ha-card {
--ha-card-background: teal;
color: var(--primary-color);
}
entities:
- light.bed_light
```
---
## HACS Integration
| Use case | Solution |
|----------|----------|
| Popular community card | HACS — search and install via HACS API |
| Small custom styling | Inline CSS — register via HA dashboard resource API |
| One-off custom card | Inline module — register via HA dashboard resource API |
| Large/complex card | HACS or filesystem (`/config/www/`) |
### Finding and Installing Cards
Search HACS for community cards by name/category, review repository details, then install. HACS install operations can overwrite or add dashboard resources, so clients should ask for user confirmation before proceeding.
### Popular HACS Cards
- **mushroom** — Modern, clean card collection
- **bubble-card** — Stylish cards with heavy customisation and pop-up functionality
- **button-card** — Highly customizable buttons
- **mini-graph-card** — Compact graphs
- **card-mod** — CSS styling for any card
- **layout-card** — Advanced layout control
- **apexcharts-card** — Professional charts
---
## Complete Example: Multi-View Dashboard
```json
{
"views": [
{
"title": "Overview",
"path": "home",
"type": "sections",
"max_columns": 4,
"badges": ["person.john", "person.jane"],
"sections": [
{
"title": "Quick Actions",
"cards": [{
"type": "grid",
"columns": 4,
"square": false,
"cards": [
{"type": "button", "name": "Lights", "icon": "mdi:lightbulb", "tap_action": {"action": "navigate", "navigation_path": "/lovelace/lights"}},
{"type": "button", "name": "Climate", "icon": "mdi:thermostat", "tap_action": {"action": "navigate", "navigation_path": "/lovelace/climate"}},
{"type": "button", "name": "Security", "icon": "mdi:shield-home", "tap_action": {"action": "navigate", "navigation_path": "/lovelace/security"}},
{"type": "button", "name": "Energy", "icon": "mdi:lightning-bolt", "tap_action": {"action": "navigate", "navigation_path": "/lovelace/energy"}}
]
}]
},
{
"title": "Favorites",
"cards": [{
"type": "grid",
"columns": 3,
"square": false,
"cards": [
{"type": "tile", "entity": "light.living_room", "features": [{"type": "light-brightness"}]},
{"type": "tile", "entity": "climate.bedroom", "features": [{"type": "target-temperature"}]},
{"type": "tile", "entity": "lock.front_door"}
]
}]
}
]
},
{
"title": "Lights",
"path": "lights",
"type": "sections",
"icon": "mdi:lightbulb",
"max_columns": 3,
"sections": [
{
"title": "Living Room",
"cards": [{
"type": "grid",
"columns": 3,
"cards": [
{"type": "tile", "entity": "light.overhead", "features": [{"type": "light-brightness"}]},
{"type": "tile", "entity": "light.lamp", "features": [{"type": "light-brightness"}]},
{"type": "tile", "entity": "light.accent", "features": [{"type": "light-color-temp"}]}
]
}]
}
]
}
]
}
```
---
## Common Pitfalls
| Issue | Solution |
|-------|----------|
| url_path rejected | New dashboards need a hyphen: `my-dashboard` not `mydashboard`. Use `lovelace` for the default dashboard. |
| Entity not found | Use full entity ID: `light.living_room` not `living_room` |
| Features not working | Match feature type to entity domain (e.g., `light-brightness` only works on `light.*`) |
| Custom card not loading | Check resource type is `module` and verify URL is accessible |
| Card too large for inline | Use HACS or filesystem instead |
---
## Modern Best Practices (2024+)
- Use **sections** view type with grid-based layouts
- Use **tile** cards as primary card type (replaces legacy entity/light/climate cards)
- Use **grid** cards for multi-column layouts within sections
- Create **multiple views** with navigation paths (avoid single-view endless scrolling)
- Use **area** cards with navigation for hierarchical organization
**Legacy patterns to avoid:**
- Single-view dashboards with all cards in one long scroll
- Excessive use of vertical-stack/horizontal-stack instead of grid
- Masonry view (auto-layout) — use sections for precise control
- Putting all entities in generic "entities" cards
---
## Visual Iteration Workflow
For iterative dashboard design with visual feedback, add a browser automation MCP server:
### Recommended MCP Servers
- **Playwright MCP** (`microsoft/playwright-mcp`) — Take screenshots, interact with pages
- **Puppeteer MCP** — Similar browser automation capabilities
- **Chrome DevTools MCP** — Inspect elements, debug layouts
### Workflow
```
1. Create/update dashboard via the HA config API
2. Navigate browser to dashboard URL (e.g., http://homeassistant.local:8123/lovelace/my-dashboard)
3. Take screenshot to see current layout
4. Analyze screenshot for issues (spacing, alignment, colors)
5. Adjust configuration and repeat
```
### Example with Playwright MCP
```
1. Get the HA base URL from the system overview (e.g., "http://homeassistant.local:8123")
2. Update dashboard config via the HA REST API
3. Navigate browser to {base_url}/lovelace/{url_path}
4. Take screenshot → analyze → adjust → repeat
```
### Benefits
- See actual rendered output, not just JSON config
- Catch visual issues (card overlap, responsive breakpoints)
- Verify custom card styling
- Test on different viewport sizesIs this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!