Skip to content

feat: Give the app an icon and a link preview - #17

Merged
shmuto merged 2 commits into
mainfrom
claude/loving-hamilton-2r5kj3
Sep 11, 2026
Merged

shmuto merged 2 commits into
mainfrom
claude/loving-hamilton-2r5kj3

Conversation

@shmuto

@shmuto shmuto commented Sep 11, 2026

Copy link
Copy Markdown
Owner

The favicon pointed at /vite.svg, which is not in the repository — every tab showed the browser's blank-page glyph. There were no Open Graph tags either, so pasting the link into Slack produced a bare URL and nothing else.

The icon

An OID tree: a root node, a trunk and two children, white on the blue the header already uses. Drawn once as public/favicon.svg and rendered to PNG for the browsers and platforms that will not take one — 96px as a favicon fallback, 180px full-bleed for the iOS home screen, where the system applies its own rounding and a rounded source would be rounded twice.

It was checked at the size it is actually used: at 16px the branches still read as branches rather than smearing into a blob.

The link preview

public/og-image.png is a 1200×630 render of scripts/og-image.html — the name, what the thing does, and a slice of the merged tree with two SMIv1 traps under an enterprise node, so the picture says what the product is without being read. The source is committed next to the output, along with the one command that regenerates it, because an image nobody can rebuild is an image nobody will change. That source pulls in favicon.svg rather than carrying its own copy of the glyph, so the two cannot drift apart.

The og: URLs are absolute and name the deployed site: a relative one unfurls with no image at all. A fork that publishes elsewhere has to edit them, which the README now says, along with everything else about these files.

Also here

  • The document language was ja while every string in the interface is English.
  • There was no meta description for a search engine or an unfurl to quote.
  • twitter:image had no alt text while og:image did.

Verification

Against the built artefacts, not the sources:

  • The three PNGs really are the sizes the tags declare — 96×96, 180×180, 1200×630 — read back out of the file headers.
  • All four files are served at the base path with the right content types, in the dev server and in the production build alike; no request fails.
  • The tags land in the DOM with their absolute URLs intact, and Vite rewrites the icon hrefs to /mib-browser/… as it should.
  • The command the README gives for regenerating the preview reproduces the committed PNG byte for byte.
  • Nothing in the repository still refers to vite.svg.
  • The interface contains no Japanese, so lang="en" is the truthful value.

Tests, typecheck and build are unaffected and green (176 pass).

One thing this cannot do from a file

Pasting the repository URL rather than the site URL unfurls from GitHub's own social preview, which is a repository setting, not a file in the tree. Uploading the same og-image.png under Settings → General → Social preview makes the two match. Worth knowing too: Slack caches an unfurl for a while, so a changed image shows up sooner if the message is posted with ?1 on the end of the URL.

🤖 Generated with Claude Code

https://claude.ai/code/session_018qyesKa9si8szMUe7w8HNK


Generated by Claude Code

The favicon pointed at /vite.svg, which is not in the repository - every tab
showed the browser's blank-page glyph. There were no Open Graph tags either,
so pasting the link into Slack produced a bare URL.

The icon is an OID tree: a root node, a trunk and two children, white on the
blue the header already uses. It is drawn once as an SVG and rendered to PNG
for the browsers and platforms that will not take one - 96px as a favicon
fallback, 180px full-bleed for the iOS home screen, where the system applies
its own rounding.

The preview image is a 1200x630 render of scripts/og-image.html: the name, what
the thing does, and a slice of the merged tree with two SMIv1 traps under an
enterprise node, so the picture says what the product is without being read.
Its source is committed next to it, along with the one command that regenerates
it, because an image nobody can rebuild is an image nobody will change.

The og: URLs are absolute and name the deployed site: a relative one unfurls
with no image at all. A fork that publishes elsewhere has to edit them, which
the README now says, along with everything else about these files.

Also here: the document language was ja while every string in the interface is
English, and there was no meta description for a search engine or an unfurl to
quote.

Verified against the built output rather than the sources - all four files are
served at the base path with the right content types, and the tags land in the
DOM with the absolute URLs intact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qyesKa9si8szMUe7w8HNK
…witter

The preview image carried its own copy of the glyph, so the next edit to
favicon.svg would have left the two different without anything failing. It
pulls in the file itself now, which the render resolves relative to the source
and so still needs no network.

twitter:image had no alt text while og:image did.

Checked the rest of the change against the artefacts rather than the sources:
the three PNGs really are the sizes the tags declare (96, 180, 1200x630), all
four files are served at the base path in dev and in the build, nothing still
refers to the vite.svg that was never there, the document language matches the
interface - which has no Japanese in it - and the command the README gives for
regenerating the preview reproduces the committed PNG byte for byte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qyesKa9si8szMUe7w8HNK
@shmuto
shmuto merged commit 5c5865b into main Sep 11, 2026
4 checks passed
@shmuto
shmuto deleted the claude/loving-hamilton-2r5kj3 branch September 11, 2026 12:04
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.

2 participants