Skip to content

/favicon.ico answered 404, the one path every crawler tries - #2787

Merged
Flotapponnier merged 1 commit into
devfrom
fix/favicon-ico
Oct 2, 2026
Merged

Flotapponnier merged 1 commit into
devfrom
fix/favicon-ico

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Scope, honestly

The noindex on /icon was the cause of Google's globe and is fixed in #2771. This is not expected to be what flips the listing — Google documents the rel="icon" link as sufficient, and we have it. But /favicon.ico returned 404, and that is the single most-requested URL on any website. A file there is strictly better than a 404.

What ships

A real multi-size ICO: 16, 32, 48 and 64 px, each a PNG payload, on the same #f8f3eb background as icon.tsx, with 10 % padding so the mark is not flush to the edge at 16 px.

Verified structurally before building: header type=1, four entries, each payload a valid PNG whose dimensions match its declared size.

Two things that cost an attempt each

Next's ICO decoder rejects non-RGBA payloads. flatten() produces RGB, so the first build died on Format error decoding Ico: The PNG is not in RGBA format!. ensureAlpha() after flatten() is required. The generator now asserts four channels per size rather than trusting it.

The file is binary and nobody would remember how it was made, so scripts/build-favicon.mjs regenerates it from public/logo.png and documents both constraints.

What this does not change

The existing <link rel="icon" href="/icon?…"> is untouched. Google wants a stable favicon URL, and that one was already reset once this morning when icon.tsx was edited for the noindex fix. It is not being churned again.

Next now emits both links; /favicon.ico answers 200 image/x-icon with exactly the generated bytes (confirmed from the build output's route meta).

444 tests, 235 specs, tsc clean.

The noindex on /icon was the cause of Google's globe and is fixed
(#2771). This is the gap that survived it: /favicon.ico, the
conventional location every crawler and tool probes directly, returned
404. The rel="icon" link is what Google documents as sufficient, so this
is unlikely to be what finally flips the listing, but a 404 on that path
is strictly worse than a file, and it is the single most-requested URL on
any site.

A real multi-size ICO: 16, 32, 48 and 64 px, each a PNG payload, on the
same #f8f3eb background as icon.tsx with 10 % padding so the mark is not
flush to the edge at 16 px.

Two things cost an attempt each and are written into the generator so
they cost nobody else one:

Next's ICO decoder rejects non-RGBA payloads. flatten() produces RGB, so
the first build died on "Format error decoding Ico: The PNG is not in
RGBA format!". ensureAlpha() after flatten() is required, and the script
asserts four channels per size rather than trusting it.

The file is binary and nobody would remember how it was made, so
scripts/build-favicon.mjs regenerates it from public/logo.png and
explains both constraints.

What this does NOT change: the existing <link rel="icon" href="/icon">
stays exactly as it is. Google wants a stable favicon URL and that one
has already been reset once this morning when icon.tsx was edited; it is
not being touched again.
@Flotapponnier
Flotapponnier merged commit b491e9c into dev Oct 2, 2026
2 checks passed
@Flotapponnier
Flotapponnier deleted the fix/favicon-ico branch October 2, 2026 14:42
Flotapponnier added a commit that referenced this pull request Oct 2, 2026
…2788)

The noindex on /icon was the cause of Google's globe and is fixed
(#2771). This is the gap that survived it: /favicon.ico, the
conventional location every crawler and tool probes directly, returned
404. The rel="icon" link is what Google documents as sufficient, so this
is unlikely to be what finally flips the listing, but a 404 on that path
is strictly worse than a file, and it is the single most-requested URL on
any site.

A real multi-size ICO: 16, 32, 48 and 64 px, each a PNG payload, on the
same #f8f3eb background as icon.tsx with 10 % padding so the mark is not
flush to the edge at 16 px.

Two things cost an attempt each and are written into the generator so
they cost nobody else one:

Next's ICO decoder rejects non-RGBA payloads. flatten() produces RGB, so
the first build died on "Format error decoding Ico: The PNG is not in
RGBA format!". ensureAlpha() after flatten() is required, and the script
asserts four channels per size rather than trusting it.

The file is binary and nobody would remember how it was made, so
scripts/build-favicon.mjs regenerates it from public/logo.png and
explains both constraints.

What this does NOT change: the existing <link rel="icon" href="/icon">
stays exactly as it is. Google wants a stable favicon URL and that one
has already been reset once this morning when icon.tsx was edited; it is
not being touched again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant