Skip to content

Add a share-preview image (og:image) served at /og.png on the API host - #9

Merged
dmccoystephenson merged 1 commit into
mainfrom
og-image
Oct 6, 2026
Merged

dmccoystephenson merged 1 commit into
mainfrom
og-image

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

The landing page at play.danielstephenson.dev got share-preview text tags in #8, but no image, because the repository held none. This adds one.

  • src/arcade/og.png: a 1200×630 card showing the page's name ("Play"), the existing DESCRIPTION and the domain. It uses the landing page's dark-scheme tokens (#121418 background, #7d98ff accent). It is about 15 KB. No artwork is invented.
  • landing.py: OG_IMAGE_PATH, OG_IMAGE_WIDTH/HEIGHT, OG_IMAGE_ALT, and ogImage(), which reads the bytes once. The page now carries og:image and twitter:image at https://<domain>/og.png, plus og:image:type/width/height/alt and twitter:image:alt. twitter:card is now summary_large_image.
  • server.py: GET/HEAD /og.png serves the PNG as image/png (Cache-Control: public, max-age=86400) on the API host only, next to /robots.txt. A game's host never answers it, so a static game's own /og.png is not shadowed.
  • The page itself never loads the image, so the CSP (img-src data:) is unchanged.
  • Dockerfile already copies src/, so the PNG ships in the image.
  • Tests: the share-tag test now checks the image tags and the domain-following test checks og:image. New tests check the PNG's IHDR size against the constants (and that it is under 150 KB), that the API host serves the bytes for GET and HEAD, and that on game hosts /og.png is the game's own file or a 404.
  • CHANGELOG [Unreleased] and the README endpoint table updated.

The card's text names play.danielstephenson.dev, the production domain. The tag URLs follow the configured domain.

Test plan

  • python -m pytest: 145 passed
  • PYTHONPATH=src python -m arcade check-registry examples/games.yaml

drafted by Claude on behalf of Daniel Stephenson

🤖 Generated with Claude Code

https://claude.ai/code/session_01BZQMN1M5hQKfUpPwDkMjqd

src/arcade/og.png is a 1200x630 card (the page's name, DESCRIPTION and
the play domain, in its dark colours). The landing page now carries
og:image and twitter:image at https://<domain>/og.png with type, width,
height and alt, and a summary_large_image Twitter card. GET /og.png is
answered on the API host only, like /robots.txt, so a game's own /og.png
is never shadowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZQMN1M5hQKfUpPwDkMjqd
@dmccoystephenson
dmccoystephenson merged commit 86cbdf4 into main Oct 6, 2026
3 checks passed
@dmccoystephenson
dmccoystephenson deleted the og-image branch October 6, 2026 03:42
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