October 4, 2026

My dashboard is on every TV, and none of them cast

homelabhome-assistant3 min read

The problem with casting

Home Assistant makes it trivially easy to “cast” an announcement, a camera feed, or a dashboard view straight to a TV. The problem is that casting takes over whatever’s on screen. Someone’s mid-episode, and suddenly the TV cuts to a weather alert or a doorbell camera, full screen, no way to dismiss it from the couch.

That’s not an announcement, that’s an interruption. I wanted information on the TVs without ever stealing the input away from whatever people were actually watching.

The approach: a page that’s already open

Instead of pushing content to the TV, I built a dashboard page that’s always already open on a dedicated input — most of my TVs have a spare HDMI input or a cheap streaming stick sitting on a tab pointed at it. Switching to “the dashboard input” is a deliberate choice someone makes, the same way you’d switch to any other input. Home Assistant never fights for the screen; it just updates a page that happens to be sitting there if you choose to look at it.

That page is read-only and key-gated — it reads a token from the URL so it’s not an open door into my dashboard, but it doesn’t accept input from the TV itself. It’s a one-way window.

Picking what’s on screen, by voice

The dashboard cycles through a handful of views on a timer: a homelab status board, a calendar view, a photo view. But sometimes you want to pin a specific view — say, the calendar, right before a family gets together. For that, I use a Home Assistant input_select that holds the current “pinned view,” and the dashboard page polls it and jumps there when it changes:

input_select:
  tv_pinned_view:
    name: TV Pinned View
    options:
      - auto
      - calendar
      - homelab
      - photos
    initial: auto

A voice command sets input_select.tv_pinned_view to whatever view you want, and every TV running the dashboard page picks it up within a few seconds. No casting, no hijacking — just a page quietly changing itself.

Speech, without a screen takeover

The other half of “announcements” is audio — I still want the house to be able to say things, just without yanking the screen along with it. For that, the dashboard page includes a hidden <audio> element that Home Assistant can point at a generated speech file:

<audio id="announcer" style="display:none"></audio>
<script>
  // Home Assistant calls this via a webhook/websocket message
  function announce(url) {
    const player = document.getElementById('announcer');
    player.src = url;
    player.play();
  }
</script>

The TV’s own speakers play the line, the screen doesn’t change at all, and whatever was already on stays exactly where it was.

Where that leaves things

None of my TVs “cast” anymore, by design. They each just have the dashboard page sitting on a spare input, ready if someone wants to glance at it, speaking up through a hidden audio element when something needs saying. It’s a smaller, less flashy solution than casting — and it’s the one that doesn’t make anyone want to throw the remote.

Enjoyed this

Here's what I'm building with it.

See projects →