The card that took five months and one evening to finish
A Home Assistant dashboard card, an archive folder full of contradicting decisions, and a live design session with an AI agent.
I have a folder on my desktop called govee-scene-card-archive-2026-08-06. It exists because I lost track of a feature: design docs in one gstack project, HTML mockups in another, the shipped code in a repo that isn't even the one generating the data it displays. Three homes for one card. By August I couldn't tell you what was live, what was designed but never built, and what I'd imagined.
One evening I dumped everything into that folder β INDEX, design docs, HTML prototypes, the shipped JS, the bridge source, the memory notes β and told my agent to read all of it and tell me what's next.
The archaeology
The story it found: I started this in March as next/prev buttons for cycling Govee lighting scenes. By June it had grown into a full button-card YAML dashboard with pin-and-restore and favorites, built on native Home Assistant helpers and scripts. I run a strict rule here: best-in-class visuals, most-native logic, and when those two collide, native wins everywhere except the actual pixels on screen. By July it had become a real custom Lovelace card, redesigned into a "now playing" layout, with a locked vision I'd called living scenes: the card as theatre, full-bleed animated colour fields decoded from each scene's real palette instead of a flat data readout. That last part got designed, mocked up, and shelved.
The archive also carried a finding from a July session, marked critical: the bridge had no way to jump directly to a scene by name. Cycling was the only navigation, and favorites could label a scene but never send you back to it.
That finding was wrong. It took an agent five minutes of reading the actual bridge source to prove it.
light.turn_on with an effect: parameter has called device_set_scene since forever, and every light publishes its entire scene list as a standard HA effect list. The July audit had looked for a select.<device>_mode_scene entity, found none, and concluded the primitive didn't exist. It missed that select entities are built for non-light devices only. For lights, scenes are effects. The primitive had been sitting there the whole time, misfiled as missing.
That's the kind of bug a diff review never catches. It shows up when you make an agent read the code instead of trusting a stale note about the code.
Shipping the thing that was already possible
Once that was untangled, the rest moved fast: a favourites tray that teleports (tap a favourite, the light jumps straight to that scene via the effect call), a restore-pinned-scene script that had been silently calling a select entity that never existed, fixed to resolve the actual light through the device registry and set the effect directly, a README describing a card version from three redesigns ago, rewritten. A three-agent adversarial review pass caught a nasty one: the favourites tray could get stuck open if the underlying capability disappeared mid-interaction β say a light going unavailable while you're browsing your favourites β with no way to close it.
Then the boring-but-necessary part. The bridge hadn't published a release since May, so none of the sensor enrichment my new card needed β thumbnails, hints, active state β existed on my running instance. I went to cut a release and every build failed with "Invalid base image." Home Assistant's docker-base project had rotated to a newer cosign signing toolchain in June, and every publicly available version of their builder action still shipped the old cosign, unable to verify the new signatures. Three months of silent build failures, and the fix was one line: --no-cosign-verify, the builder's own documented escape hatch for exactly this situation.
I updated the addon that night and had a real bug from my own release within a minute. The bridge now published the literal string "None" for "no scene active," and Home Assistant's MQTT layer treats that payload as a reset signal, collapsing the state to unknown. My card treated any unknown as offline and hid every control. The update meant to make everything richer made every idle light look dead instead. I fixed it and shipped a same-night follow-up.
Where it got interesting
I sent a screenshot and said the icons looked bad.
The agent fixed the CSS and opened a pull request in the same breath, screenshot as the only preview, and I stopped it there. I don't review visual work from a diff. I need to play with something before I can tell if it's right, and a PR description isn't playing with something. I said so, and the agent converted the PR back to draft and built an actual interactive local page instead: the real card code, running against real Govee icon URLs pulled from CDN, cycling through scenes in my own browser.
That's when the real design consultation started: why does the art look bad, and why is it inconsistent? Govee's scene "art" is a tiny flat app-icon badge that was never meant to be a hero image, and it's only present for scenes served through Govee's undocumented API. Scenes served through their official Platform API never get one. "Sometimes there's a picture" came down to two different data sources wearing the same UI. No amount of polish on a mediocre icon fixes a data problem.
How much weight should the icon get? Tap through the three options β same scene, same palette, three levels of icon prominence. Option A is what I actually sent that screenshot about: Govee's little sun icon stretched to fill the card.
Palette hero with the icon demoted to a small corner mark won: the same visual language whether or not an icon exists, which unifies the actual bug (two different backends, two different looks) instead of decorating around it.
The first pass at that direction still wasn't right. My note: not lighty enough, and the badge is hiding under the ON pill. Three motion treatments later, live and playable:
Aurora sweep won. Both fixed inside the same evening, both verified in the browser before a single line touched a pull request.
The part I like best: today's aurora is deterministic noise β a hash of the scene's name into three hues β because the bridge doesn't decode real palettes yet. The render path, the gradient math, the drifting blobs, doesn't know or care where the colours came from. When the bridge eventually decodes each scene's real palette from its icon file (the living scenes idea from March, still on the list), it drops into the same card with zero rendering changes. We built the shape of a future feature while shipping the MVP of a different one.
Here is the card as it actually ships β the real card code, not a mockup. Cycle with βΉ βΊ, favourite with β₯, and tap the β₯-count pill to open the tray and teleport straight to a scene. Toggle the art off to see that a scene with no icon gets exactly the same treatment.
What stuck with me
Two lessons, and neither is about the card.
The "preview before PR" correction was a workflow bug, not a nitpick. An agent that treats a screenshot as sufficient sign-off for a visual change is optimizing to look done. The fix was cheap: a local HTML harness loading the real component. It should be the default for any UI work, not something I have to ask for mid-session.
I also did all of this inside a workspace for my Govee bridge repo, while the card lives entirely in my home-assistant-config repo. I'd nested a worktree for the wrong project inside the wrong workspace because it was expedient at 11pm, and it worked fine right up until I asked myself where I should come back to next time. The bridge and the dashboard that reads it are two different projects with two different lifecycles. Treating them as one because they're related is exactly the kind of shortcut that turns into next August's archive folder.
I'm trying not to build that folder again.