№ 025 · 2026-09-29 · shipped · home assistant + a fire tablet on the wall

Designing for one screen

claudehome-assistantdashboardslovelacefully-kioskdesignthree-jsheadless-chrome

There’s a Fire tablet mounted on the wall at home. It runs Fully Kiosk pointed at Home Assistant, and it is the thing everyone in the house actually touches: lights, locks, the pool, the thermostat, which car is home.

Its dashboards had grown the way these things always grow. A card here when a device got added, a section there when I wanted something at a glance. Nobody ever designed the whole. Here’s what the lights page looked like this morning:

The old lights page: four crowded columns, names cut off mid-word, and the last column running off the bottom of the screen

Half the names are truncated — Kitchen Cei…, Guest Hou… — the last column runs off the bottom of the screen, and there’s no margin anywhere. It works. It also looks like what it is: a list that kept getting longer.

One screen, exactly

The first useful realisation was that I am not designing a website. There is exactly one screen this has to look good on, and I know its dimensions to the pixel: the tablet is 1920×1200 physical, which Home Assistant lays out at 1280×800. Not “responsive”. Not “works on mobile too”. One rectangle, every page, forever.

That changes the brief completely. Every page should fill that rectangle — not scroll, not float in the top third with a black void underneath — with a margin round the edge and room between the groups. It should look like it was built for the thing it runs on, because it was.

Letting the assistant see it

The second realisation was that I was about to ask Claude to design something it couldn’t look at.

The browser extension I’d normally use to show it a page was having a bad day, so it built its own eyes: a small script that launches headless Chrome with a throwaway profile, logs in to Home Assistant with a token, sets the viewport to exactly 1280×800, screenshots any dashboard, and deletes the profile. From then on every change went through the same loop — change the config, take the picture, look at it, fix what’s wrong — and it caught things I’d never have described in words: a stray separator at the end of a status line, colour names kissing the bottom edge of their buttons, a column 16 pixels from the bottom bezel.

It also got into the real tablet. Fully Kiosk has a remote-admin API on the local network, so it could send the tablet to any page and screenshot what the wall was actually showing, not a simulation of it. That turned out to matter.

Why the columns kept jumping

Home Assistant’s default dashboard layout is “masonry”: it drops cards into whichever column it thinks is shortest. The catch is thinks. It works from each card’s estimated size, and it keeps filling a column until that estimate passes a threshold. Shrink one column’s contents and it doesn’t stay a shorter column — it swallows the next one. Mid-redesign the home page went from three columns to two with no warning, the thermostat stacked neatly under the music player.

The fix was to stop letting it guess. Every page is now a sections layout with exactly one section per column: three columns, fixed, full stop. Equal-height cards come from the grid’s own row sizing rather than CSS overrides — which, it turned out, the card library I use quietly ignores anyway.

The home page got a header row: pool, thermostat, and an “ask AI” button for the front door, all the same height, with everything else hanging underneath.

The home dashboard: an even header row of pool, thermostat and front-door AI, then music, weather and the two cars, and the cameras on the right (blurred)

A design system for one rectangle

Once the columns stopped moving, the rest was rules, applied to every page:

Here’s the lights page again, after:

The new lights page: three columns of rounded room panels — kitchen, living room, bedrooms, garage, guest house, outside — every name readable, with a whole-house summary at the top right

Same lights. It now has room to breathe, and a small “whole house” panel that counts what’s on and offers an All inside off that asks before it does anything and leaves the outside lights alone.

The pool page is the one I use most, and it was the worst — it ran to nearly two screens, mostly because fourteen light colours were each getting a card the size of a coaster:

The pool page: pool controls and targets, the spa, a live backyard view (blurred), and a compact grid of the fourteen pool-light colours

Every button on it still shows an amber spinner while the pool equipment catches up — it can take half a minute to act, and the spinner is what stops everyone tapping it five more times.

Edit the generator, not the output

Four of these pages — garage, guest house, cameras and cars — aren’t hand-built. They’re generated by a script that lives with my Tesla telemetry project, because those pages are mostly car and door state. Editing them by hand would have lasted exactly until the next time the script ran.

So the design system went into the generator instead: a helper that turns any “title followed by some cards” into a padded panel, and a sections-layout wrapper that every generated page goes through. The cars page is the best before-and-after. It had been a page and a half of separate boxes and a nine-row list of details per car; it’s now one screen, with every value still on it:

The cars page: a map (blurred) and a 48-hour battery chart on the left, and a compact status grid for each car — battery, range, locks, doors, tyres — with a one-line summary underneath

The locks page got the same treatment — a panel per part of the property, and the last day’s activity alongside:

The locks page: main house, garage and guest house, and inside locks in panels, with a 24-hour activity log

The model that froze the wall

The last tab is a 3D model of the property — the house, the detached garage, the apartment above it and the pool — built from the builder’s construction drawings, with every light and lock live on it. You can tap a light in a 3D room to turn it off. It’s also, by a distance, the heaviest thing the tablet has to draw.

The floor-plan tab: a 3D model of the property, deliberately blurred here because it's my actual house

It’s blurred here for the obvious reason. It also taught me the lesson of the day.

When I went back to verify every page on the real tablet, each screenshot came back showing the same frozen frame of the floor plan, with a page-load bar stuck across the top — even after telling the tablet to go home. The tablet’s browser was stuck. My best explanation: the model was being redrawn sixty times a second, at full 1920×1200 resolution, whether anything had moved or not. On a laptop that’s invisible. On a Fire tablet’s GPU it’s a space heater.

The fix was a Fully Kiosk app restart over its API — no ladder required — and then two changes to the model: render at 1× instead of the screen’s full pixel density, and render only when something changes — you drag it, a light flips, the window resizes. Idle, it now does no GPU work at all.

It’s the kind of bug you only find by testing on the device, which is really the point of this whole entry.

What I’d tell someone doing the same

Every camera in these screenshots is blurred on purpose. The dashboards show a lot about a house, and the neighbours don’t need to see what I can.