Family Dashboard
The Problem
Section titled “The Problem”A six-year-old needs structure. Morning routines, evening routines, what’s happening today, what’s happening tomorrow. The information exists — in calendars, in weather apps, in parents’ heads — but it’s scattered across devices and requires an adult to interpret and relay it.
The goal: a single, always-on display mounted on the wall that Katherine can look at herself. What do I need to do this morning? Is it going to rain? What’s on the calendar today? And for the parents: quick camera checks and commute times without pulling out a phone.
Architecture
Section titled “Architecture”The dashboard is a React/Next.js application running on the home Kubernetes cluster, displayed on a wall-mounted tablet. It integrates with Home Assistant for device data, Google Calendar for scheduling, and the Nest camera system for live video feeds.
Tech Stack
Section titled “Tech Stack”- Frontend: React with Next.js — server-side rendering for fast initial load on the tablet
- Backend: Next.js API routes proxying to Home Assistant’s REST API
- Camera feeds: WebRTC via Home Assistant’s Nest SDM integration
- Hosting: Kubernetes pod on the home cluster (Orange Pi 5 nodes)
- Display: Wall-mounted tablet in the kitchen
Phase 1: Basic Widgets
Section titled “Phase 1: Basic Widgets”The initial version solved the “what does Katherine need to do” problem with four widgets:
- Calendar widget — today’s and tomorrow’s events from Google Calendar, color-coded by family member
- Weather widget — current conditions and forecast, with kid-friendly icons
- Clock — large, readable, with day-of-week (because six-year-olds are still learning days)
- Task checklist — morning and evening routines as checkable items (brush teeth, pack backpack, feed Maddie)
Phase 2: Camera Integration
Section titled “Phase 2: Camera Integration”Adding live camera feeds turned a simple dashboard into something the whole household uses.
WebRTC via Home Assistant
Section titled “WebRTC via Home Assistant”The camera widget connects to Nest cameras through Home Assistant’s Nest SDM (Smart Device Management) integration. The feed path: Nest camera → Google Cloud → Home Assistant → WebRTC → Dashboard.
Getting this working reliably was the hardest part of the project. The initial implementation had three bugs that each caused the feed to freeze or disconnect:
Track listener race condition (FAD-352). WebRTC connections fire ontrack events when media streams arrive. The original code attached the stream to the video element inside the ontrack handler, but occasionally the track arrived before the video element was mounted in React’s DOM. Fix: buffer incoming tracks and attach them once the video element’s ref is set.
Home Assistant WebSocket lifecycle (FAD-352). The HA WebSocket connection that negotiates the WebRTC session has its own lifecycle — it can disconnect during HA restarts, network blips, or session timeouts. The original code didn’t handle WebSocket reconnection, so a single HA restart killed all camera feeds until the dashboard page was manually refreshed. Fix: WebSocket reconnection with exponential backoff, plus re-negotiation of the WebRTC session after reconnect.
Retry storm (FAD-352). When the camera was offline (firmware update, network issue), the reconnection logic would retry aggressively — hundreds of connection attempts per minute, which triggered Nest’s rate limits and made recovery take even longer. Fix: capped exponential backoff with jitter, plus a frame watchdog that detects frozen feeds without hammering the connection.
Camera Widget Improvements (FAD-428)
Section titled “Camera Widget Improvements (FAD-428)”The second iteration of the camera widget added:
- Both cameras — front door and living room, switchable with a tap
- Auto-connect on load — camera feed starts immediately, no manual “connect” button
- Session renewal — WebRTC sessions expire; the widget transparently renews them before expiry
- Frame watchdog (FAD-435/436) — detects frozen frames (camera connected but no new video data) and triggers reconnection automatically
Nest SDM Quota
Section titled “Nest SDM Quota”One operational constraint: Google’s Nest SDM API has a daily quota on ExecuteDeviceCommand calls. Every WebRTC session negotiation consumes a command call. Frequent reconnections (from the retry storm bug) burned through the daily quota by mid-morning. The backoff fix resolved this, but the quota constraint means the reconnection logic needs to be rate-limit-aware — you can’t just retry aggressively when the feed drops.
Phase 3: Traffic and Polish
Section titled “Phase 3: Traffic and Polish”The third phase (FAD-333 epic) added commute logistics and refined the overall experience:
- Traffic widget (FAD-338) — commute time to Spencer’s office, powered by a Home Assistant travel time sensor. Shows current drive time with color coding (green/yellow/red based on deviation from typical).
- Container optimization (FAD-426) — the pod’s postStart hook was making 36 CLI calls on startup. Reduced to 1. Startup time dropped dramatically.
- Camera freeze detection (FAD-435/436) — automated detection of frozen video frames, distinct from connection drops. A frozen frame means the WebRTC connection is alive but no new data is flowing — requires a different recovery strategy (renegotiate the media stream, not the entire connection).
What’s Next
Section titled “What’s Next”The dashboard is in maintenance mode — all three phases are complete, the major bugs are fixed, and it’s been running reliably on the kitchen wall. Remaining items:
- Camera aspect ratio fix (FAD-429) — minor visual issue with the camera feed not filling its container correctly on certain screen sizes
- Camera widget review (FAD-428) — deployed and working, awaiting Spencer’s final review for the portfolio
What This Demonstrates
Section titled “What This Demonstrates”Family-first engineering. This isn’t a tech demo — it’s a tool a six-year-old uses every morning. The design constraints come from the user: large text, simple interactions, information that a child can act on independently. The technical complexity (WebRTC, Kubernetes, Home Assistant integration) is invisible to the person who matters most.
Real-time reliability matters. A dashboard that freezes, disconnects, or shows stale data is worse than no dashboard. The camera widget went through three bug-fix iterations because “usually works” isn’t good enough for something on the kitchen wall. The frame watchdog and session renewal exist because the failure mode of “frozen camera feed that looks connected” is particularly insidious — you think it’s working when it’s not.
Home Kubernetes as application platform. Running a family dashboard on a home K8s cluster (Orange Pi 5 nodes) proves the cluster isn’t just for agent infrastructure — it’s a general-purpose application platform. The dashboard gets the same benefits as every other cluster workload: automatic restarts, resource limits, rolling updates, and centralized logging.