Skip to content

Desk Companion — Kiosk Dashboard Design

Date: 2026-06-16 Status: Approved (brainstorm) — ready for implementation plan Target device: iPad (11th gen, A16, 2025) — model A3354 / MD4Q4LL/A. 10.9″ Liquid Retina, 2360×1640 px (≈1180×820 pt @2x), landscape, on a fixed desk arm, charging, kiosk mode during the workday.


1. Purpose

A brand-new, standalone Home Assistant dashboard — not a tab on the existing Home Command Dashboard — purpose-built for one always-on screen at Louis's desk. It is a glance-first "Desk Companion": you mostly look at it, with media playback as the one routinely-interactive element. It must look premium ("Midnight Glass") and be readable at a glance from a seated desk distance.

Decisions locked during brainstorm (visual companion)

Decision Choice
Primary job Desk Companion (personal + house blend, glance-first)
Modules Time+Weather · Office Air · Energy Now · Now Playing · House at a Glance
Aesthetic Midnight Glass (frosted glass on deep navy, gradient accents, thin type)
Layout Layout B — full-width hero band / three equal columns / thin house-status strip
Kiosk method HA Companion iOS app + Guided Access
Screen hours Always-on while charging (LCD, no burn-in); iOS Night Shift at night

Modules deliberately excluded (YAGNI): focus/pomodoro timer, a full internet panel (internet appears only as one chip), quick controls, calendar agenda.


2. Architecture

2.1 Dashboard delivery — YAML mode

A new YAML-mode dashboard, not a storage-mode one.

  • File: desk_companion.yaml (repo root, alongside other deployable config).
  • Registration: in configuration.yaml:
    lovelace:
      dashboards:
        desk-companion:
          mode: yaml
          title: Desk
          icon: mdi:monitor-dashboard
          show_in_sidebar: true   # hidden anyway by kiosk-mode on the iPad
          filename: desk_companion.yaml
    
  • Why YAML, not storage: this dashboard is code-built and heavily templated; Louis will never edit it in the UI. A version-controlled YAML file is the right home and avoids the fragile storage stop→swap→start deploy dance used for the main dashboard. The existing lovelace/home_command_dashboard.json stays storage-mode (the user does edit that one in the UI).
  • URL: /desk-companion (or /desk-companion/0 for the single view).

2.2 Deploy via CI

  • Add desk_companion.yaml to the deployable-config list in .github/workflows/ci.yml (deploy-ha job scps it to /config/).
  • Registering a new dashboard in configuration.yaml requires a full HA restart (not just a Lovelace reload), so the change set (configuration.yaml + desk_companion.yaml) deploys as a config change → CI ha core restart with health-check wait.
  • After registration, subsequent edits to desk_companion.yaml alone hot-reload via the dashboard's ⋮ → "Reload" (no restart) — but CI will still restart on push since it can't distinguish; acceptable for an infrequently-changed file. (Plan may add a YAML-only fast path later.)

2.3 Test-suite integration

  • Add desk_companion.yaml to the entity-reference scan (the test that asserts every referenced entity_id exists in tests/fixtures/entities.txt or the allowlist).
  • All entities this dashboard references already exist (see Appendix A) except sensor.time (added via the Time & Date integration — see §3) and the three new card resources (frontend, not entities). Refresh make snapshot after the Time & Date integration is added so sensor.time/sensor.date land in the fixture.
  • make test must stay green before any push.

3. Dependencies

3.1 HACS frontend cards to install (3 new)

Already installed: button-card, Mushroom, mini-graph-card, apexcharts-card.

Card Purpose Why needed
card-mod Frosted-glass effect (backdrop-filter: blur), gradient backgrounds, per-card CSS, full-viewport grid sizing Near-essential for the Midnight Glass aesthetic; nothing native does glassmorphism
mini-media-player "Now Playing" with album art, transport, volume, room source-select Themeable to Midnight Glass; native media-control can't be styled to match
kiosk-mode Hide HA header + sidebar for a full-screen kiosk view Standard way to strip HA chrome on a tablet

All three are standard, free HACS frontend plugins. Each must be added as a Lovelace resource (HACS does this on install). The plan documents install + resource registration.

3.2 Native integration to add

  • Time & Date (time_date / Settings → Devices → Add Integration → "Time & Date") to create sensor.time (minute resolution) and sensor.date. The hero clock binds to sensor.time so it ticks every minute without custom JS timers.

4. Visual system — "Midnight Glass"

Implemented as reusable card-mod snippets / button-card style blocks (the plan will factor these into shared templates so each module isn't copy-pasting CSS).

4.1 Color tokens

Token Value Use
--bg radial-gradient(130% 120% at 8% -10%, #1b2542 0%, #0a0e1a 58%) Dashboard background
Glass fill rgba(255,255,255,0.055) Card body
Glass border 1px solid rgba(255,255,255,0.12) Card edge
Glass blur backdrop-filter: blur(9px) Frosted effect
Text primary #e7ecf6 Values
Text muted #9fb0d0 Labels/secondary
Accent cool linear-gradient(120deg, #34d399, #22d3ee) Energy / good states
Accent brand linear-gradient(120deg, #fff, #9db4ff) Clock / hero
Accent purple linear-gradient(135deg, #8b5cf6, #3b82f6, #22d3ee) Media art, progress
Warn #fbbf24 (amber) / #ef4444 (red) Threshold states
Glow blobs blurred radial #3b82f6 (top-left) + #8b5cf6 (bottom-right) behind cards Depth

4.2 Typography

System font stack (-apple-system). Clock: thin (300), large, gradient-clipped. Values: 600–800 weight. Labels: 9px uppercase, 1.5px letter-spacing, muted.

4.3 Glass card recipe

Semi-transparent white fill + 1px translucent border + backdrop-filter: blur + 14px radius, over the navy gradient background with two blurred accent blobs for depth. Reference mockup: .superpowers/brainstorm/<session>/content/layout-options.html (Layout B, gitignored).


5. Layout (Layout B)

Single full-screen view (panel-style root card stretched to 100vh via card-mod) holding a CSS-grid of three bands:

┌───────────────────────────────────────────────┐
│  HERO BAND  (clock + date  ····  weather)       │  ~22% height, full width
├───────────────┬───────────────┬─────────────────┤
│  OFFICE AIR   │  ENERGY NOW   │  NOW PLAYING    │  ~56% height, 3 equal cols
│  (CO₂ ring)   │  ($ + TOU)    │  (media player) │
├───────────────┴───────────────┴─────────────────┤
│  HOUSE AT A GLANCE  (chip row)                  │  ~22% height, full width
└───────────────────────────────────────────────┘
  • Implemented with vertical-stack → [hero, horizontal-stack(air, energy, now), house], with card-mod forcing the stacks/cards to flex to fill the viewport height (no layout-card dependency).
  • 12–14px gaps; 14px outer padding. Tuned so nothing scrolls — the whole thing fits one screen at 1180×820 pt.

6. Module specifications

6.1 Time + Weather hero (full-width band)

  • Cards: custom:button-card (clock/date, binds sensor.time) + weather glyph/temps from weather.office and weather.forecast_home.
  • Shows: big live clock (HH:MM), long date, office temp + outdoor temp + condition, today's hi/lo.
  • Interaction: none (display only).

6.2 Office Air (column 1)

  • Card: custom:button-card rendering a conic-gradient ring gauge for CO₂, plus a 3-stat row (VOC, temp, RH).
  • Entities: sensor.office_carbon_dioxide (ring), sensor.office_volatile_organic_compounds, sensor.office_temperature, sensor.office_humidity.
  • Color thresholds (tunable):
  • CO₂: green < 800, amber 800–1200, red > 1200 ppm.
  • VOC: green < 500, amber 500–1000, red > 1000 (sensor units; verify ppb vs µg/m³ at build).
  • Interaction: tap → more-info popup (optional). Display-first.

6.3 Energy Now (column 2)

  • Cards: custom:button-card for the figures + custom:mini-graph-card sparkline.
  • Entities: sensor.energy_cost_today (big $), sensor.tou_period + sensor.tou_rate (pill), sensor.whole_home_power (live kW + sparkline), input_boolean.peak_mode (peak state).
  • States: TOU pill green for off/super-off-peak; red "PEAK · $0.30/kWh" with a "hold big appliances" hint when peak_mode is on. Sparkline = last few hours of whole-home power.
  • Interaction: none.

6.4 Now Playing (column 3)

  • Card: custom:mini-media-player, card-mod themed to glass.
  • Entities: default media_player.office_apple_tv; fall back / source-select among media_player.office_soundbar and other rooms (Sonos, echoes). Album art, title/artist, ⏮ ⏯ ⏭, volume.
  • Interaction: full transport control (the one routinely-interactive module). Source/room picker so Louis can drive office audio or grab another room.

6.5 House at a Glance (full-width strip)

  • Card: chip row (Mushroom chips or button-card chips), card-mod themed.
  • Chips (real entities only — no locks; none installed yet):
  • Garage: cover.right_garage_door_opener_garage_door + cover.left_garage_door_opener_garage_door → "Garage closed/OPEN" (red if either open).
  • Leaks: any of the ~12 leak binary_sensor.* wet → "Leak!" red, else "No leaks" green.
  • Presence: person.louis / person.lindsay (or zone.home count) → who's home.
  • Internet (single chip): sensor.speedtest_download → "858↓ Mbps", red if degraded.
  • Interaction: tap a chip → more-info (optional). When smart locks are installed later, add a lock chip.

7. Kiosk setup (device-side, documented not automated)

  1. Install the Home Assistant Companion app on the iPad; log in to the instance.
  2. Open the /desk-companion dashboard.
  3. Enable Guided Access (Settings → Accessibility → Guided Access) and triple-click to lock the iPad to the dashboard.
  4. kiosk-mode plugin config hides the HA header + sidebar — target this dashboard by path (and/or this device/user) so the rest of HA is unaffected.
  5. Always-on: Settings → Display → Auto-Lock → Never; keep it on the charging arm. Enable Night Shift (and optionally Reduce White Point) for nighttime comfort. Midnight Glass is already dark.

The plan will produce a step-by-step setup doc (and likely a short page in the MkDocs manual under a "Desk Kiosk" entry).


8. Testing & deploy plan

  1. Install 3 HACS cards + Time & Date integration; register resources.
  2. make snapshot (with the new sensor.time/sensor.date) → commit refreshed tests/fixtures/entities.txt.
  3. Build desk_companion.yaml; register in configuration.yaml.
  4. Extend ci.yml deploy list + the entity-ref test to include desk_companion.yaml.
  5. make test green locally.
  6. Push → CI tests → ha core restart (new dashboard registration) → verify dashboard renders on the iPad.
  7. Document kiosk setup steps.

9. Out of scope (YAGNI)

Focus/pomodoro timer; a dedicated internet panel; quick-controls module; calendar agenda (no calendar integration connected); any HVAC control (Ecobee-owned); editing the existing Home Command Dashboard.


10. Risks / open questions

  • Full-viewport fit without layout-card: card-mod height forcing on stacks should fill 1180×820 cleanly, but exact %/vh values need tuning on the real device. If stacks prove fiddly, fall back to adding custom:layout-card (a 4th HACS card).
  • mini-media-player + Apple TV / Echo quirks: Apple TV media entities expose limited transport; Alexa media players read unavailable when idle. Confirm which office player gives the best control surface at build; the source-picker mitigates.
  • VOC units: office VOC sensor may report ppb vs µg/m³ — confirm before setting thresholds.
  • YAML edits still trigger CI restart: acceptable now; optional future optimization to hot-reload YAML-only changes.

Appendix A — Entity reference

# Time / weather
sensor.time                         (NEW — Time & Date integration)
weather.office
weather.forecast_home
# Office air
sensor.office_carbon_dioxide
sensor.office_volatile_organic_compounds
sensor.office_temperature
sensor.office_humidity
# Energy
sensor.energy_cost_today
sensor.tou_period
sensor.tou_rate
sensor.whole_home_power
input_boolean.peak_mode
# Media
media_player.office_apple_tv
media_player.office_soundbar
# House at a glance
cover.right_garage_door_opener_garage_door
cover.left_garage_door_opener_garage_door
binary_sensor.*_leak_detector / *_leak_sensor   (group)
person.louis
person.lindsay
sensor.speedtest_download