A standalone Material Design 3 dashboard builder for Home Assistant, built with Svelte 5 and SvelteKit.
This project is not a Lovelace theme. It is a full dashboard application with its own app shell, generated and editable layouts, Home Assistant add-on support, shared backend configuration, touch/tablet ergonomics, Music Assistant controls, Radio Browser country radio, weather, meals, shopping, presence, attention/maintenance surfaces, and a growing smart-card library.
These public-safe screenshots are generated from a temporary demo configuration, not from a private Home Assistant instance.
Regenerate them with npm run screenshots:readme.
The app is designed for a household dashboard that works on wall tablets, phones, and desktops:
| Route | Purpose |
|---|---|
/ |
Initial landing route; redirects into the dashboard experience. |
/dashboard |
Main home/floor/room dashboard, generator, editor, and live card grid. |
/dashboard/[floor] |
Floor dashboard generated from Home Assistant floor/area data. |
/dashboard/[floor]/[room] |
Room dashboard with room-specific controls, sensors, media, security, and history. |
/attention |
"For You" surface for open doors/windows, motion, low batteries, unavailable entities, active media, lights on, updates, and other maintenance items. |
/presence |
Household presence, people, zones, guest mode hints, and commute/ETA sensor context. |
/music |
Music Assistant browsing, search, playback, favorites, radio, and default player controls. |
/meals |
Mealie recipes, imports, meal planning, serving scaling, shopping lists, and optional Albert Heijn export. |
/weather |
Weather dashboard with forecasts, rain radar, rain graph, and environmental widgets. |
/calendar |
Calendar agenda view through Home Assistant calendar services. |
/library |
Live card/component library with examples for dashboard cards and editor flows. |
/theme |
Material Design 3 theme playground and visual token preview. |
/settings |
Home Assistant connection, integrations, navigation, dashboard, lock screen, kiosk, image providers, Mealie, AH, and app settings. |
Navigation is editable in Settings. Known routes are normalized so common routes get stable icons and labels even after older or customized navigation config is loaded.
The generator reads Home Assistant data and builds editable dashboard configs. It is preview-first: a generated dashboard is shown as a preview and is only saved when the user explicitly applies it.
Generation understands:
Clean regeneration replaces generated cards while preserving manual and pinned cards.
The dashboard editor supports:
The root app shell owns global editor/detail sheets so reusable card actions work on dashboard pages, the library route, attention, presence, and future feature routes.
The current card families include:
New cards should be added to the renderer, schemas, editor/config flow, generator where useful, focused tests, and /library examples. This keeps the app discoverable and prevents hidden one-off functionality.
The app uses Home Assistant as the source of live home state.
Supported behavior:
The browser never receives the Home Assistant Supervisor token in add-on mode. In standalone OAuth mode, the app also keeps Home Assistant access and refresh tokens server-side behind an HttpOnly session cookie.
The music route is built around Music Assistant and Home Assistant media players.
Features:
Country radio browsing prefers Home Assistant Radio Browser metadata through media-source://radio_browser/country/<CODE>. This gives reliable country-based station lists and avoids fuzzy Music Assistant search results. If Radio Browser is unavailable, the app falls back to Music Assistant search with curated filters.
The country station list is cached for a week, can fetch up to 1000 stations per country, and includes a name filter for quick navigation.
Mealie is the canonical recipe, meal-planning, and shopping backend.
The meals route supports:
Albert Heijn support is optional and Dutch-context only. AH tokens are stored server-side under the app data directory and are never exposed to the browser. The AH flow starts from reviewed/deduplicated shopping rows, shows product/free-text choices, and exports to the main AH shopping list.
The attention surface answers "what needs attention now?"
It groups and surfaces:
The route and generated dashboard cards avoid summary-only cards that hide which entities need action.
The presence route provides household context:
Presence data stays local to Home Assistant and this app runtime.
Weather features include:
Calendar features include:
The app uses Material Design 3 color generation and component primitives.
Configurable UI behavior:
Kiosk mode is intended for wall tablets:
The UI supports:
nl) as the primary dashboard language.en).de).fr).es).Translations cover the app shell, dashboard/editor surfaces, settings, lock/kiosk areas, music, meals, weather, attention, presence, specialist cards, and common controls. New features should add translations for all supported languages in the same change.
data/config.json is the canonical shared household configuration.
Shared backend-backed state includes:
Additional server-side runtime files under data/ store integration settings and tokens such as Mealie, image-provider settings, Albert Heijn tokens, uploads, and generated assets. These files are intentionally ignored by git.
Browser localStorage is used only for:
Remote config updates are streamed through /api/events, and clients refresh /api/settings without write-back loops.
Requirements:
Install and run:
npm install
npm run dev
Useful commands:
npm run check
npm test -- --run
npm run build
npm run test:visual
npm run test:e2e
npm run test:visual runs Playwright visual smoke checks against a simulated Home Assistant ingress base path across desktop, tablet landscape, tablet portrait, and phone viewports. It covers dashboard, library, attention, presence, settings, music, meals, weather, and calendar. It checks local route failures, page overflow, visible text escaping local containers, key label contrast, screenshot-sampled image-label contrast, image-label protection, and key navigation/action overlap.
Build and run with Docker Compose:
docker compose up --build
Mount persistent data:
-v $(pwd)/data:/app/data
Or set an explicit data directory:
DASHBOARD_DATA_DIR=/srv/ha-dashboard/data
Standalone Docker now performs Home Assistant OAuth, REST, media, history, and WebSocket access from the app server. The Home Assistant URL you type in Settings is the browser-facing URL used to open the OAuth login page. If the app server needs a different address, configure a server-facing URL in .env:
DASHBOARD_HA_INTERNAL_URL=http://192.168.0.157:8123
This is the recommended Docker setup when homeassistant.local works in your browser but not inside the container. The login page still opens at the URL you entered, while token exchange, REST, media, history, and WebSocket proxying use DASHBOARD_HA_INTERNAL_URL.
As a lower-level fallback, you can also add a Docker host mapping:
DASHBOARD_EXTRA_HOST=homeassistant.local:192.168.0.157
Standalone mode starts Home Assistant OAuth from the browser, but the callback code is exchanged by the app server. Home Assistant tokens are stored in the server-side app data directory behind an HttpOnly session cookie.
This repository can be added to the Home Assistant add-on store:
https://github.com/mdegrootnl/svelte5-ha-dashboard-md3
The add-on lives in ha-dashboard/ and provides:
/data.SUPERVISOR_TOKEN.Local ingress-style preview:
npm run preview:addon
See ha-dashboard/DOCS.md for add-on-specific installation and troubleshooting notes.
First-run setup:
Implemented:
src/hooks.server.ts.src/lib/server/securityHeaders.ts.data/./api/ha-websocket proxy with a harmless browser token; the real HA token is loaded/refreshed server-side.Retry-After responses when exceeded.nosniff headers.cookie dependency is pinned to patched 0.7.2 through an npm override.CSP is intentionally deployment-aware:
unsafe-eval.Optional CSP controls:
DASHBOARD_CSP_CONNECT_SRC="https://ha.example.local wss://ha.example.local"
DASHBOARD_CSP_IMG_SRC="http://camera.example.local"
DASHBOARD_CSP_REPORT_ONLY=true
Use DASHBOARD_CSP_MODE=compat only when a trusted local deployment still depends on broad direct browser access to local HTTP/WS origins.
See securityrisks.md for current risks, mitigations, and hardening work.
src/
app.css
hooks.server.ts
lib/
components/ Shared UI, MD3 primitives, layout, settings, weather, viz
domain/ Pure generation, schema, contrast, analytics, and action logic
features/ Dashboard, attention, presence, music, meals, kiosk, lock screen, calendar
server/ Storage, deployment, proxy, image, Mealie, AH, and integration helpers
stores/ Global Home Assistant, registry, theme, weather, and shared stores
types/ Shared TypeScript types
utils/ Browser, app-base, icon, gesture, and helper utilities
routes/
api/ App settings, events, proxies, integration endpoints
attention/ For You / Attention
calendar/ Calendar agenda
dashboard/ Main dashboard route
library/ Card library and examples
meals/ Mealie, meal planning, shopping
music/ Music Assistant and radio
presence/ Household presence
settings/ Connections and app settings
theme/ Theme builder
weather/ Weather dashboard
ha-dashboard/ Home Assistant add-on metadata, docs, and image config
Architectural expectations:
+layout.svelte as the only global shell owner.PageShell.Testing expectations:
The maturity roadmap in BACKLOG.md is the source of truth.
Completed major slices include:
Still active:
MIT