Skip to content

feat(desktop): add favicons to the Browser panel - #5644

Open
chrisdeeming wants to merge 2 commits into
pingdotgg:mainfrom
chrisdeeming:browser-favicons
Open

feat(desktop): add favicons to the Browser panel#5644
chrisdeeming wants to merge 2 commits into
pingdotgg:mainfrom
chrisdeeming:browser-favicons

Conversation

@chrisdeeming

@chrisdeeming chrisdeeming commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

What Changed

Capture favicons from desktop preview sessions and show them in recently used sites and browser tabs, with the existing fallback when no captured icon is available.

Why

External favicon lookups cannot resolve local or private sites. Capturing the favicon from the browser keeps those icons accurate and available across sessions.

UI Changes

Recently used sites and browser tabs now show captured site favicons. Screenshots show the state before #5270 (history tracking) was merged, the state before the favicons are displayed, and the state after this PR is merged.

Before #5270 Before #5644 After #5644
Before #5270 Before #5644 After #5644

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Prepared with GPT-5.6 Codex in T3 Code.


Note

Medium Risk
Touches desktop preview navigation lifecycle and cross-process favicon fetch/rasterization; regressions could affect tab loading or icon display, but changes are largely isolated to preview/browser UI with broad test coverage.

Overview
Adds end-to-end favicon capture for the in-app browser: the desktop PreviewManager listens for page-favicon-updated, fetches/decodes/rasterizes candidates (with size, byte, and abort/race guards), and exposes favicon / faviconOrigin on preview tab state. Navigation, refresh, webview swap, and tab-close paths were tightened so loads are not blocked on pending navigations, superseded ERR_ABORTED navigations do not fail the UI, and stale captures cannot overwrite newer pages.

On the web side, a persisted browserFaviconStore keys icons by scoped project + canonical origin (collapsing localhost vs environment host), queues captures until the thread project/connection is ready, and wires PreviewFaviconIcon / tab chrome to prefer captured data URLs over Google’s s2 service—with expanded isPrivateNetworkHost so private/local origins never hit the public favicon provider.

Reviewed by Cursor Bugbot for commit c7d9f6e. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add favicons to the Browser panel in the desktop preview

  • Captures favicons from page loads in the desktop PreviewManager, normalizing them to bounded PNG data URLs (≤8192 bytes, ≤32px) with support for SVG/ICO rasterization via an isolated world and deduplication by content hash.
  • Adds a persistent Zustand store (browserFaviconStore.ts) keyed by project and canonical host (with loopback/localhost collapsed to local), backed by localStorage with an in-memory fallback and a 40-entry eviction policy.
  • Displays favicons in the Browser panel tab strip (RightPanelTabs) and empty-state cards (PreviewRecentUrlCard, PreviewLocalServerCard), preferring the captured data URL and falling back to the Google S2 favicon service for public hosts only.
  • Skips the Google S2 fallback for private network hosts (loopback, RFC-1918, .local, .localhost, ts.net, bare hostnames, IPv4-mapped IPv6 private ranges).
  • Favicons are invalidated on cross-document navigations, load failures, window opens, and webContents detach; publication is deferred until a successful navigation confirms the origin matches.
  • Risk: favicon capture runs JavaScript in an isolated world per webContents and is serialized with a semaphore; timeouts guard each rasterization step, but failed captures are silently dropped rather than surfaced as errors.

Macroscope summarized c7d9f6e.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d27bf89-7086-476e-8793-1a44825343a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
@chrisdeeming
chrisdeeming marked this pull request as ready for review August 7, 2026 19:15
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/web/src/components/RightPanelTabs.tsx Outdated
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/web/src/components/preview/usePreviewBridge.ts
@macroscopeapp

macroscopeapp Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a substantial new feature (favicon display in Browser tabs) with ~1400 lines of new production code including complex async favicon capture/rasterization logic, a new persisted Zustand store, and UI components. New features introducing user-facing behavior warrant human review even when well-tested.

You can customize Macroscope's approvability policy. Learn more.

Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts Outdated
@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/web/src/components/preview/usePreviewBridge.ts Outdated
Comment thread apps/web/src/components/preview/usePreviewBridge.ts Outdated
Comment thread apps/web/src/components/preview/usePreviewBridge.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/web/src/browserFaviconStore.ts Outdated
Comment thread apps/desktop/src/preview/Manager.ts
@chrisdeeming
chrisdeeming force-pushed the browser-favicons branch 2 times, most recently from 7a84eeb to b845a05 Compare August 8, 2026 02:58
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/web/src/browserFaviconLogic.ts
Comment thread apps/web/src/lib/favicon.ts
@chrisdeeming
chrisdeeming force-pushed the browser-favicons branch 2 times, most recently from 38d9dc9 to 7dbf34e Compare August 8, 2026 04:27
Comment thread apps/desktop/src/preview/Manager.ts
Comment thread apps/web/src/browserFaviconStore.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 819c314. Configure here.

Comment thread apps/desktop/src/preview/Manager.ts
The guest page's favicon is only observable in the main process, so the
desktop side captures it from page-favicon-updated, fetches it through
the preview session and publishes it on the tab state. The renderer
persists it keyed by project and origin.

Icons are stored as data urls so they still render when the dev server
is stopped, which is the common case on the splash. Bytes are stored
verbatim where they fit, since ICO and SVG cannot be decoded by
nativeImage. Empty and oversized payloads are rejected, and the captured
origin travels with the icon so a sticky field cannot attribute one
site's favicon to another.
Recently used and Local servers rows now show the captured favicon,
falling back to the generic icon when there is none.

The tab strip previously resolved favicons through Google's s2 service
by domain, which cannot reach a developer's machine, so every local site
showed a globe. It now prefers the locally captured icon and falls back
to the previous behaviour, which also means no request is made to Google
for sites already captured.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants