fix(frontend): repair the site icon in link previews - #177
Merged
Conversation
Both icon links pointed at static/favicon.png, which is 32x32. That file is right for a browser tab, but `apple-touch-icon` is what iMessage, Safari, Slack and most other link-unfurl clients read for the small site icon on a preview card, and Apple asks for at least 180x180 there. At 32x32 those clients either upscale it to a blur or drop it outright, which is what "the favicon is not showing up properly in social previews" was. Adds a 180x180 apple-touch-icon.png rendered from the vector mark in static/logos/sdsc.svg (square viewBox centred on the mark's bounding box, so the glyph keeps its aspect ratio and gains a small inset that iOS's rounded-corner mask will not crowd), and points the link at it with an explicit `sizes`. Transparent background, matching favicon.png. The 32x32 `rel="icon"` tag is unchanged.
Shared links rendered a broken-image glyph where the site icon belongs in Slack's preview card. Slack's unfurler — like several other crawlers and some browsers — requests /favicon.ico at the site root by hard-coded convention and never reads <link rel="icon"> at all, and static/ had no .ico, so that request 404'd. This is separate from the apple-touch-icon sizing in the previous commit: Slack does not consume apple-touch-icon. Not an auth-guard problem, despite /favicon.ico being absent from PUBLIC_ROUTE_PATTERNS: static assets are served ahead of hooks.server.ts, which favicon.png and og-default.jpg already demonstrate by loading on unauthenticated pages. It was a plain missing file. Adds a multi-resolution favicon.ico (16, 32 and 48 px sub-images, 32bpp with alpha) rendered from the same vector mark and the same square crop as apple-touch-icon.png, so every icon surface shows identical framing. Also declares it in app.html for completeness, without a type or sizes so the existing, more specific 32x32 PNG still wins in browsers that support it.
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.
Summary
Two separate faults behind one report — "the favicon is not showing up properly in social previews". Both are in the frontend's icon set; neither is an auth or routing problem.
1.
apple-touch-iconwas a 32×32 image (commit 1)src/app.htmlpointed both icon links at the same file,static/favicon.png, which is 32×32:32×32 is correct for a browser tab, but
apple-touch-iconis what iMessage, Safari and iOS home screens read, and Apple's guidance is at least 180×180. At 32×32 those clients either upscale it to a blur or ignore it.Fix: a real 180×180
static/apple-touch-icon.png, with an explicitsizes="180x180". The 32×32rel="icon"tag is left alone.2. There was no
favicon.icoat all (commit 2)The reported symptom in Slack was a broken-image glyph where the site icon belongs. Slack does not consume
apple-touch-icon, so commit 1 does not address it. Slack's unfurler — like several other crawlers and some browsers — requests/favicon.icoat the site root by hard-coded convention and never reads<link rel="icon">at all.static/had no.ico, so that request 404'd.Worth ruling out explicitly: this is not the auth guard, even though
/favicon.icois absent fromPUBLIC_ROUTE_PATTERNS. Static assets are served ahead ofhooks.server.ts—favicon.pngandog-default.jpgalready demonstrate this by loading on unauthenticated pages. It was a plain missing file.Fix: a multi-resolution
static/favicon.ico(16, 32 and 48 px sub-images), declared inapp.htmlwithout atypeorsizesso the more specific 32×32 PNG still wins in browsers that support it.The asset source
Both new files are rendered from the vector mark already in the repo (
static/logos/sdsc.svg) using the same squareviewBox, centred on the mark's measured bounding box — so every icon surface shows identical framing. Aspect ratio preserved (no stretching), with a ~5% inset per side so iOS's rounded-corner mask does not crowd the lobes. Transparent background, matchingfavicon.png. Both stored via git-lfs, like the repo's other binaries.Deliberately out of scope: no
manifest.json/ PWA icon set, no change toog-default.jpg,static/social/*orSeo.svelte(the large preview image is a separate concern), no change to the Keycloak theme'sfavicon.ico.Test plan
favicon.png's IHDR reports 32×32 and both links resolved to it;static/contained no.ico(the repo's only one is the Keycloak theme's).apple-touch-icon.pngverified by decoding: 180×180, colour type 6 (RGBA), glyph bbox(9,12)–(170,167)→ symmetric insets, aspect 1.0385 vs the source's 1.0467 (antialias rounding, i.e. not stretched), corners fully transparent.favicon.icoverified by parsing the container by hand, not justidentify: valid header (type=1,count=3), three frames whose directory entries agree with the actual pixel dimensions, all 32bpp BMP sub-images (not PNG-in-ICO, which some older consumers cannot read),alpha=Blendand pixel (0,0)srgba(0,0,0,0)on every frame.prettier --checkpasses onapp.htmlin the style the tree actually uses, so the diff is only the intended lines.git lfs fsckalone only checks the local store; a pointer whose object never uploaded breaks every fresh checkout.)Note for reviewers:
nix run ./tools/nix#treefmt -- components/frontend/src --cireformats 133 of 135 files in that tree to 4-space, because the treefmt wrapper honours.editorconfig(indent_size = 4) while the tracked sources are prettier-with---no-editorconfig(2-space). That is pre-existing and repo-wide — this PR deliberately matches the tracked style rather than touching it.