Reflect run status in tab title + favicon (BEN-50)#54
Closed
benSepanski wants to merge 1 commit intomainfrom
Closed
Reflect run status in tab title + favicon (BEN-50)#54benSepanski wants to merge 1 commit intomainfrom
benSepanski wants to merge 1 commit intomainfrom
Conversation
Each top-level route now sets its own tab title and a tiny SVG favicon. The dashboard escalates to a recent failure for five minutes, so a tab parked alongside other work surfaces a red 'S' + '✖ BEN-30 failed' without forcing the user to switch tabs. - documentTitle.ts: pure helpers (dashboardTitle, runDetailTitle, faviconColor, buildFaviconHref) with 14 unit tests. - useDocumentChrome.ts: thin React hook that mutates document.title and a single <link rel="icon"> on each render. - Dashboard / RunDetail / Search call the hook with the right data; Dashboard ticks 'now' every 30s so the failure window expires without an SSE event. - index.html ships the neutral favicon up front so the very first paint already has it; runtime swaps to the fail variant when needed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
BEN-50:
src/web/index.htmlhardcoded<title>Symphony</title>and shipped no favicon, so users keeping Symphony open alongside tracker / docs / logs had no at-a-glance signal that a run went red, and multiple run-detail tabs were indistinguishable.TL;DR
Each top-level route now sets its own tab title via a tiny
useDocumentChromehook, and ships a monotone SVG favicon that flips red on a recent failure.Summary
src/web/documentTitle.ts— pure helpers (dashboardTitle,runDetailTitle,dashboardFaviconColor,runFaviconColor,findMostRecentFailure,buildFaviconHref). 14 unit tests indocumentTitle.test.ts.src/web/useDocumentChrome.ts— thin React hook that writesdocument.titleand patches a single<link rel="icon">; lazily creates the link tag if the page didn't ship one.Dashboard.tsx— derives title fromruns+ a 30 snowtick.Symphony→● N running · Symphony→✖ <issue> <status> · Symphonyfor failures within the 5 min window.RunDetail.tsx—<issue> · <status> · Symphony; favicon flips red while the run isfailed/rate_limited.Search.tsx—<query> · search · Symphony(or justsearch · Symphony) so the route doesn't inherit a stale dashboard title.src/web/index.html— ships the neutral SVG favicon up front so the first paint is already correct; runtime updates the same<link>for state changes.docs/FRONTEND.md— documents the per-route title pattern + 5 min failure-escalation window.Demo
n/a — automated cron run; no browser MCP in this environment. Manual smoke-test path:
pnpm dev WORKFLOW.md --mock, open the dashboard with a live mock run (● 1 running · Symphony), trigger thecrashscenario and confirm the tab title escalates to✖ <issue> failed · Symphonyand the favicon flips rose; open two run-detail tabs and confirm each tab title differs.Alternatives
runsintoApp.tsxand set the title from there — rejected: requires re-plumbing every Dashboard data path through a shared store; the per-view hook keeps each route owning its own state.requestAnimationFrameto update title — rejected: BEN-50 acceptance explicitly calls out that backgrounded tabs must still update, andrAFis paused when the tab is hidden.setIntervalkeeps the failure window honest.public/— rejected: a 64×64 SVG data URL is two lines of code, recolorable at runtime, and avoids a binary asset in the repo.BEN-9's server-side hook.Test Plan
pnpm all— typecheck + fmt:check + lint + test + eval (134 unit + 5 eval, all green)pnpm build:web— bundle builds (176 ms, 228.86 kB)documentTitle.test.tscovers running-count titles, recent-failure escalation, stale-failure expiration, missing/futurefinishedAt, per-route favicon color, SVG data URL encoding, andfindMostRecentFailureordering.Generated by Claude Code