Wallboard for displaying information from Home Assistant
  • JavaScript 50.3%
  • PHP 32.7%
  • CSS 16.2%
  • Dockerfile 0.8%
Find a file
Nathan van Dael 3083e3e69d
All checks were successful
Auto Build & Push Multi-Arch Docker Image / build-and-push (push) Successful in 1m55s
Enhance chart modal with updated layout and localization; add last updated timestamp and improve CSS styles
2026-06-29 16:17:39 +02:00
.forgejo/workflows
api Add chart modal for detailed temperature history; update UI and localization 2026-06-24 18:17:20 +02:00
lang Enhance chart modal with updated layout and localization; add last updated timestamp and improve CSS styles 2026-06-29 16:17:39 +02:00
.dockerignore
.env.example Enhance dashboard with indoor climate data, rooms modal, and temperature sparklines; update README and localization files 2026-06-24 16:36:25 +02:00
.gitignore
app.js Enhance chart modal with updated layout and localization; add last updated timestamp and improve CSS styles 2026-06-29 16:17:39 +02:00
docker-compose.override.yml
docker-compose.yml
Dockerfile
i18n.js
icon-192.png
icon-512.png
index.php Enhance chart modal with updated layout and localization; add last updated timestamp and improve CSS styles 2026-06-29 16:17:39 +02:00
LICENSE
manifest.php
nosleep.mp4
README.md Add chart modal for detailed temperature history; update UI and localization 2026-06-24 18:17:20 +02:00
style.css Enhance chart modal with updated layout and localization; add last updated timestamp and improve CSS styles 2026-06-29 16:17:39 +02:00

Internal Dashboard

A fullscreen wallboard for displaying Home Assistant sensor data, camera feeds, and weather forecasts. Designed to run on a wall-mounted tablet or monitor.

Features

  • Live clock and date
  • Outdoor and indoor temperature and humidity (top left), each with a smooth temperature history sparkline (configurable time range)
  • Click the indoor climate card to open a modal with the temperature and humidity of other rooms (also with sparklines)
  • Click any temperature tile (outdoor, indoor, or a room) to open a large history chart with labelled X (time) and Y (value) axes; the indoor tile stays clickable for its own chart when no rooms are configured
  • Configurable quick-access entities in the top-right bar
  • Camera feed with a subtle blue-tint overlay and optional location dot
  • Daily and hourly weather forecasts with precipitation charts (equal-height, side by side)
  • Toggle support for switches, lights, automations, and scripts
  • Real-time updates via Home Assistant WebSocket API (60 s polling fallback)
  • Multi-language support (Dutch, English, German) — auto-detected from browser
  • PWA support — installable on iPad/Android home screen
  • Screen wake lock to keep the display active (Wake Lock API + silent video fallback for iOS 15.8)
  • Subtle refresh button in the bottom-right corner

Compatibility

Tested with Home Assistant version 2026.6

Getting started

1. Configure environment

Copy .env.example to .env and fill in your values:

cp .env.example .env

2. Run with Docker

docker compose up -d

The dashboard is available at http://localhost:8080.

For development, docker-compose.override.yml mounts the project directory as a volume so changes are reflected immediately without rebuilding.

Environment variables

Two variables are required; all others are optional.

General

Variable Required Description
APP_NAME Display name shown in the browser tab, home screen, and PWA manifest. Defaults to Dashboard.

Home Assistant connection

Variable Required Description
HASS_URL Base URL of your Home Assistant instance, without trailing slash. Example: http://homeassistant.local:8123
HASS_TOKEN Long-lived access token. Create one via Profile → Security → Long-lived access tokens.

Security note: The token is injected into the page source by the PHP backend. Only expose this dashboard on a trusted local network — never on the public internet.

Entities

Variable Required Description
HASS_ENTITIES Comma-separated list of entity IDs to display as cards on the dashboard. If omitted, no general entity cards are shown.
HASS_ENTITY_NAMES Custom display names for HASS_ENTITIES, in the same order.
HASS_OUTDOOR_TEMP Entity ID for outdoor temperature, shown prominently in the top left.
HASS_OUTDOOR_HUMIDITY Entity ID for outdoor humidity, shown next to the outdoor temperature.
HASS_INDOOR_TEMP Entity ID for indoor temperature, shown next to the outdoor climate card in the top left.
HASS_INDOOR_HUMIDITY Entity ID for indoor humidity, shown next to the indoor temperature.
HASS_ROOM_NAMES Comma-separated room labels for the rooms modal (opened by clicking the indoor climate card).
HASS_ROOM_TEMPS Comma-separated temperature entity IDs for the rooms modal, in the same order as HASS_ROOM_NAMES.
HASS_ROOM_HUMIDITY Comma-separated humidity entity IDs for the rooms modal, in the same order as HASS_ROOM_NAMES.
HASS_HISTORY_HOURS 24 Number of hours of history shown in the temperature sparklines (1168).
HASS_TOP_ENTITIES Comma-separated entity IDs shown in the fixed top-right bar. Supports sensors, switches, lights, scripts, and automations. Text is truncated with an ellipsis if too long.
HASS_TOP_ENTITY_NAMES Custom display names for HASS_TOP_ENTITIES, in the same order.

Camera

Variable Required Description
HASS_CAMERA Entity ID of a camera to display (e.g. camera.buienradar). The image is rendered square with a grayscale + blue-tint overlay.
HASS_CAMERA_DOT Position of a small location dot on the camera image, as x,y in percentage (0100). Example: 52,48 places the dot slightly left of centre. Useful for marking your location on a rain radar.

Weather

Variable Required Description
HASS_WEATHER Entity ID of a weather integration for the daily forecast card (up to 8 days).
HASS_WEATHER_HOURLY Entity ID of a weather integration for the hourly forecast card (up to 24 hours).

The precipitation chart prefers the precipitation amount (mm) from the forecast. If the integration does not provide it (e.g. KNMI's daily forecast only exposes precipitation_probability), the chart falls back to showing the probability (%) instead. If neither field is present, no bars are drawn. Note that some integrations (e.g. Buienradar) do not support an hourly forecast at all — keep HASS_WEATHER_HOURLY on an entity that does.

Language

The dashboard language is automatically detected from the browser. Supported languages:

Code Language
nl Dutch
en English (default fallback)
de German

Translation files are located in lang/. To add a language, create lang/<code>.json following the structure of an existing file.

Real-time updates

The dashboard connects to the Home Assistant WebSocket API on load and subscribes to state_changed events. Entity cards are updated in place without rebuilding the DOM, which avoids camera image flicker. A 60-second polling interval runs in parallel as a safety net. The WebSocket reconnects automatically after 5 seconds if the connection is lost.

Troubleshooting

Inspecting the weather forecast

If a forecast card is empty or the precipitation chart shows no bars, you can inspect exactly what Home Assistant returns by adding ?debug to the forecast endpoint in your browser:

URL Forecast
http://<host>:8080/api/forecast.php?debug Daily (HASS_WEATHER)
http://<host>:8080/api/forecast.php?hourly&debug Hourly (HASS_WEATHER_HOURLY)

The response highlights the most useful diagnostics at the top:

  • available_keys — the fields each forecast entry exposes (look for precipitation and/or precipitation_probability).
  • has_precipitation — whether the precipitation (mm) field is present.
  • first_entry — the full first forecast entry.
  • raw_service_response — the complete weather.get_forecasts response.

This is handy when switching between weather integrations, since each exposes a different set of fields.

PWA / tablet installation

The dashboard can be installed as a Progressive Web App on iPad or Android:

  1. Open the dashboard in Safari (iPad) or Chrome (Android).
  2. Tap the share icon → Add to Home Screen.
  3. The app opens fullscreen without browser chrome.

The fullscreen button is automatically hidden when running in standalone (PWA) mode or when the Fullscreen API is unavailable.

Keeping the screen awake

Platform Method
Modern browsers Screen Wake Lock API
iOS 15.8 and older Silent looping H.264 video (nosleep.mp4) activated on first touch

On iPadOS 15 and older, also set Settings → Display & Brightness → Auto-Lock → Never for fully reliable always-on behaviour.

Docker

The image is built from the official php:apache base image. Apache mod_rewrite and mod_headers are enabled.

services:
  internal-dashboard:
    build: .
    container_name: internal-dashboard
    env_file:
      - .env
    ports:
      - "8080:80"

The docker-compose.override.yml file adds a bind-mount of the project directory for live development without rebuilding the image.