Skip to content

fix(server): find project icons inside monorepo workspace packages - #5347

Open
mackinleysmith wants to merge 1 commit into
pingdotgg:mainfrom
mackinleysmith:fix/monorepo-favicon-resolution
Open

fix(server): find project icons inside monorepo workspace packages#5347
mackinleysmith wants to merge 1 commit into
pingdotgg:mainfrom
mackinleysmith:fix/monorepo-favicon-resolution

Conversation

@mackinleysmith

@mackinleysmith mackinleysmith commented Aug 4, 2026

Copy link
Copy Markdown

Problem

Project favicons are resolved by checking a fixed list of paths relative to the project root (favicon.ico, public/favicon.*, app/favicon.ico, src/app/icon.*, …). A monorepo root almost never has any of those — the icon lives inside a workspace package. A Turborepo whose web app sits at apps/frontend shows the generic fallback icon even though apps/frontend/app/favicon.ico exists.

Setting iconPath in t3.json works around it, but it shouldn't be needed for the standard layout.

Fix

When the root scan comes up empty, ProjectFaviconResolver re-checks the same well-known icon locations and <link rel="icon"> source files inside each apps/* and packages/* directory.

Most of the diff is moving the existing root scan into a findIconWithin(projectCwd, packageDir) helper that takes a package directory prefix; the new logic is one directory listing and the loop that calls it.

  • The root is checked first and t3.json iconPath still wins over everything, so single-package projects are unchanged.
  • apps/* is scanned before packages/*, children sorted, so the result is deterministic.
  • A missing apps/ or packages/ directory is skipped. Other filesystem failures surface as ProjectFaviconResolutionError (list-packages), matching how candidate stats are already handled rather than silently reporting "no icon".

This deliberately keys off the apps//packages/ convention rather than parsing pnpm-workspace.yaml or package.json workspace globs. That covers the layout Turborepo scaffolds and nearly everyone uses, without a glob engine in the resolver. A project with a custom layout still has t3.json iconPath.

No UI change beyond the icon itself now resolving, so there's nothing meaningful to screenshot.

Testing

vp test run src/project/ProjectFaviconResolver.test.ts src/assets/AssetAccess.test.ts — 25 passed. Five new cases cover a package favicon file, package-level <link rel="icon"> resolution, root precedence, apps-before-packages ordering, and a propagated listing failure.

Also ran the resolver against a real Turborepo: it now returns apps/frontend/app/favicon.ico instead of null, and this repo still resolves via its own t3.json iconPath.

Model: Claude Opus 5. Harness: T3 Code.

Note

Fix project icon resolution to search inside monorepo workspace packages

  • ProjectFaviconResolver.resolvePath now searches apps/* and packages/* workspace directories for icons when no icon is found at the repo root.
  • Adds findIconWithin to scope icon discovery (favicon candidates and <link rel="icon"> hrefs in source files) to a single directory, and findPackageDirectories to enumerate workspace package dirs.
  • Root-level icons take precedence over workspace package icons; among packages, apps/ is checked before packages/, with subdirectories sorted alphabetically.
  • Non-NotFound filesystem errors during package directory listing are surfaced as ProjectFaviconResolutionError with the new list-packages operation.

Macroscope summarized a6229a9.

@coderabbitai

coderabbitai Bot commented Aug 4, 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: c3abce29-54ab-42a6-a14d-b195c7ca1fdc

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:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 4, 2026
Comment thread apps/server/src/project/ProjectFaviconResolver.ts Outdated

@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.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f794a2d. Configure here.

for (const directory of packages) {
if (excluded.has(directory)) {
continue;
}

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.

Negated globs block pnpm re-inclusions

Medium Severity

In findWorkspacePackages, negated workspace globs add paths to excluded, and the final pass drops any package in that set. pnpm allows a later positive glob to re-include a package after a broad negation (for example !packages/* then packages/web). Those re-included packages stay in excluded, so they are never scanned for icons and favicon resolution can miss the only valid icon.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f794a2d. Configure here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed by removal in a6229a9 — the analysis was correct.

pnpm re-inclusion after a broad negation (!packages/* then packages/web) was genuinely mishandled: excluded was a one-way set with no re-inclusion path.

Rather than fix the ordering, the PR no longer parses workspace globs at all. It scans the apps/* and packages/* convention directly, so negation semantics are out of scope. Projects with a custom layout can still point at an icon with iconPath in t3.json.

@macroscopeapp

macroscopeapp Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds new monorepo favicon discovery capability, searching workspace packages when icons aren't found at the root. While well-tested and relatively low-risk, this introduces new runtime behavior beyond a simple bug fix. The open review comment references code not present in this PR.

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

@mackinleysmith
mackinleysmith force-pushed the fix/monorepo-favicon-resolution branch from f794a2d to 83d35d9 Compare August 4, 2026 17:41
Comment thread apps/server/src/project/ProjectFaviconResolver.ts
Monorepo roots almost never carry a favicon of their own, so projects like
a Turborepo with its app at apps/frontend fell back to the generic project
icon even though apps/frontend/app/favicon.ico was right there.

When the root scan comes up empty, the resolver now re-checks the same
well-known icon locations inside each apps/* and packages/* directory. The
root is still checked first, so nothing changes for single-package projects.

Model: Claude Opus 5. Harness: T3 Code.
@mackinleysmith
mackinleysmith force-pushed the fix/monorepo-favicon-resolution branch from 83d35d9 to a6229a9 Compare August 4, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant