← Back to list

ha-dashboard-create
by dawiddutoit
Collection of Claude Code skills, agents, and plugins
⭐ 0🍴 0📅 Jan 20, 2026
SKILL.md
name: ha-dashboard-create description: "Create and update Home Assistant Lovelace dashboards programmatically via WebSocket API. Use when building custom dashboards, automating dashboard creation, or managing multiple dashboards for different users/views. Covers WebSocket protocol, dashboard structure, view configuration, and card layout patterns."
Home Assistant Dashboard Creation
Create and update Lovelace dashboards programmatically using the WebSocket API.
CRITICAL: Dashboard URL Path Requirements
Home Assistant requires dashboard URL paths to contain a hyphen:
- ✅ CORRECT: "climate-control", "mobile-app", "energy-monitor"
- ❌ WRONG: "climate", "mobile", "energy"
Rule: Always use kebab-case with at least one hyphen in the url_path field.
Quick Start
import json
import websocket
HA_URL = "http://192.168.68.123:8123"
HA_TOKEN = os.environ["HA_LONG_LIVED_TOKEN"]
def create_dashboard(url_path: str, title: str, config: dict):
"""Create or update a dashboard.
Args:
url_path: Dashboard URL path (must contain hyphen, e.g., "climate-control")
title: Dashboard display title
config: Dashboard configuration dict
"""
# Validate url_path contains hyphen
if "-" not in url_path:
raise ValueError(f"url_path must contain hyphen: '{url_path}' -> '{url_path}-view'")
ws_url = HA_URL.replace("http://", "ws://") + "/api/websocket"
ws = websocket.create_connection(ws_url)
msg_id = 1
# 1. Receive auth_required
ws.recv()
# 2. Send auth
ws.send(json.dumps({"type": "auth", "access_token": HA_TOKEN}))
ws.recv() # auth_ok
# 3. Check if dashboard exists
ws.send(json.dumps({"id": msg_id, "type": "lovelace/dashboards/list"}))
msg_id += 1
response = json.loads(ws.recv())
exists = any(d["url_path"] == url_path for d in response.get("result", []))
# 4. Create if doesn't exist
if not exists:
ws.send(json.dumps({
"id": msg_id,
"type": "lovelace/dashboards/create",
"url_path": url_path, # Must contain hyphen!
"title": title,
"icon": "mdi:view-dashboard",
"show_in_sidebar": True,
}))
msg_id += 1
ws.recv()
# 5. Save configuration
ws.send(json.dumps({
"id": msg_id,
"type": "lovelace/config/save",
"url_path": url_path,
"config": config,
}))
ws.recv()
ws.close()
Dashboard Configuration Structure
dashboard_config = {
"views": [
{
"title": "Overview",
"path": "overview", # View path (no hyphen required)
"cards": [
# Card configurations here
],
},
{
"title": "Climate",
"path": "climate", # View path (no hyphen required)
"cards": [
# More cards
],
},
],
}
Note: View paths (within a dashboard) don't require hyphens, only the dashboard url_path does.
WebSocket Message Types
| Type | Purpose |
|---|---|
lovelace/dashboards/list | List all dashboards |
lovelace/dashboards/create | Create new dashboard |
lovelace/dashboards/delete | Delete dashboard |
lovelace/config/save | Save dashboard config |
lovelace/config | Get dashboard config |
system_log/list | Check for lovelace errors |
Common Card Types
Entities Card
{
"type": "entities",
"title": "Climate",
"entities": [
"climate.snorlug",
"climate.val_hella_wam",
"climate.mines_of_moria",
],
}
Gauge Card
{
"type": "gauge",
"entity": "sensor.officeht_temperature",
"name": "Temperature",
"min": 0,
"max": 50,
"severity": {
"green": 18,
"yellow": 26,
"red": 35,
},
}
Grid Layout
{
"type": "grid",
"columns": 3,
"square": False,
"cards": [
# Cards here
],
}
Vertical Stack
{
"type": "vertical-stack",
"cards": [
# Multiple cards stacked vertically
],
}
Error Checking
Validate Dashboard Configuration
# 1. Check system logs for lovelace errors
ws.send(json.dumps({"id": 1, "type": "system_log/list"}))
logs = json.loads(ws.recv())
# Filter for 'lovelace' or 'frontend' errors
# 2. Validate dashboard configuration
ws.send(json.dumps({
"id": 2,
"type": "lovelace/config",
"url_path": "climate-control" # Must contain hyphen
}))
config = json.loads(ws.recv())
# 3. Validate entity IDs exist
ws.send(json.dumps({"id": 3, "type": "get_states"}))
states = json.loads(ws.recv())
entity_ids = [s["entity_id"] for s in states["result"]]
# 4. Check if entities used in dashboard exist
for card in dashboard_config["views"][0]["cards"]:
if "entity" in card:
if card["entity"] not in entity_ids:
print(f"Warning: Entity {card['entity']} not found")
Common Error Patterns
- URL path missing hyphen:
"url_path": "climate"→ Add hyphen:"climate-control" - Entity doesn't exist: Check entity ID in Developer Tools → States
- Custom card not installed: Install via HACS first
- JavaScript errors: Check browser console (F12) for configuration errors
Entity Validation
Verify Entity IDs Before Creating Dashboard
def get_entity_ids(ws) -> list[str]:
"""Get all available entity IDs from HA."""
ws.send(json.dumps({"id": 1, "type": "get_states"}))
response = json.loads(ws.recv())
return [state["entity_id"] for state in response.get("result", [])]
def validate_dashboard_entities(config: dict, available_entities: set[str]) -> list[str]:
"""Validate all entities in dashboard exist.
Returns:
List of missing entity IDs
"""
used_entities = []
missing = []
for view in config.get("views", []):
for card in view.get("cards", []):
# Extract entities from card (handles different card types)
if "entity" in card:
used_entities.append(card["entity"])
if "entities" in card:
used_entities.extend(card["entities"])
for entity in used_entities:
# Handle entity strings and dicts
entity_id = entity if isinstance(entity, str) else entity.get("entity")
if entity_id and entity_id not in available_entities:
missing.append(entity_id)
return missing
# Usage
ws = connect_to_ha()
available = set(get_entity_ids(ws))
missing = validate_dashboard_entities(dashboard_config, available)
if missing:
print(f"Warning: Missing entities: {missing}")
Entity ID Patterns (from HA instance)
Enviro+ Sensors
enviro_sensors = [
"sensor.enviro_sensor_temperature",
"sensor.enviro_sensor_humidity",
"sensor.enviro_sensor_pressure",
"sensor.enviro_sensor_light",
"sensor.enviro_sensor_pm1_0",
"sensor.enviro_sensor_pm2_5",
"sensor.enviro_sensor_pm10",
]
Office Sensors
office_sensors = [
"sensor.officeht_temperature",
"sensor.officeht_humidity",
"sensor.officeht_battery",
]
Climate Devices
climate_devices = [
"climate.snorlug",
"climate.val_hella_wam",
"climate.mines_of_moria",
]
Shelly Power Monitoring
power_sensors = [
"sensor.shellyplus1pm_*_switch_0_power",
"sensor.shellyswitch25_*_channel_1_power",
]
Complete Example
See scripts/create_dashboard.py for a complete working example.
Workflow
- Design dashboard - Plan views and card layout
- Validate entities - Check all entity IDs exist
- Connect to WebSocket - Authenticate with HA
- Check if exists - Query existing dashboards
- Create dashboard - Create if new (ensure url_path has hyphen!)
- Save configuration - Update dashboard config
- Verify - Check in HA UI and system logs for errors
URL Path Examples
| Dashboard Type | Bad URL Path | Good URL Path |
|---|---|---|
| Climate monitoring | "climate" | "climate-control" |
| Mobile view | "mobile" | "mobile-app" |
| Energy tracking | "energy" | "energy-monitor" |
| Air quality | "air" | "air-quality" |
| Irrigation | "irrigation" | "irrigation-control" |
Troubleshooting
Dashboard not appearing in sidebar
- Check
show_in_sidebar: Truein dashboard creation - Verify
url_pathcontains hyphen - Refresh browser (Ctrl+Shift+R)
- Check HA logs for errors
Configuration not saving
- Verify WebSocket authentication succeeded
- Check
url_pathmatches existing dashboard - Validate JSON structure (no syntax errors)
- Check system logs via
system_log/list
Entity not found errors
- Get all entities:
{"type": "get_states"} - Compare with entities used in dashboard
- Fix entity IDs or remove missing entities
- Ensure entity has proper
state_classfor sensors
Resources
- scripts/create_dashboard.py - Complete dashboard creation script
- references/card_types.md - All available card types and configurations
Score
Total Score
50/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon