Skip to content

feat(seo): proper OG/Twitter meta tags + default share card#29

Open
mastermanas805 wants to merge 1 commit into
mainfrom
feat/og-meta-tags-and-social-cards
Open

feat(seo): proper OG/Twitter meta tags + default share card#29
mastermanas805 wants to merge 1 commit into
mainfrom
feat/og-meta-tags-and-social-cards

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Summary

  • Replaces the favicon-as-og:image (180px square) with a real 1200x630 share card at /og-default.png. Dark canvas, mint accent, wordmark + value prop + sample curl. Generated by scripts/generate-og-image.mjs (Playwright screenshot of an in-memory HTML template) and committed to source so CI doesn't need a browser.
  • Extends scripts/prerender.mjs to splice per-route <title>, description, og:*, twitter:*, and canonical tags into every pre-rendered HTML file. Marketing pages use hard-coded copy; blog posts and use-cases pull from frontmatter (title + excerpt / scenario). Blog posts get og:type=article plus article:published_time and article:author.
  • index.html cleaned up: og:url ends in /, adds og:site_name, og:image:width/height/alt, twitter:image:alt.

Why now

The GTM bundle in /tmp/gtm-next-push/ lands on HN / Product Hunt / Twitter. Right now pasting instanode.dev into Slack/Discord/Twitter renders a tiny apple-touch-icon thumbnail with no value-prop. After this PR every share renders the 1200x630 card with the mint wordmark and the "real infrastructure for AI agents" tagline. Per-route variation means each blog post and use-case page gets its own card title + description.

What's in the image

og-default.png

Test plan

  • npm run build succeeds (116 pre-rendered HTML files)
  • npm test — 96 unit tests pass
  • dist/og-default.png exists, 1200x630, 208 KB
  • dist/index.html has og:image pointing at /og-default.png with width/height/alt
  • dist/pricing/index.html has its own og:title and description (not the homepage default)
  • dist/blog/why-anonymous-is-the-trial/index.html has og:type=article, article:published_time, article:author
  • dist/use-cases/24-hour-hackathon-backend/index.html has its scenario as description
  • npm run preview + curl localhost:4173/og-default.png returns 200
  • Post-merge: paste instanode.dev into a Slack / Discord channel to confirm the card renders. Use https://www.opengraph.xyz/url/https%3A%2F%2Finstanode.dev for a multi-platform preview.

🤖 Generated with Claude Code

Pre-launch (HN/PH/Twitter) the site needs a real share card. The base
index.html previously pointed og:image at apple-touch-icon.png (180px
square), so Slack/Discord/Twitter rendered a tiny thumbnail with no
context. Replaces that with a 1200x630 default card and gives every
pre-rendered route its own title + description.

- public/og-default.png: 1200x630 PNG generated from a Playwright
  screenshot of an in-memory HTML template. Dark canvas (#08080a)
  matching --ink, mint accent (#00e48e), wordmark + value prop + a
  sample curl. Committed to source so CI doesn't need a browser;
  re-run scripts/generate-og-image.mjs to regenerate.

- index.html: og:image now points to /og-default.png with explicit
  width, height, and alt. Adds og:site_name and twitter:image:alt.
  twitter:site=@instanode preserved (handle exists).

- scripts/prerender.mjs: per-route OG splicing.
  * Marketing pages (/, /pricing, /for-agents, /status, /docs, /blog,
    /use-cases): hard-coded titles + descriptions.
  * Blog posts: title + excerpt from frontmatter, og:type=article,
    plus article:published_time and article:author from frontmatter.
  * Use cases: title + scenario from frontmatter, og:type=article.
  * Helpers: htmlEscape, clamp(200), firstParagraph fallback.

Verified via `npm run build` + `npm run preview`: /og-default.png
returns 200 (208 kB), /blog/why-anonymous-is-the-trial/ emits its
own og:title and article:published_time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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