@newthird/og-preview
v1.2.0
Published
Local link-preview tester: how a URL's Open Graph tags look on X, LinkedIn, Facebook, Slack, Discord, iMessage, WhatsApp, Telegram, Bluesky and Mastodon, with a JSON report for scripts and an MCP tool for AI agents.
Maintainers
Readme
og-preview
A local link-preview tester. Point it at any URL, a dev server on localhost included, and it shows how the link would look on X, LinkedIn, Facebook, Slack, Discord, Bluesky, Mastodon, iMessage, WhatsApp, Telegram and Instagram (plus a Google-style result), in light and dark, with a checks panel (tags, sizes, limits) and crop guides on the image. Threads, Reddit, Pinterest, Teams, Notion, Google Chat, Element, Signal, Messenger, Snapchat, LINE and KakaoTalk are there too, off by default; the "Show" row turns them on, by platform or by group. Each card opens in context, with what the platform reads, where it cuts, how long it caches, and how to refresh. No dependencies; Node 18 or newer.
A hosted copy runs at https://ogpreview.newthird.co for public URLs.
Use it yourself
npx @newthird/og-preview localhost:8080/plumbopens http://localhost:4747/?url=… in the browser. Options: --port=N,
--no-open. A missing scheme is filled in: localhost:3000, 3000,
myapp.local and private IPs get http, anything else gets https.
Use it from scripts
npx @newthird/og-preview --report localhost:8080/plumbprints a JSON report and exits 1 if any check fails (warnings pass).
Add --open to also show the visual preview. The same report is served
at /api/report?url=… while the page is running. Fields: summary
(pass, warn, fail), checks (group, level, text,
detail, meter), image (size, ratio, bytes, format, status),
the resolved title, description, siteName, twitterCard,
canonical, every og:/twitter: tag, and previewUrl.
Host it
Run it with --public (or OG_PREVIEW_PUBLIC=1) on any host that keeps a
Node process alive. In that mode it refuses private and loopback addresses,
the page tells visitors that localhost only works when they run it on their
own machine, and the "Set up" button hands out the install prompt with the
right origin filled in.
On Netlify (how ogpreview.newthird.co runs): netlify.toml builds the
static page with node build.mjs and serves the API from one function,
netlify/functions/api.mjs, which shares lib.mjs with server.mjs.
Set SITE_ORIGIN to the public URL so the page's own canonical and
og:image tags come out right.
Use it from an AI agent
The "Set up" button in the page header shows these commands with the
right origin filled in, and a running instance serves its own skill file
at /skill/SKILL.md.
Claude Code skill. Copy skills/og-preview into ~/.claude/skills/
(for every project) or .claude/skills/ (for one project). Claude Code
then runs the report whenever it touches meta tags or an og:image, fixes
what fails, and opens the preview for you when the change is visual.
mkdir -p ~/.claude/skills/og-preview && curl -fsSL https://ogpreview.newthird.co/skill/SKILL.md -o ~/.claude/skills/og-preview/SKILL.mdMCP server, for Claude Code, Cursor, VS Code, Claude Desktop, Windsurf,
Zed, Codex and anything else that speaks MCP over stdio. One tool,
og_preview_report, takes { url, open?, localImage? } and returns the
report; open: true also opens the browser preview.
claude mcp add og-preview -- npx -y @newthird/og-preview --mcpCursor, Claude Desktop and Windsurf take the same server in their JSON config:
{ "mcpServers": { "og-preview": { "command": "npx", "args": ["-y", "@newthird/og-preview", "--mcp"] } } }VS Code uses a servers key in .vscode/mcp.json, Zed context_servers
in settings.json, Codex a [mcp_servers.og-preview] table in
~/.codex/config.toml. The "Set up" button on the page has every variant
with a copy button, plus one-click links for Cursor and VS Code.
Notes
- A missing scheme is filled in, on the page and on the command line:
localhost:3000,3000,myapp.localand private IPs get http, anything else gets https. - A dev server's
og:imageusually points at the production domain. The "Local image" switch in the strip under the URL bar (shown only when it applies, on by default for localhost pages) swaps the host so the local copy is shown; the checks still judge the URL as written. - The sidebar shows the image with crop guides, then the checks, then the tags (collapsed). Click the image for a large view.
- Icons are Iconamoon (Regular style, MIT), inlined as an SVG sprite at
the top of
index.html. - The "Show" row hides platforms, one at a time or by group (Social, Messaging, Work, Search), and reorders them by dragging a chip or a card header. Both stick in localStorage; "Reset" puts everything back.
- Images go through a small proxy (
/api/img) so referer checks and other local ports don't get in the way. - The mocks are faithful to each platform's layout and crop, not pixel copies, and platforms change: treat them as a quick read, and check the real thing before a launch (LinkedIn Post Inspector, Facebook's Sharing Debugger).
- The checks are the documented limits: 1200×630, 1.91:1 (X crops to
2:1), under 5 MB for X and 8 MB for Facebook, titles under ~70
characters, descriptions under ~200, absolute https
og:image,og:image:width/heightset,twitter:cardset tosummary_large_image.
