Skip to content

Add buildMeta utility for consistent page meta tags (SEO fix)#211

Merged
david-crespo merged 4 commits into
mainfrom
claude/strange-jones-0d258c
May 21, 2026
Merged

Add buildMeta utility for consistent page meta tags (SEO fix)#211
david-crespo merged 4 commits into
mainfrom
claude/strange-jones-0d258c

Conversation

@kev507
Copy link
Copy Markdown
Contributor

@kev507 kev507 commented May 9, 2026

Summary

Ports the buildMeta() utility from oxidecomputer/oxide-computer#751 to the RFD site so every HTML route emits a consistent set of OpenGraph, Twitter Card, and canonical tags.

Today, only app/root.tsx (title only) and app/routes/rfd.$slug.tsx (title + canonical) set any metadata — there are no og:*, twitter:*, or description tags anywhere on the site, so links shared on social media or in chat clients show no preview cards and search engines have no description to surface.

What's in here

  • New app/utils/meta.tsbuildMeta({ title, description, image?, path, type? }) returns the full set of title, description, og:, twitter:, and <link rel="canonical"> tags. It reuses the existing SITE_URL and canonicalUrl() from app/utils/canonicalUrl.ts rather than introducing a parallel base-URL constant.
  • Migrated routesroot.tsx, rfd.$slug.tsx switched to buildMeta. Added meta to _index.tsx and login.tsx, removing their separate links() canonical exports since buildMeta now owns the canonical link.
  • Title separator standardized on | to match #751 (e.g., 0001 - <title> | RFD | Oxide).

Adapted vs. #751

  • No default OG image. The marketing site PR defaults to /img/meta/og-oxide.png; rfd-site has no comparable static image yet. image is optional, and og:image / twitter:image are simply omitted when none is supplied. Adding a default image (or hooking up the existing rfd.image.$rfd.$.tsx endpoint as per-RFD social art) is a follow-up.
  • Tighter scope. Resource routes (search.tsx is JSON-only, plus the PDF/raw/fetch/jobs/discussion/auth/sitemap endpoints) are intentionally left alone since they don't render HTML.

Test plan

  • npm run tsc passes
  • npm run lint passes
  • Reviewer: spot-check /, /rfd/0001, /login in dev — verify <title>, <meta name="description">, og:* / twitter:* tags, and <link rel="canonical"> render with the expected values
  • Reviewer: visit /rfd/nonexistent — confirm fallback Page not found | Oxide title still renders

🤖 Generated with Claude Code

Ports the buildMeta() utility from oxidecomputer/oxide-computer#751 to the
RFD site so every HTML route emits a consistent set of OpenGraph, Twitter
Card, and canonical tags.

- New app/utils/meta.ts that reuses SITE_URL/canonicalUrl from
  app/utils/canonicalUrl.ts (no duplicate base-URL constant). The image
  arg is optional; og:image/twitter:image are only emitted when supplied.
- root.tsx and rfd.$slug.tsx switched to buildMeta. Title separator
  standardized on " | " to match #751.
- _index.tsx and login.tsx now use buildMeta and drop their separate
  links() canonical exports — buildMeta owns the canonical link.
- Resource routes (search, sitemap, PDF/raw, auth callbacks, etc.) are
  intentionally left alone since they don't render HTML.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

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

Project Deployment Actions Updated (UTC)
rfd-site Ready Ready Preview May 21, 2026 10:08pm

Request Review

@kev507 kev507 self-assigned this May 9, 2026
@kev507 kev507 requested a review from david-crespo May 9, 2026 00:38
@kev507 kev507 changed the title Add buildMeta utility for consistent page meta tags Add buildMeta utility for consistent page meta tags (SEO fix) May 9, 2026
Prettier prefers the description string on a single line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Make description optional in buildMeta; skip description/og:description/
  twitter:description tags when absent. Drop title-as-description on the
  RFD slug page (it was a low-quality duplicate of the title).
- Add normalizeDescription: strip HTML, collapse whitespace, truncate at
  a word boundary to 160 chars.
- Only emit twitter:card=summary_large_image when an image is actually
  present (was unconditional).
- Return MetaDescriptor[] from react-router instead of
  Array<Record<string, string>>.
- Drop the duplicate meta export from /_index — root.tsx already covers
  the index route.
- Skip the dash in the RFD slug title when title is null.
Comment thread app/routes/_index.tsx
@david-crespo
Copy link
Copy Markdown
Contributor

Looks good, and I see #210 covers the need for a default OG image.

@david-crespo david-crespo merged commit 188496a into main May 21, 2026
4 checks passed
@david-crespo david-crespo deleted the claude/strange-jones-0d258c branch May 21, 2026 22:11
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