Skip to content

feat(seo): give the home, playstyle and reveals pages their own link preview images (#1135) - #1137

Merged
Doberjohn merged 2 commits into
masterfrom
claude/project-thread-s0ce6e
Nov 5, 2026
Merged

Doberjohn merged 2 commits into
masterfrom
claude/project-thread-s0ce6e

Conversation

@Doberjohn

@Doberjohn Doberjohn commented Nov 5, 2026 •

Copy link
Copy Markdown
Owner

Closes #1135

What changes

A link to the home page, a playstyle page or, in reveal season, /reveals now previews with an image of its own, and every other page previews with the new home image instead of the old wordmark banner (/og-image.png). Each image is 1200x630:

  • Home: the six featured cards in an arc, each glowing in its ink, under "Find the cards that work together".
  • Playstyle (25): the gallery tile's fan (the hero, then the next four cards with art by name, Locations left out), "Lorcana playstyle · N cards", the name, the tagline and three key cards, in the playstyle's accent.
  • Reveals (in season only): the set's name, "N of 204 cards revealed" with a progress bar, and the five newest revealed cards.

Details:

  • scripts/generate-og-images.mjs draws the page images on a fifth page beside the four card pages, with scripts/og/page-template.html. It writes dist/og/page/{home|reveals|playstyle-<id>}.{sha256 prefix}.jpg and a second record, apps/web/node_modules/.cache/og-pages.json. Locally: 26 page images (27 in a faked season), 2.0 MiB, with no change to the run's 30 s.
  • scripts/lib/pageOgImage.mjs holds the pure parts: what each image shows, its alt text, which image a route names (pageOgKey, ogImageForRoute), the season test, and the parsers for PLAYSTYLE_UI and PER_INK. Its tests are in scripts/lib/__tests__/pageOgImage.test.mjs, and they parse the app's real playstyleUi.ts and revealSet.ts.
  • scripts/prerender.mjs writes each page's own image, or the home image, into every page it captures. isRevealSeasonActive now calls the helper's revealSeasonSet, so the crawl and the generator always agree on the season.
  • Check 13 in scripts/check-rendered-html.mjs fails the deploy when /, a playstyle page or /reveals (when the crawl wrote it) doesn't name its own /og/page/ image, or another prerendered route doesn't name the home image. It also fails when twitter:image differs from og:image, or when the build lacks the file. Check 12's image test is now shared with it.
  • withCardOgImage is renamed withOgImage, since every page uses it now.
  • deploy.yml's dry-run paths add the new helper. build:vercel's fallback message names both checks.
  • Docs: CLAUDE.md's Link previews note and IMAGES.md.

Where it differs from the issue

  • The playstyle image's "Key cards" names the fan's first three distinct names, so a playstyle whose fan holds two Aladdins shows two names, not "Aladdin · Aladdin".
  • homeOgData takes the featured ids and the card list. The issue had it read featuredCards.json's cards directly, but that file's cards carry no image hash.

Verification

  • pnpm test:scripts: 1195 passed (10 new helper tests, 5 for check 13)
  • lint:root, knip, and the CodeScene gate (Code Health 10 on every changed script)
  • Three generator runs and a rebuild give the same 26 file names
  • Every page JPEG is 1200x630, at most 111 KB
  • A sample crawl over a faked reveal season: / and /playstyles/lore-denial name their own /og/page/ image in both tags with alt text, /reveals names its own, and /browse, /playstyles, /ink/amber and /vote name the home image
  • Planted fault: deleting playstyle-lore-denial.*.jpg makes check 13 fail, naming that page
  • A sheet of all 26 images, and /reveals with five reveals, two reveals, and Locations among the newest, looked right to me. It goes to the owner before merge.
  • No app JavaScript or card data changes

After deploy: curl the og:image of / and /playstyles/bounce, check one image's headers, and Scrape Again on / in Facebook's Sharing Debugger.


Generated by Claude Code


Summary by cubic

Gives the home, playstyle, and /reveals pages their own link preview images, so links to them no longer show the site-wide wordmark banner. Every other page the crawl writes now previews with the new home image.

  • The deploy build draws each image (home, all 25 playstyles, and /reveals in reveal season only) from a new template and pure helper; featured and playstyle cards from the next reveal set are drawn and counted too, preview-only cards read as the app's loader merges them.
  • Check 13 fails the deploy when a page names anything but its expected image, when twitter:image differs from og:image, when the file is missing from the build, or when a route the crawl should have written has no page at all.
  • Playstyle accents and reveal-set totals live in app TypeScript, so the helper parses playstyleUi.ts and revealSet.ts as text; their tests fail when either file stops parsing.
  • The crawl, image generator, and check 13 share the reveal-season test, so /reveals is drawn and expected exactly when it is captured.
  • withCardOgImage is renamed withOgImage, since every page now uses it.

Written for commit 45c7f49. Summary will update on new commits.

View guided diff

…preview images (#1135)

The deploy build now draws three more kinds of preview image beside the
card images: the home page's (the six featured cards under "Find the
cards that work together"), each of the 25 playstyle pages' (the gallery
tile's fan, its name, tagline and card count) and, in reveal season
only, /reveals' (the set, how many of its cards are out, and the five
newest). Every other page the crawl writes, a card without art included,
names the home image instead of the old wordmark banner.

Check 13 fails the deploy when a page names anything but its image.
PLAYSTYLE_UI and PER_INK live in the app's TypeScript, so the helper
reads them as text, and its tests fail when either stops parsing.

Closes #1135

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjrxDUg8t6RHUrGiKw1neQ
@vercel

vercel Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
inkweave Ready Ready Preview Nov 5, 2026 3:55pm UTC

Request Review

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

🎨 Design-surface change detected

This PR touches files mirrored by the Inkweave design system project.
After merge, refresh the mirror so it doesn't drift out of sync.

What changed:

  • 📖 CLAUDE.md — design language sections may have shifted

To refresh: open the design system Claude project and prompt:

Refresh against the latest of Doberjohn/inkweave@master. Focus on the files this PR touched: CLAUDE.md

This is a reminder, not a blocker. Configured in .github/workflows/design-system-drift.yml.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
User-facing JS 457.02 KB (0%)
Supabase SDK (lazy) 26.98 KB (0%)
PostHog SDK (lazy) 100.91 KB (0%)
Entry chunk 28.06 KB (0%)
Collection and reveals JS 74.44 KB (0%)
Binders JS (lazy) 24.68 KB (0%)
Release notes page 9.33 KB (0%)
Card data JSON 110.37 KB (0%)
Collection index JSON 63.83 KB (0%)
Collection set chunks 158.18 KB (0%)

@cubic-dev-ai cubic-dev-ai Bot 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.

cubic analysis

All reported issues were addressed across 14 files

Linked issue analysis

Linked issue: Doberjohn/inkweave#1135: Give the reveals, playstyle and home pages their own link preview images

Status Acceptance criteria Notes
✅ Give home and playstyle pages their own images The generator creates per-route page images, and the crawl writes them with alt text into the captured pages.
✅ Give reveals its own in-season image The shared season test gates generation and capture; the image includes the set, revealed count, total, and newest cards.
✅ Use the home image for other prerendered pages ogImageForRoute falls back to the home image, and check 13 verifies each captured route’s expected image.
✅ Use byte-hashed image URLs served as immutable Page images use ogFileName to hash JPEG bytes; the existing immutable rule for /og/ remains in place.
✅ Fail deploy checks for missing page images Check 13 verifies expected filenames and build files, and its tests remove an image to prove the failure.
✅ Test parsing of playstyle and reveal configuration Tests parse both real TypeScript files and assert catalog playstyles have entries and the reveal total is positive.
⚠️ Keep staging builds from drawing images The generator comments say SKIP_PRERENDER skips image drawing, but the diff shows no staging guard or test for it.
✅ Leave app JavaScript and card data unchanged The PR reports no app JavaScript or card data changes, and the supplied diff changes scripts and documentation only.

Reply with feedback, questions, or to request a fix.

View guided diff | Fix all with cubic | Re-trigger cubic

Comment thread scripts/check-rendered-html.mjs Resolved
Comment thread apps/web/src/features/cards/IMAGES.md Resolved
Comment thread scripts/generate-og-images.mjs Resolved
Comment thread scripts/generate-og-images.mjs Resolved
Comment thread scripts/lib/pageOgImage.mjs Resolved
Comment thread scripts/lib/pageOgImage.mjs Resolved
Comment thread scripts/generate-og-images.mjs Resolved
Comment thread scripts/lib/pageOgImage.mjs Resolved
Comment thread scripts/check-rendered-html.mjs Resolved
Comment thread scripts/lib/pageOgImage.mjs Resolved
…check 13 (#1135)

The page images now read preview-only cards as the app's loader does, so a
featured or playstyle card from the next set is drawn and counted. Check 13
fails a page it expects that the crawl never wrote, and expects /reveals only
in season. The reveal season test moves into pageOgImage.mjs as a boolean,
one ogImageUrl builder serves both image folders, and capturedPageFile is
shared by every check that opens a captured page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjrxDUg8t6RHUrGiKw1neQ

@codescene-delta-analysis codescene-delta-analysis Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gates Passed
6 Quality Gates Passed

See analysis details in CodeScene

Quality Gate Profile: Pay Down Tech Debt
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

@Doberjohn
Doberjohn merged commit f03789d into master Nov 5, 2026
19 checks passed
@Doberjohn
Doberjohn deleted the claude/project-thread-s0ce6e branch November 5, 2026 16:58

This branch was successfully deployed

1 active deployment
Preview — 45c7f49a Deployed Nov 5, 2026 by vercel[bot]
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.

Give the reveals, playstyle and home pages their own link preview images

1 participant