Sensor Panel HUD is a Linux hardware telemetry overlay for fullscreen media setups. It combines a Go/Fiber backend with a browser HUD that sits on top of YouTube video, then lets you tune both media framing and overlay layout from a built-in settings UI.
The project is designed for kiosk-style dashboards (Hyprland, ultrawide, and small secondary displays), but it also works as a local observability panel while gaming, streaming, or monitoring workloads.
It was inspired by the Lian Li Universal Screen and created to accommodate the small format displays people mount inside a computer case.
Since those screens do not provide Linux support, I decided to build my own setup using free and open-source tools plus an inexpensive Lesown 1920x480 display from AliExpress. Similar options from brands like Wisecoco, Waveshare, Eyoyo, UPERFECT, and other generic HDMI mini displays should also work (for example 5 in, 7 in, and 13.3 in panels at 1920x480, 800x480, 1024x600, and 1920x1080).
screenrecording-2026-02-26_19-02-08.mp4
- Samples live CPU, RAM, and GPU telemetry on a fixed interval.
- Serves normalized metrics over REST and WebSocket.
- Renders a live HUD overlay with temperature, utilization, VRAM, and power.
- Plays YouTube video/playlist content under the overlay.
- Stores panel customization as versioned settings in SQLite.
- Applies new settings live (panel auto-reloads when settings are updated).
Tested on:
- Arch Linux
- Hyprland (Wayland)
- AMD Ryzen CPU
- AMD GPU (
amdgpu) lm-sensors
Runtime strategy status:
- Currently only an Arch Linux (Hyprland) strategy is implemented.
- Additional distro/window-manager strategies can be added over time.
Requirements:
- Go 1.25+
lm-sensors- AMD GPU sysfs paths (for GPU busy/VRAM sensors)
- User access to sensor power files (add your user to the
powergroup if needed)
Example (then log out/in):
sudo usermod -aG power "$USER"- Clone/download this repository, then install:
make installThis builds ./bin/sensorpanel and copies it to ~/.local/bin/sensorpanel.
You can override the install path:
make install INSTALL_DIR=/your/path/bin- Start the server:
sensorpanelIf sensorpanel is not in your PATH yet:
~/.local/bin/sensorpanel- Open:
http://localhost:9070/to view Sensor Panelhttp://localhost:9070/settingsto configure layout/media/metrics
- In Hyprland, add a keybind that launches Chrome in kiosk/fullscreen mode:
bindd = SUPER CTRL, P, Launch SensorPanel, exec, ~/.config/hypr/scripts/launch-sensor-panel.shThe launch-sensor-panel.sh script is shown in the Hyprland Extras section below.
- Add a window rule so the kiosk window opens on your small monitor workspace.
Example scripts (~/.config/hypr/scripts):
launch-sensor-panel.sh
#!/usr/bin/env bash
set -euo pipefail
PROFILE_DIR="$HOME/.config/chromium-sensor-panel"
hyprctl dispatch exec "chromium \
--class=chromium-sensor-panel \
--user-data-dir=$PROFILE_DIR \
--kiosk \
--noerrdialogs \
--disable-extensions \
--disable-infobars \
--disable-session-crashed-bubble \
--disable-translate \
--disable-features=TranslateUI \
--disable-sync \
\"http://localhost:9070\"
"run-sensor-panel-server.sh
#!/usr/bin/env bash
~/.local/bin/sensorpanelMake scripts executable:
chmod +x ~/.config/hypr/scripts/launch-sensor-panel.sh
chmod +x ~/.config/hypr/scripts/run-sensor-panel-server.shHyprland config snippets:
bindd = SUPER CTRL, P, Launch SensorPanel, exec, ~/.config/hypr/scripts/launch-sensor-panel.sh
exec-once = ~/.config/hypr/scripts/run-sensor-panel-server.sh
# Workspace dedicated to the sensor screen
workspace = 15, monitor:HDMI-A-1
# Move SensorPanel Chromium window to that workspace
windowrule = match:class ^(chromium-sensor-panel)$, workspace 15 silentAdjust workspace number and monitor name to match your setup (hyprctl monitors).
- Install dependencies for local development:
Most distros (Ubuntu, Omarchy, Fedora, Pop!_OS, etc.) already ship with
lm-sensors. Run sensors first to confirm it is available before installing.
sudo pacman -S lm_sensors
sudo sensors-detect
go install github.com/air-verse/air@latest- Create local env file:
cp .env.example .env- Run in dev mode (hot reload):
make devOr run once:
make runDatabase migrations are applied automatically at startup.
Assuming default APP_PORT=9070:
-
Main overlay:
http://localhost:9070/ -
Settings editor:
http://localhost:9070/settings -
Telemetry debug page:
http://localhost:9070/telemetry -
Metrics JSON:
http://localhost:9070/metrics
All of these are editable in the settings page and persisted as versioned records.
- Media source kind:
youtube,video,playlist - YouTube URL or video ID
- Playlist URL support (
list=parsing) - Video fit:
coverorcontain - Video alignment (for contain):
left,center,right - Video offsets:
video_offset_x_pct(-100to100)video_offset_y_pct(-100to100)
- Infinite playback loop guard (
infinite_video_playback)
- DaisyUI theme (cool, winter, business, nord, lofi, etc.)
- Overlay position:
left,right,center,cover - Overlay orientation:
columnorrow - Backdrop on/off (
overlay_disable_backdrop) - Fine-grained overlay padding (
0to500px per side)
- Metrics scale (
metrics_scale_pct:50to200) - Metrics offset X (
-1000to1000px) - Metrics offset Y (
-1000to1000px)
- Each save creates a new settings version.
- The newest saved version becomes
current. - Version history is visible in the settings page.
- The running panel receives a settings WebSocket event and reloads.
- Open
http://localhost:9070/settings - Adjust media/overlay/metrics controls
- Click Save version
- Panel reloads and applies the new current version
Create a new version:
curl -X POST http://localhost:9070/api/settings \
-H 'Content-Type: application/json' \
-d '{
"config": {
"name": "Main Stream Profile",
"layout": {
"name": "left",
"overlay_layout": "column",
"theme": "winter",
"video_fit": "cover",
"video_align": "center",
"video_offset_x_pct": 0,
"video_offset_y_pct": 0,
"infinite_video_playback": true,
"metrics_scale_pct": 100,
"metrics_offset_x": 0,
"metrics_offset_y": 0
},
"media_sources": [
{
"kind": "youtube",
"url": "https://www.youtube.com/watch?v=AKfsikEXZHM",
"label": ""
}
]
}
}'Get current settings:
curl http://localhost:9070/api/settings/currentList recent versions:
curl http://localhost:9070/api/settingsReturns a normalized snapshot:
{
"cpu": {
"temp_c": 38.6,
"util_pct": 12.4,
"power_w": 22.1
},
"ram": {
"total_gb": 31.9,
"used_gb": 11.4,
"avail_gb": 20.5,
"used_pct": 35.7
},
"gpu": {
"edge_c": 48,
"hotspot_c": 57,
"vram_c": 74,
"vram_used_gb": 3.2,
"vram_total_gb": 16,
"vram_used_pct": 20,
"power_w": 42,
"util_pct": 18
}
}GET /metrics/wsstreams live sensor snapshots.GET /settings/wsemits settings update events.
DATABASE_URISQLite path (default:~/.config/sensorpanel.db.sqlite3)APP_ENVapp mode (developmentenables verbose SQL logs)APP_PORTHTTP port (default in example:9070)APP_SHUTDOWN_TIMEOUTgraceful shutdown timeout (default:10s)
- Intended for localhost / trusted LAN use.
- Do not expose directly to the public internet without auth and transport security.
Main overlay:
Settings editor:
Telemetry page:
Settings tuning examples:
MIT. See LICENSE.