# 2026-06-08 ## sherpa-hub Shipped the UI v2 redesign — the hub went from plain light-Tailwind to a dark, polished dashboard matching the mockup I liked, without giving up the "stays-current-by-itself" guarantee that's the whole point of the rebuild. ### What we did Full brainstorm → spec → plan → subagent-driven build cycle: - Brainstormed the look using the visual companion. Looked at three directions first (minimal / dense-dark / playful), then I dropped in a reference mockup (the sherpa-dashboard-style dark dashboard with sidebar + summary cards + icon tiles + two-button cards) and we built around that. - Key call: **Path 3 (hybrid).** Adopt the mockup's look, but keep status, activity buckets, and all counts 100% auto-derived from GitHub + Render. The only hand-set data is set-once and non-rotting: per-app icon (glyph + color) in `icons.yaml`, and category tags from GitHub repo topics. This preserves the thing that matters most to me — it never goes stale on its own. - Wrote the spec (`docs/superpowers/specs/2026-05-20-ui-redesign-v2-design.md`, decisions UI-1..UI-15) and a 10-task TDD plan, then executed subagent-driven with spec + code-quality review on the load-bearing tasks. ### What shipped - Dark theme, violet accent, left sidebar (bucket filters with live counts + Diary/Health links) - 4 summary stat cards: Total / Live / Active / Needs Attention (the last links to /health and shows a green ✓ when nothing's wrong) - App cards: colored Lucide icon tile, name, description, category tag pills, status pill, and two buttons — "Open App ↗" (jumps to the app's URL) and "⌁ Status" (drills into the detail page) - Client-side search + grid/list toggle (no page reload, no backend) - `/apps` list view dropped — home IS the apps view now (301 redirect) - Detail, diary, and health pages all restyled dark ### How the icons work (for future me) `web/app/icons.yaml` maps each slug to a Lucide icon name + a color. The SVGs are self-hosted via the `lucide-static` npm package and inlined server-side — no CDN, no icon flash, glyphs color from the tile via currentColor. Lookup is case-insensitive (matters for repos like `Pips`/`Tanks` that GitHub stores with capitals). Add a line per new app; anything missing falls back to a slate box. `reload_icons()` fires on every sync upload so icon edits show up without a restart. ### Decisions recorded - D-012: UI v2 dark dashboard, Path 3 hybrid (auto-derived + set-once icons) - D-013: icons.yaml is a deliberate, bounded exception to D-001 (hub-owns-nothing) — an icon is a display preference with no source of truth elsewhere, and it doesn't rot, so it doesn't reintroduce the legacy failure mode - D-014: self-host Lucide via lucide-static, inlined (no CDN, no runtime JS) ### Numbers - 10 plan tasks, all subagent-driven with review gates - 99 tests pass (49 web + 50 sync) - Local full-page smoke render confirmed real Lucide SVGs inline on every page (17 on the dashboard) — proved the icon pipeline end-to-end, which the unit tests alone couldn't - Pushed to main; Render auto-deploy in flight ## ideas - Once the deploy lands, fill in `icons.yaml` for any app still showing the slate box, and sprinkle GitHub topics on repos I want category tags for. Both set-once. - Favorites was in the mockup but I cut it — no data source and it'd need upkeep. If I ever want it, the cheap version is a `favorites: [slugs]` list in a hub config file + a star toggle that's really just a filter. Only if I'll actually use it. - The "Needs Attention" card is a nice nudge — when it's >0 it's red with a count, when clean it's a green check. Worth watching whether it actually drives me to fix orphans/missing-memory, or whether I just ignore it like the legacy hub. ## notes - Reviewer caught a good one on the icon module: it suggested lowercasing the YAML keys to fix `Pips`/`Tanks`, but that would've BROKEN the match (GitHub slugs preserve case, so the cache has `Pips` with a capital). Right fix was case-insensitive lookup on both sides. Good reminder to verify review feedback against the actual data rather than implementing it blindly. - Subagent-driven dev keeps paying off: the model-vs-data reasoning above, the CVE catch last session, the schema-datetime tightening — all came from the review gates, not the first-pass implementation. - Hub URL unchanged: https://sherpa-hub-6psj.onrender.com (dark UI live after the deploy finishes). Still need to eyeball it + run a fresh sync. --- ## sherpa-hub — UI v2.1 polish (later same day) Same-day follow-up after I looked at the live v2 dashboard. Three quick refinements, brainstormed with the visual companion then built subagent-driven (5 tasks, 103 tests green). - **Buttons toned down.** The big filled-purple "Open App" bar was too much. Now both buttons are small outlined; "Open ↗" keeps a faint violet tint as the primary, "Status" is a quiet outline. - **Light mode.** Added a sidebar Light/Dark toggle (sun-moon). Default dark, remembered in the browser, applied before paint so there's no flash on reload. The light palette is a token-override block plus explicit light variants for the status pills and the open button (their dark translucent colors were invisible on white). - **The Yeti.** Went down a fun rabbit hole on the app icon — the plain Lucide "mountain" looked like a pencil. Generated a few yetis; landed on a flat-style "Coding Yeti" logo (shades + hoodie + laptop with `</>`). It's now sherpa-hub's icon on its card, the sidebar brand, and the favicon. Built a small extension: icons.yaml entries can now carry an `image` field that renders a standalone PNG instead of a recolored Lucide glyph — bounded one-app exception, every other app keeps the clean Lucide tiles. ### Notes / lessons - The icon detour was a good reminder that "give me an icon" and "here's a gorgeous AI illustration" are different things. Detailed full-color mascots are hero images, not 24px tiles. The flat two-tone logo (which even shipped with its own small-size preview) was the right kind of asset. - Verified review feedback against real data again: a reviewer wanted me to lowercase the icons.yaml keys to "fix" Pips/Tanks, but GitHub slugs preserve case so the cache really has `Pips` — case-insensitive lookup was the correct fix, not lowercasing the keys. - Source yeti images saved in D:\dev\sherpa-server\Images\ (yeti-laptop.png is the keeper). Crop recipe is in the v2.1 plan. ### Still to do - Eyeball the live site after deploy: yeti everywhere, smaller buttons, theme toggle. Run a fresh sync so the sherpa-hub *card* picks up the yeti. - If the yeti's dark hoodie is low-contrast on a dark card, there's a ready one-line `.icon-tile:has(.icon-img)` plate fix noted in the plan. --- ## sherpa-hub — end of day: two bugs on the live v2.1 site (paused, resume tomorrow) Looked at the deployed v2.1 site. Light/dark mode works. Two issues; both root-caused (systematic-debugging), no fixes applied yet — stopped for the day. **Bug 1 — yeti not showing.** Server side is verified correct: the image returns 200 image/png live, and the render test proves the sidebar HTML includes the `<img>`. So it's a browser cache (a stale failed-load from the brief window before the asset deployed). To do: hard-refresh (Ctrl+Shift+R) and confirm. Likely no code change. **Bug 2 — "Open" links go to GitHub, not the live app.** Real root cause: only 13 of 43 apps match a Render service. The matcher requires the Render service name to EXACTLY equal the repo slug, and many don't — georgianna-mahjong=games-mahjong, ken-half=half-training-app, four CFB* services=cfb-picks, plus ~27 repos not on Render (some at kenlill.com). All of those fall back to GitHub. The hub can't guess these — only I know the mappings/custom domains. Plan: a manual per-app `url:` override in hub config (like icons.yaml), precedence url > render > github. Need to decide tomorrow: (A) manual override only, or (B) also auto-pull Render custom domains. Leaning A. Then I supply the real URLs and re-sync. Also: the deployed cache is stale (last sync Jun 5) — a fresh sync is needed after the fix regardless. --- ## games-mahjong + sherpa-hub — evening wrap **Hub link fix shipped.** Built the per-app `url:` override in icons.yaml (precedence url > Render > GitHub), read at render time so no re-sync needed. First mapping: games-mahjong → https://mahjong.kenlill.com (verified live there — "Georgianna's Mahjong Tutorial"; the old Render service is suspended). 55 web tests green, pushed. Remaining GitHub-linking apps just need their real URLs added one line each. **kenlill.com apex finding:** the root domain is serving a *different, empty* sherpa-hub instance — no data, and NO auth (open to the world, though only the empty state shows). The real hub (sherpa-hub-6psj on Render) has the data and Basic auth. Recommended fix: move the kenlill.com domain to the real hub service. Decide tomorrow. **KenBot → mahjong: investigated, correctly STOPPED at pre-flight.** Ken dropped `D:\Personal\sherpa-kenbot\INTEGRATION.md` (animated talking help character for the mahjong help screen). Ran the doc's pre-flight gates; both fail: 1. KenBot is React-19-only; the mahjong app is vanilla JS + Vite (no React). Recommended path: a tiny React island just for the bot (package ships built ESM, so no JSX tooling needed in the host). 2. The doc requires an existing AI help backend; mahjong has none (Supabase Edge Functions for game moves only). Natural fit: a new `ask_kenbot` Edge Function calling an LLM with keys in Supabase secrets; the ElevenLabs voice proxy can be an Edge Function too (doc's Django proxy doesn't apply). Two decisions for Ken tomorrow: React-island vs vanilla-build, and which LLM/knowledge should power the bot's answers. Also: re-cloned games-mahjong to D:\Personal\games-mahjong (local copy had been lost in the D: cleanup — it was a repo-no-local orphan on the hub Health page), and created its missing STATUS.md + MEMORY.md with all of the above. Tomorrow's agenda: hub URL list + kenlill.com domain move + KenBot decisions.
Diary
Filtered to games-mahjong. Clear