---
title: "A home dashboard on an old Samsung TV"
description: "A Tizen app that turns the living room TV into a calm home dashboard with eight screens, four seasonal themes and a remote that can water the garden."
date: 2026-10-16T18:00:00+02:00
lastmod: 2026-11-03T00:52:22+01:00
url: https://klimek.link/projects/tv-dashboard/
author: "Marcin Klimek"
source: https://klimek.link/projects/tv-dashboard/
---

# A home dashboard on an old Samsung TV

I wanted to see what's going on in the house without reaching for a phone, so in March I wrote a small Tizen app for our TV with weather, power use, internet speed and room temperatures. It had one screen, the cards didn't line up, and the colors on the TV differed from what I saw in Chrome on my laptop. In October I decided to rebuild it from scratch.

![Main screen of the design mockup, autumn day theme, sample data](glowny-autumn-day.jpg)

## A browser from 2015

Tizen 3.0 ships a web engine at roughly Chrome 47 level, which means no CSS variables, no grid, no `gap`, and JavaScript that has to stay at ES5. I keep one palette in a Python script that writes stylesheets with literal colors for every theme. A small checker greps the CSS and JS for anything Chrome 47 can't handle, and its self-test plants 12 violations and expects to catch all of them.

Cards sit on a 12-column module of 130 px columns with 24 px gutters on a 1920 × 1080 frame, and body text is at least 28 px because you read it from three meters away. Before touching any app code I built static HTML mockups of all the screens with sample data. Scripts took screenshots of each screen and theme, measured card edges against the grid and computed contrast ratios for 970 pairs of text and background colors.

There are four themes: autumn and winter, each with a day and a night variant that switch at sunrise and sunset. Night themes are dark and warm with dimmed surfaces, and every minute or two the whole picture shifts by up to 6 pixels so that static parts of the layout don't burn into the panel.

![Same screen in the winter night theme](glowny-winter-night.jpg)

## Eight screens and a remote

Channel up and down switch between the main screen, home server status, network devices, weather, garden, lights, our robot vacuum and two cameras. When nobody touches the remote, screens rotate every 30 seconds, and any key press pauses the rotation for five minutes. The weather screen has an animated rain radar, Meteosat clouds, yesterday's satellite photo and a 48-hour forecast.

![Weather screen of the mockup, with placeholder maps](pogoda-autumn-day.jpg)

The garden screen draws a plan of our garden with soil moisture sensors on it, and from the remote you can start one watering zone. Home Assistant stops the water on its own and never runs a zone for longer than 30 minutes, whatever happens on the TV side. Starting the vacuum takes a second OK within five seconds, and a held or double-tapped button doesn't count, so nobody sends the robot out by sitting on the remote.

![Garden screen of the mockup, with a sample garden plan and zone 2 watering](ogrod-autumn-day.jpg)

## Where the data comes from

The TV holds no API keys or passwords. It talks to a single nginx proxy that answers only the TV's address and only on a short list of paths, and nginx passes those requests on to Prometheus, Home Assistant, weather services and a camera bridge.

*Diagram: The TV asks one proxy, and the proxy knows the sources*

What's installed on the TV is little more than a shell that loads JavaScript and CSS from the server on every start. A change to a screen goes live after a reload, and I reinstall the package only for a new icon or a new permission. Native HLS video didn't work on this TV, so the camera tab loads hls.js when you open it and falls back to a still picture every 15 seconds.


Most of this code was written by Claude Code agents working from a spec and a design brief I approved, under the workflow I describe in [my workflow kit post](/posts/claude-workflow-kit/).

Source: https://klimek.link/projects/tv-dashboard/
