Skip to content

🐛 Rules pages have no Open Graph image - shared links show no preview #2698

Description

@isaaclombardssw

Originally requested by @isaaclombardssw via YakShaver.ai 🦬
cc: @isaaclombardssw, @Marxoz, @PothieuG, @Freego1783

  🟥  Watch the video (1 min 16 sec)

  Url from screen share: https://www.opengraph.xyz/url?https%3A%2F%2Fwww.ssw.com.au%2Frules%2Freply-done

Consolidates #1379, #2691 and #2697 — all three describe the same gap. See History at the bottom.

Pain

Sharing any SSW Rules link (Teams, Slack, LinkedIn, X, Facebook) shows no preview image. The Next.js site emits zero Open Graph and Twitter Card meta tags — not even a generic default.

curl -sL https://www.ssw.com.au/rules/reply-done | grep -i 'og:\|twitter:'
# (no output)

Screenshot
❌ Figure: Bad example — no og:image, so the link falls back to a plain text card

For comparison, www.ssw.com.au sets a default on every page:

<meta property="og:image" content="https://assets.tina.io/8a7b77f2-cde8-44e7-a592-ebeb7e9dc437/ssw-default-og.jpg"/>

✅ Figure: Good example — the main SSW site has a default OG image

Cause

This is a regression from the Gatsby → Next.js migration. The old src/components/head/head.js (deleted in 3c0fd0b "removing gatsby files") set the full set — og:title, og:description, og:type, og:site_name, og:url, og:image, twitter:card=summary_large_image, twitter:site, twitter:creator, fb:app_id — defaulting the image to /rules/assets/Open-Graph-images-Website-Rules.jpg. That asset now 404s too.

Nothing replaced it:

  • app/layout.tsx — no openGraph, no twitter, no metadataBase
  • generateMetadata() in app/[filename]/page.tsx — only title, description and canonical

Suggested Solution

Two phases. Phase 1 is shippable on its own and fixes the reported pain.

Phase 1 — Default OG image (small)

Use Next's Metadata API rather than hand-rolled tags:

  • Set metadataBase + default openGraph / twitter in app/layout.tsx so every route inherits them (rules, categories, latest-rules, search, user, archived…)
  • Add a default OG image (1200×630) to public/ — or point at the existing SSW default
  • In each generateMetadata(), override openGraph.title / description / url with the page's own values

Phase 2 — Dynamic per-rule OG images (carried from #1379)

@adamcogan's original ask: a per-rule image rather than one generic one.

Image
✅ Figure: Good example — specific thumbnail, as on https://github.com/ApacheTech/BlazOrchard

  • Should include the image of the first author (People data)
  • Should include some specific text from that rule (the SEO description is a good basis)
  • @bradystroud: use Vercel's OG image generation rather than building our own — the site is already on Next
  • Needs PO approval before starting

Tasks

Phase 1

  • Get a default SSW Rules OG image (1200×630)
  • Add metadataBase and default openGraph + twitter to app/layout.tsx
  • Override per-page openGraph in the generateMetadata() functions (rules + categories first)
  • Verify with an OG debugger and a real paste into Teams

Phase 2

  • Get PO approval
  • Generate per-rule OG images via @vercel/og, using first author + SEO description

Acceptance Criteria

  1. SSW Rules pages include valid Open Graph metadata for title, description and image
  2. A valid OG image is displayed when Rules links are shared on social platforms
  3. Metadata validates correctly in common social sharing preview tools
  4. (Phase 2) The OG image is generated per-rule and populated from People data

Out of scope — please don't chase these

"Malformed SEO title" is a false positive. The original report flagged quote characters in the title. The raw HTML is correct:

<title>Dones - Do you reply &#x27;Done&#x27; and delete the original email? | SSW.Rules</title>

&#x27; is a properly escaped apostrophe. React escapes it, and any conformant HTML parser decodes it back to '. opengraph.xyz simply doesn't decode entities in its preview pane — that's a display bug on their end, not ours. Adding an explicit og:title won't change the escaping either, since Next escapes attribute content the same way. No title sanitisation is needed.

Title length — separate nit worth its own PBI: the reply-done title is 80 characters, over Google's ~60 char truncation point. Not an OG problem.

History

Issue Filed Covered
#1379 Jun 2024 Dynamic per-rule OG images → now Phase 2
#2691 Jul 2026 Missing default OG image + root cause → now Phase 1 + Cause
#2697 Aug 2026 Missing OG metadata, video repro, ACs → now Pain + AC

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions