Hello DEV! I built a 100% client-side Open Graph & Social Thumbnail Previewer (Zero Login, Next.js)
Hey DEV community! π I'm excited to finally join DEV and share what I've been building, breaking, and shipping lately. Over the past few years working on web apps, technical blogs, and creator tools, I kept running int
Hey DEV community! π
I'm excited to finally join DEV and share what I've been building, breaking, and shipping lately.
Over the past few years working on web apps, technical blogs, and creator tools, I kept running into the same annoying pre-launch ritual:
- You export a
1200Γ630Open Graph image (og:image) or a1280Γ720YouTube / social graphic. - You want to see how it actually renders inside X (
summary_large_image), LinkedIn (1200Γ627), Facebook, Discord's dark#2B2D31embed, WhatsApp, or Instagram's3:4profile grid before deploying to production. - Every existing preview tool either requires your URL to already be live on a public HTTPS domain (like Meta Sharing Debugger or LinkedIn Post Inspector) or forces you to create an account, hit a paywall, and upload your local files to a remote server.
So I decided to build a fast, 100% client-side, zero-login preview studio: SocialThumbs.com.
π οΈ What It Does (And Why Everything Runs in the Browser)
My main engineering rule for the project was simple: zero server uploads, zero accounts, and sub-second feedback.
When you drag and drop a local image file (PNG, JPG, WebP, or AVIF) into any of the 8 platform simulators, the file never leaves your machine. Everything is rendered in memory via the browser's File and URL.createObjectURL() APIs inside pixel-accurate DOM replicas of each platform's feed container:
// Zero-upload local preview lifecycle with automatic memory cleanup
const handleFileSelect = (file: File) => {
if (previewUrl) {
URL.revokeObjectURL(previewUrl);
}
const localBlobUrl = URL.createObjectURL(file);
setPreviewUrl(localBlobUrl);
};
Here are the 8 interactive simulators currently live:
-
Open Graph (
og:image) 5-Platform Previewer + HTML<meta>Generator: Upload a local1200Γ630banner, type yourog:titleandog:description, and preview X (1.91:1with domain pill overlay), LinkedIn (1200Γ627), Facebook (1200Γ630), Discord (#2B2D31dark card with customizabletheme-colorborder), and WhatsAppβplus copy the production HTML<head>snippet in one click. -
YouTube Thumbnail Preview & A/B Tester: Compare Variant A vs. Variant B side-by-side across Desktop Home, Search, and the tiny
168Γ94 pxSuggested Video sidebar, toggle Dark Mode (#0F0F0F), and check the12:45bottom-right timestamp overlay (140Γ60 pxdead zone). -
Instagram
4:5Feed &3:4Profile Grid Simulator: Preview how1080Γ1350(4:5) carousels crop horizontally to1012.5Γ1350(-33.75 pxon left and right) inside Instagram's3:4vertical profile grid without logging into Instagram. -
TikTok, Reels & Shorts
9:16Safe-Zone Checker: Toggle the exact1080Γ1920UI danger zones (top150 pxheader, right120 pxaction icon bar, and bottom320 pxcaption/audio dock). -
X / Twitter, LinkedIn, Facebook & Pinterest: Compare Native
16:9/4:5image posts against1.91:1Link Cards and test LinkedIn's210-character"β¦more"fold cutoff in real time.
π 3 Weird Social Crawler Bugs I Discovered Along the Way
Building the previewers and writing the engineering documentation led me down a deep rabbit hole of how social crawlers (Twitterbot/1.0, LinkedInBot/1.0, facebookexternalhit/1.1, Discordbot/2.0, and WhatsApp/2.x) actually parse pages in production:
1. WhatsApp's Undocumented 300 KB Mobile Image Ceiling
While Facebook (8 MB) and X (5 MB) happily download large PNGs, WhatsApp's mobile link preview fetcher (WhatsApp/2.x) silently aborts downloading your og:image on cellular connections if the payload exceeds ~300 KB (600 KB max on Wi-Fi). If you use @vercel/og (ImageResponse), exporting a progressive JPEG or WebP under 250 KB is the difference between a rich preview and a blank gray box.
2. Why X Crushes 1200Γ630 Images Into a Tiny 120Γ120 Square
Even though Twitterbot falls back to og:title, og:description, and og:image, it defaults the card layout to summary (a tiny 1:1 thumbnail) unless you explicitly include:
<meta name="twitter:card" content="summary_large_image" />
3. Headless Bots Don't Do TLS "AIA Chasing"
Desktop browsers (Chrome, Safari, Firefox) automatically fetch missing intermediate SSL certificates via Authority Information Access (AIA). Social scrapers (LinkedInBot, Twitterbot, Discordbot) do notβif your server only serves cert.pem instead of fullchain.pem, the bot drops the TLS handshake and shows zero link preview even though your site shows a green padlock in Chrome!
If you ever need a quick checklist when debugging a stubborn social card, I documented all the crawler rules and cache-busting tricks in this Broken Link Preview & Open Graph Troubleshooting Guide.
π¬ Let's Connect!
I'm planning to publish more deep-dives here on frontend performance, Next.js static exports, Open Graph automation, and indie tool building.
- Have you ever been bitten by a cached or broken
og:imageright in the middle of a launch? - If you try out SocialThumbs.com, is there another platform embed (like Slack, Telegram, Bluesky, or Mastodon) you'd like me to add next?
Drop a comment below and say hiβI'd love to check out what you're building too! π
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.