Skip to content

Update OG image generation to the new visual style #5652

@MarkusNeusinger

Description

@MarkusNeusinger

The OG image generators in core/images.py (create_branded_og_image, create_og_collage, create_compare_image, _draw_branded_header) still use the old visual identity — flat light background ANYPLOT_BG = "#f8f9fa", plain logo strip, no link to the design language we now use across /, /specs, /palette, /map.

These OG images are what shows up when an anyplot URL is shared on Slack / Twitter / LinkedIn / WhatsApp, so they should match the rest of the brand.

Affected endpoints (in api/routers/og_images.py)

  • GET /og/home.png — currently serves the static api/static/og-image.png
  • GET /og/plots.png — same static fallback
  • GET /og/{spec_id}/{language}/{library}.png — branded single-implementation card via create_branded_og_image
  • GET /og/{spec_id}.png — multi-library collage via create_og_collage
  • (compare/diff variants via create_compare_image)

What "new style" means here

The patterns we've settled on across the React app:

  • Background / ink tokens matching the site theme — the cream #FFFDF6 / dark #0a0a08 surface, var(--ink) / var(--ink-soft) for type
  • Okabe-Ito palette (#009E73, #D55E00, #0072B2, #CC79A7, #E69F00, #56B4E9, #F0E442 + ink) for any colored chips / accents — same CLUSTER_COLORS we use on /map
  • Typography: serif for the lede / titles (Domine), MonoLisa for code-shaped labels (spec-id, library.method()-style hints) — already loaded server-side
  • Layout idioms that the site uses: ❯ section chevron, library.foo() method chips with the colored 8x8 square, dotted-underline links in body copy
  • Spec/lib labels as method-call style chips (e.g. matplotlib.scatter() rather than the current header strip)

Things to decide while implementing

  • Should the static fallback api/static/og-image.png be regenerated from the new template or stay as a hardcoded asset?
  • Cache invalidation: existing OGs are cached by cache_key — bumping a version in the cache key should be enough to force a refresh after deploy.
  • Make sure the compare-image variant (used by /og/{spec_id}/{language}/{library}.png?) reads consistently with the rest.

Done when

  • All five /og/*.png endpoints render in the new visual style on a fresh request
  • core/images.py exposes the same public function signatures (no router changes needed)
  • Manual smoke: paste a few anyplot URLs into a Slack DM / X post, confirm the cards look on-brand
  • Cache key bumped so the deploy cycles old images out

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestinfrastructureWorkflow, backend, or frontend issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions