Skip to content

fix(seo): declare site icons for crawlers and ship favicon.ico - #11838

Merged
MarkusNeusinger merged 2 commits into
mainfrom
feat/site-icons
Sep 19, 2026
Merged

MarkusNeusinger merged 2 commits into
mainfrom
feat/site-icons

Conversation

@MarkusNeusinger

Copy link
Copy Markdown
Owner

Summary

  • Google showed no icon for anyplot.ai. Crawlers are routed to the bot HTML from api/routers/seo.py, whose <head> declared no icon, and Google's /favicon.ico fallback returned 404. The bot template now carries the same three icon links as app/index.html (absolute URLs), and app/public/ ships favicon.ico (16, 32, 48 px), apple-touch-icon.png (180 px) and a square icon-512.png.
  • Organization.logo in app/index.html and seo.py points at icon-512.png instead of the 1200×630 banner.
  • The favicon is drawn from the real MonoLisa outlines. An SVG favicon loads no webfonts, so the <text> mark always rendered in the viewer's system monospace. scripts/generate_favicon.py outlines the ap monogram from MonoLisa Bold into plain paths on an opaque paper ground (the transparent icon with dark ink vanished on dark result pages) and rasterizes the ICO and PNG siblings from that one SVG.

Plan

  • scripts/generate_favicon.py: fontTools outlines at wght=700, resvg for the rasters, Pillow for the ICO. Run with uv run --with resvg-py python scripts/generate_favicon.py; outputs are committed.
  • app/index.html, api/routers/seo.py: icon links and Organization.logo.
  • Docs: new "Site icons" section in docs/reference/seo.md; the favicon row of docs/reference/style-guide.md now describes the ap over square mark that is actually shipped (owner's choice over the a.p reduction).
  • nginx needs no change: the static-asset regex location already covers .ico and .png and wins over the bot proxy.

Test plan

  • uv run ruff check ., ruff format --check ., mypy api core: clean
  • uv run pytest tests/unit tests/integration: 2023 passed, 1 skipped; new test_has_site_icon_links pins the three links in the bot HTML
  • yarn lint, yarn fm:check, yarn type-check, yarn test, yarn build: green; dist/ contains the four icon files and the three links
  • Icon judged by eye at 16, 32, 48 and 180 px and in a mocked Google result row, light and dark
  • After deploy: curl -A Googlebot https://anyplot.ai/ | grep 'rel="icon"' finds the links and https://anyplot.ai/favicon.ico answers 200; then request re-indexing of the home page in Search Console (Google refreshes favicons over days to weeks)

Not driven through /verify-frontend or /verify-api against a running stack; the change is static head markup plus files in app/public/.

Licensing note for /audit-licenses: the new binaries contain only the outlines of two MonoLisa letters, no font data. The MonoLisa licence allows static images but asks for a special licence for "trademark, logo, brand" use, so a favicon is a borderline case the owner is aware of.

Crawlers receive the bot HTML from api/routers/seo.py, whose head had no
icon link, and the /favicon.ico fallback returned 404, so Google showed no
icon for anyplot.ai. The bot template now mirrors the icon links of
app/index.html, and app/public/ ships favicon.ico, apple-touch-icon.png and
a square icon-512.png for Organization.logo.

The favicon itself is now outlined from MonoLisa Bold by
scripts/generate_favicon.py: an SVG favicon loads no webfonts, so the
former <text> mark rendered in the system monospace.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 19, 2026 20:13
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Human confirmation of MonoLisa’s brand-use licensing is required before publishing the derived assets.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Adds crawler-visible site icons and updates structured metadata to use the new square logo.

Changes:

  • Declares favicon and touch-icon links in browser and crawler HTML.
  • Generates favicon assets from outlined branding.
  • Documents and tests the SEO behavior.
File Description
tests/​unit/​api/​test_seo_helpers.py Tests crawler icon links.
scripts/​generate_favicon.py Generates SVG, PNG, and ICO assets.
docs/​reference/​style-guide.md Documents the revised favicon mark.
docs/​reference/​seo.md Documents site-icon behavior and assets.
changelog.d/​site-icons.md Records the SEO and favicon changes.
app/​public/​favicon.svg Replaces font text with outlined paths.
app/​index.html Adds icon links and updates the organization logo.
api/​routers/​seo.py Adds crawler icon links and updates structured data.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/generate_favicon.py
Comment thread api/routers/seo.py
@MarkusNeusinger
MarkusNeusinger merged commit 03bae5e into main Sep 19, 2026
16 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the feat/site-icons branch September 19, 2026 20:21
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