<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bogdan</title>
    <description>The latest articles on DEV Community by Bogdan (@ctrlzed).</description>
    <link>https://dev.to/ctrlzed</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3987782%2F7229d364-334f-44d1-a14a-6d9d73e09305.png</url>
      <title>DEV Community: Bogdan</title>
      <link>https://dev.to/ctrlzed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ctrlzed"/>
    <language>en</language>
    <item>
      <title>Link Preview Not Showing? Fix It on WhatsApp, X &amp; LinkedIn</title>
      <dc:creator>Bogdan</dc:creator>
      <pubDate>Mon, 22 Jun 2026 12:36:35 +0000</pubDate>
      <link>https://dev.to/ctrlzed/link-preview-not-showing-fix-it-on-whatsapp-x-linkedin-1l25</link>
      <guid>https://dev.to/ctrlzed/link-preview-not-showing-fix-it-on-whatsapp-x-linkedin-1l25</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://metablast.dev/blog/link-preview-not-showing" rel="noopener noreferrer"&gt;metablast.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;You paste a link into WhatsApp, X, or LinkedIn and what comes back is a bare URL, an empty card, or an image you're pretty sure you replaced weeks ago. Nine times out of ten it's one of five problems with your meta tags, or the platform is just showing you a cached preview from before you fixed anything. None of these take more than about 10 minutes once you know which one you're dealing with.&lt;/p&gt;

&lt;h2&gt;
  
  
  How platforms build link previews
&lt;/h2&gt;

&lt;p&gt;When you paste a link, the platform's crawler fetches your page and reads a handful of meta tags from the HTML &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Your Page Title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"One or two sentences about the page."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourdomain.com/og.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;og:&lt;/code&gt; tags are the Open Graph standard, used by WhatsApp, LinkedIn, Facebook, Slack, Discord, basically everyone. X reads its own &lt;code&gt;twitter:&lt;/code&gt; tags first and falls back to Open Graph if they're missing.&lt;/p&gt;

&lt;p&gt;The bit that trips most people up: every platform caches the preview the first time it crawls your link, usually for about a week. WhatsApp is the worst offender, sometimes sitting on a cached preview for weeks with no real pattern to it. So if your tags were broken the first time anyone shared the link, fixing them on your end isn't enough. The platform keeps serving the old, broken version until something forces it to re-crawl. That's the whole story behind "I fixed it, but it's still showing the old preview", and how to force that re-crawl on each platform is further down.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 most common causes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Missing og:image, or the wrong size
&lt;/h3&gt;

&lt;p&gt;No &lt;code&gt;og:image&lt;/code&gt; tag means most platforms fall back to a text-only card, or nothing at all. And if the image is too small, the wrong aspect ratio, or too heavy, platforms tend to crop it badly or drop it without telling you why.&lt;/p&gt;

&lt;p&gt;The spec that works everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1200 × 630 pixels (1.91:1 aspect ratio)&lt;/li&gt;
&lt;li&gt;JPG or PNG, not SVG, not GIF (WhatsApp ignores both)&lt;/li&gt;
&lt;li&gt;Under 300 KB if you can manage it. WhatsApp officially allows up to 600 KB but often fails to load heavier images on mobile connections, so smaller is safer.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourdomain.com/og-image.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:width"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"1200"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:height"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"630"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Relative image URL instead of absolute
&lt;/h3&gt;

&lt;p&gt;Crawlers fetch your image from a different server, not from inside your page, so a relative path means nothing to them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Wrong: crawler can't resolve this --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"/images/og.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Right: full absolute URL, with https --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourdomain.com/images/og.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you're in there: both the image URL and the page itself need to be served over HTTPS. WhatsApp refuses plain HTTP outright. The image also has to be publicly reachable, no login wall, no staging basic-auth, no localhost.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The platform is showing you a cached preview
&lt;/h3&gt;

&lt;p&gt;You find the bug, fix the tag, redeploy, share the link again, and the preview hasn't changed at all. This is cache, not your code. Platforms store the preview from their first crawl and reuse it for roughly a week (LinkedIn and X around 7 days; WhatsApp anywhere from days to weeks, with no published rule). The fix isn't on your site, it's telling the platform to re-crawl, covered in the refresh section below.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Your meta tags are rendered by JavaScript
&lt;/h3&gt;

&lt;p&gt;Crawlers read the initial HTML response from your server, and most of them don't run JavaScript. If your site is a client-rendered React/Vue/SPA app that injects meta tags after load, the crawler sees an empty &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; and gives up, no preview at all.&lt;/p&gt;

&lt;p&gt;Quick test: open your page, hit View Source (not DevTools "Inspect"), and search for &lt;code&gt;og:title&lt;/code&gt;. If it's not there, the crawler can't see it either.&lt;/p&gt;

&lt;p&gt;The fix is rendering meta tags on the server: Next.js (the Metadata API or &lt;code&gt;generateMetadata&lt;/code&gt;), Nuxt, SvelteKit, Astro, or a plain server-rendered page all handle this. If switching to SSR isn't an option right now, a prerendering service for crawler user-agents is a workable stopgap.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Redirects or an og:url mismatch
&lt;/h3&gt;

&lt;p&gt;If your URL bounces through several redirects (http → https → www → final page), some crawlers give up partway through, or cache the preview against the wrong URL. Same problem if your &lt;code&gt;og:url&lt;/code&gt; tag points somewhere other than the page itself, the crawler may follow it and scrape that page instead.&lt;/p&gt;

&lt;p&gt;Keep it simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- og:url should match the canonical, final URL of the page --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourdomain.com/blog/my-post"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One redirect (say, http → https) is fine. Chains of three or more, or anything JavaScript-based, is where previews tend to break.&lt;/p&gt;

&lt;h2&gt;
  
  
  Force a refresh, platform by platform
&lt;/h2&gt;

&lt;p&gt;Tags fixed? Now you need to make each platform forget what it saw before.&lt;/p&gt;

&lt;h3&gt;
  
  
  LinkedIn link preview not updating
&lt;/h3&gt;

&lt;p&gt;LinkedIn has the best tool of the bunch: the &lt;a href="https://www.linkedin.com/post-inspector/" rel="noopener noreferrer"&gt;Post Inspector&lt;/a&gt;. Paste your URL, hit Inspect, and LinkedIn re-scrapes the page on the spot, which alone refreshes the cached preview. It also shows you exactly which title, description, and image LinkedIn picked up, so it doubles as a debugger. No login needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  X (Twitter) preview not updating
&lt;/h3&gt;

&lt;p&gt;X's official Card Validator was deprecated back in 2022, and as of 2026 there's still no official replacement, no public tool that forces a refresh. X caches card data for about 7 days.&lt;/p&gt;

&lt;p&gt;The workaround everyone ends up using: share the URL with a new query parameter tacked on, e.g. &lt;code&gt;https://yourdomain.com/page?v=2&lt;/code&gt;. X treats it as a brand-new URL and crawls it fresh. The original URL keeps showing the stale card until its cache expires on its own, and any tweets already posted with the old card keep it forever, only new shares pick up the fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  WhatsApp link preview not showing
&lt;/h3&gt;

&lt;p&gt;WhatsApp doesn't have an official debug or refresh tool at all. Two workarounds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Append a query parameter, share &lt;code&gt;https://yourdomain.com/page?v=2&lt;/code&gt; instead of the bare URL. WhatsApp caches by exact URL, so any new parameter triggers a fresh crawl. This is the more reliable of the two.&lt;/li&gt;
&lt;li&gt;Run the URL through Facebook's Sharing Debugger (below). WhatsApp shares Meta's crawler infrastructure, so a Facebook re-scrape occasionally refreshes WhatsApp's cache too. Not guaranteed, but worth trying first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One more WhatsApp quirk: previews get baked into messages at send time. Old chats keep the old preview no matter what you fix on your end, only newly sent messages pick up the new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Facebook preview not updating
&lt;/h3&gt;

&lt;p&gt;Use the &lt;a href="https://developers.facebook.com/tools/debug/" rel="noopener noreferrer"&gt;Sharing Debugger&lt;/a&gt; (needs a Facebook login). Paste your URL and click Scrape Again, Facebook re-fetches the page and updates its cache immediately. The debugger also lists every tag it read along with any warnings, which is useful even if Facebook isn't your target platform, given the WhatsApp crossover above.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to catch this before you ship
&lt;/h2&gt;

&lt;p&gt;Broken previews are the kind of bug you only notice after you've already shared the link, and by then the broken version is cached for a week. The real fix is checking the preview before the first share, not after. &lt;a href="https://metablast.dev" rel="noopener noreferrer"&gt;MetaBlast&lt;/a&gt; renders your Google, X, and Facebook previews side by side from any URL, so you see what the crawlers see before anyone else does. There's no separate WhatsApp preview, but WhatsApp pulls from the same Open Graph tags as Facebook, so the Facebook card is a good stand-in for what WhatsApp will show too.&lt;/p&gt;

&lt;p&gt;If you're setting up meta tags from scratch, my other post covers the basics: &lt;a href="https://metablast.dev/blog/meta-descriptions-2026" rel="noopener noreferrer"&gt;Meta descriptions in 2026: what actually works&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why does my link show no image on WhatsApp?
&lt;/h3&gt;

&lt;p&gt;Usually one of three things: a missing or relative &lt;code&gt;og:image&lt;/code&gt; tag, an image that's too heavy (stay under 300 KB, JPG or PNG, never SVG or GIF), or a page that isn't served over HTTPS. WhatsApp is stricter than other platforms on all three. Fix the tag, then share the URL with &lt;code&gt;?v=2&lt;/code&gt; appended to get past WhatsApp's cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long does LinkedIn cache link previews?
&lt;/h3&gt;

&lt;p&gt;About 7 days, but you don't have to wait it out, running your URL through the &lt;a href="https://www.linkedin.com/post-inspector/" rel="noopener noreferrer"&gt;Post Inspector&lt;/a&gt; forces an immediate re-scrape and refreshes the cached preview right away.&lt;/p&gt;

&lt;h3&gt;
  
  
  I updated my og:image but the old one still shows. Why?
&lt;/h3&gt;

&lt;p&gt;That's cache, not your fix. Every platform stores the preview from its first crawl and keeps serving it for days, regardless of what's live on your site now. Use LinkedIn's Post Inspector or Facebook's Sharing Debugger to force a re-scrape, or append a query parameter like &lt;code&gt;?v=2&lt;/code&gt; for X and WhatsApp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need twitter:card tags if I already have Open Graph tags?
&lt;/h3&gt;

&lt;p&gt;X falls back to &lt;code&gt;og:&lt;/code&gt; tags, so previews mostly work without it. But add &lt;code&gt;&amp;lt;meta name="twitter:card" content="summary_large_image" /&amp;gt;&lt;/code&gt; anyway, without it, X shows the small thumbnail card instead of the large image one, which gets a lot less attention in the feed.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>programming</category>
      <category>html</category>
    </item>
    <item>
      <title>Meta descriptions in 2026: what actually works</title>
      <dc:creator>Bogdan</dc:creator>
      <pubDate>Tue, 16 Jun 2026 17:53:51 +0000</pubDate>
      <link>https://dev.to/ctrlzed/meta-descriptions-in-2026-what-actually-works-1mid</link>
      <guid>https://dev.to/ctrlzed/meta-descriptions-in-2026-what-actually-works-1mid</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://metablast.dev/blog/meta-descriptions-2026" rel="noopener noreferrer"&gt;metablast.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Open your landing page source and find the &lt;code&gt;&amp;lt;meta name="description"&amp;gt;&lt;/code&gt; tag. Go ahead, I'll wait. If you found a tight, human sentence that tells someone exactly what they get when they click, you're already beating most of the indie SaaS sites I look at. If you found nothing, or the first 155 characters of your cookie banner, or a wall of comma-separated keywords from 2014, this one's for you.&lt;/p&gt;

&lt;p&gt;The meta description is the only piece of marketing copy that runs before anyone visits your site. It's your one free ad on the most valuable real estate on the internet. And almost everyone treats it like an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why meta descriptions matter (more than you think)
&lt;/h2&gt;

&lt;p&gt;Let's kill the biggest myth first. Google does not use your meta description as a ranking signal. They confirmed this back in 2009 and have repeated it many times since. You can write the most beautiful 150 characters of your life and it will not move you up a single position.&lt;/p&gt;

&lt;p&gt;So why bother?&lt;/p&gt;

&lt;p&gt;Because ranking gets you seen. The description gets you clicked. Those are two completely different jobs, and you need both. You can rank #3 and lose to the #5 result if their snippet is sharper than yours. Click-through rate from search is a real lever, and the description is the part of it you actually control.&lt;/p&gt;

&lt;p&gt;Then there's the second job most people forget: social. Your &lt;code&gt;&amp;lt;meta name="description"&amp;gt;&lt;/code&gt; often becomes the fallback text when someone drops your link in Slack, Discord, or a tweet, at least when you haven't set a proper Open Graph description. Pair it with &lt;code&gt;og:description&lt;/code&gt; and you control how your link looks the moment it leaves your site and starts traveling.&lt;/p&gt;

&lt;p&gt;Here's a concrete contrast. Two project management tools, same search results page.&lt;/p&gt;

&lt;p&gt;The first one shipped this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Home | TaskLoop"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google had nothing to work with, so it grabbed the first scrap of text it found on the page. The snippet ended up reading "Skip to content. Login. Sign up. Features Pricing." Nobody clicks that.&lt;/p&gt;

&lt;p&gt;The second one wrote this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Plan sprints, assign tasks, and ship on time. TaskLoop keeps small teams in sync without the enterprise bloat. Free for up to 5 people."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same product category. One snippet looks like a parsing error. The other tells you who it's for, what it does, and that you can start for free. Guess which one earns the click.&lt;/p&gt;

&lt;h2&gt;
  
  
  The technical rules nobody tells you
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Length: aim for 120-155 characters.&lt;/strong&gt; You'll see "160" everywhere. Ignore it. Google measures the snippet in pixels, not characters, and the cutoff is tighter on mobile, where most of your search traffic now lives. 155 characters is the safe ceiling where your full sentence survives on a phone screen. Go past it and your closing thought gets replaced with an ellipsis. The most important words should land in the first 120 characters, because that's what shows no matter what device someone's on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it goes.&lt;/strong&gt; Inside &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, alongside your title and Open Graph tags. Nothing fancy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;TaskLoop, sprint planning for small teams&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Plan sprints, assign tasks, and ship on time. Free for up to 5 people."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"TaskLoop, sprint planning for small teams"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Plan sprints, assign tasks, and ship on time. Free for up to 5 people."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;og:description&lt;/code&gt; repeating the value. You can write a different, more casual one for social if you want, but at minimum don't leave it empty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Characters that quietly break things.&lt;/strong&gt; Your description lives inside an HTML attribute wrapped in double quotes. So a raw double quote inside your copy ends the attribute early and mangles your tag. Use single quotes inside, or escape with &lt;code&gt;&amp;amp;quot;&lt;/code&gt;. Em-dashes and curly quotes are fine in modern UTF-8 pages but will turn into garbage like â€" if your encoding is misconfigured, so confirm you've got &lt;code&gt;&amp;lt;meta charset="utf-8"&amp;gt;&lt;/code&gt; set before you get clever with typography. When in doubt, a plain hyphen never betrays you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Google decides whether to even use what you wrote.&lt;/strong&gt; This is the part that frustrates people. You write a great description, and Google ignores it and generates its own. It does this when it thinks its auto-generated snippet matches the specific search query better than your static text. For a broad query like your brand name, Google usually respects what you wrote. For a long-tail query, it might pull a more relevant sentence straight from your page body. You can't force it. What you can do is make sure both your description and your on-page copy are good, so whichever one Google picks, you win.&lt;/p&gt;

&lt;h2&gt;
  
  
  5 patterns that actually get clicks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Question + immediate answer.&lt;/strong&gt; Use it when your audience is searching with a problem in their head, not a product name. You mirror their question, then resolve it in the same breath. "Tired of flaky CI? PipeGuard re-runs failed jobs automatically and tells you which test is actually broken." It works because you've proven you understand the pain before asking for anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Specific numbers + outcome.&lt;/strong&gt; Numbers stop the eye and signal that you're not bluffing. "Cut your build times by 60%" beats "make your builds faster" every time. Vague claims read like marketing. Specific ones read like results. Just don't invent the number. If it's not true, your bounce rate will tell on you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Benefit + proof point.&lt;/strong&gt; Lead with what they get, then back it with something concrete: a customer count, a logo, a metric. "Write blog posts in your own voice. Inkwell learns your style from 3 samples and 4,000 writers already use it daily." The benefit pulls them in; the proof makes them trust it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Urgency without spam.&lt;/strong&gt; Real urgency comes from a real reason: a free tier expiring, a limited beta, a price increase. "Free during beta" is honest urgency. "ACT NOW!!! LIMITED TIME!!!" is the kind of thing that makes people scroll past on reflex. The line is whether the urgency is true. If it is, say it plainly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Match exact search intent.&lt;/strong&gt; This is the most underrated one. If someone searches "linear alternative for solo devs," the snippet that says exactly "A Linear alternative built for solo developers" will out-click anything cleverer. You're not writing poetry. You're confirming they found the right page. Sometimes the most boring, literal description is the best-performing one.&lt;/p&gt;

&lt;h2&gt;
  
  
  7 mistakes I see on most new SaaS sites
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. No description at all.&lt;/strong&gt; This is the most common and the most expensive. With the tag empty, Google scrapes whatever text it finds first, often your nav or a "Skip to content" link. You hand control of your first impression to a scraper. Always write something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Keyword stuffing.&lt;/strong&gt; "Project management tool, task tracker, team collaboration software, agile sprint planning app, kanban board." This reads like a robot wrote it for another robot, and humans skip it. It also doesn't help ranking, because, say it with me, descriptions aren't a ranking factor. Write for the person, not the index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Too long.&lt;/strong&gt; You wrote a great 200-character description and felt productive. Then it got chopped at "...and our intuitive dashboard helps teams" on mobile, and your call to action lives in the part nobody sees. Front-load the value. Assume the back half gets cut.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Generic corporate speak.&lt;/strong&gt; "Welcome to our innovative platform that empowers teams to unlock their full potential." That sentence describes 10,000 products and zero of them specifically. It says nothing, so it sells nothing. Be concrete or be silent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. No reason to click.&lt;/strong&gt; Some descriptions describe the page accurately and still flatline because they give no hint of what's in it for the reader. You don't need a hard CTA on every page, but the snippet should imply a next step: what they'll get, do, or solve. "See how it works" beats a flat product noun.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Bait and switch.&lt;/strong&gt; The description promises a free template library; the page is a pricing wall. You'll get the click and lose the trust in three seconds, and that bounce is a worse signal than no click at all. Your snippet is a contract. Honor it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. The same description on every page.&lt;/strong&gt; Your homepage, pricing page, and docs all sharing one description is a missed opportunity and, at scale, a quiet penalty. Google flags duplicate descriptions in Search Console for a reason. Each page does a different job. Each description should too.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to test before shipping
&lt;/h2&gt;

&lt;p&gt;You don't need a fancy tool to catch the obvious failures. Google Search Console's URL Inspection shows you how Google currently renders your page, and over time tells you whether it's using your description or substituting its own. That's your single best feedback loop.&lt;/p&gt;

&lt;p&gt;For the snippet itself, the cheap move is to just look at it on a real phone. Desktop gives you generous room; mobile is where descriptions die. Paste your title and description into any SERP preview tool, then sanity-check it at phone width. If the meaning survives the truncation, you're good. If the sentence only makes sense complete, rewrite it so the first half stands alone.&lt;/p&gt;

&lt;p&gt;For pages that drive real traffic, your homepage, your top landing page, it's worth A/B testing the description. Change the snippet, wait for enough impressions in Search Console, and compare CTR. Most pages won't have the volume to make this meaningful, so don't waste your life testing a blog post nobody reads. Reserve it for the two or three URLs that actually matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to write manually vs use AI
&lt;/h2&gt;

&lt;p&gt;Be honest with yourself about where the effort pays off.&lt;/p&gt;

&lt;p&gt;Write manually for the handful of pages that carry your brand: the homepage, your primary product pages, the key landing pages you're running ads to. These deserve a human who knows the product and the audience. They're a small set. You can afford the twenty minutes each.&lt;/p&gt;

&lt;p&gt;Lean on AI when the volume gets real. A content site with 80 blog posts, a docs site, a programmatic SEO play with hundreds of pages: nobody is hand-writing 200 descriptions, and pretending you will just means you'll ship 200 empty tags. This is exactly where generation earns its keep: consistent, intent-matched, length-correct descriptions at a scale that manual work can't touch.&lt;/p&gt;

&lt;p&gt;The realistic answer for most indie hackers is a hybrid. Hand-craft your five most important pages. Generate the long tail. Spot-check the generated ones and fix the few that miss. That's not a compromise, it's just allocating your attention where it changes the outcome.&lt;/p&gt;

&lt;p&gt;That's the workflow I built MetaBlast around, but you can pull this off with any decent generator. The point is that hand-writing 200 descriptions isn't a virtue, it's just lost time.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Length:&lt;/strong&gt; 120-155 characters. Front-load the value in the first 120.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent:&lt;/strong&gt; Match what the person actually searched. Literal beats clever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One job per page:&lt;/strong&gt; Unique description per URL, never a global copy-paste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile first:&lt;/strong&gt; Preview at phone width. Assume the back half gets cut.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't lie:&lt;/strong&gt; The snippet is a contract with the click. Honor it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the ones that matter:&lt;/strong&gt; Search Console for everything, A/B only for high-traffic pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iterate:&lt;/strong&gt; CTR is feedback. Watch it, rewrite, repeat.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;I built &lt;a href="https://metablast.dev" rel="noopener noreferrer"&gt;MetaBlast&lt;/a&gt; because I got tired of doing this by hand across every project I launched. It reads your page, figures out what it's actually about, and writes a length-correct, intent-matched description, plus the Open Graph and title tags while it's at it. If you're staring at a sitemap full of empty description tags right now, that's the use case.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>programming</category>
      <category>marketing</category>
    </item>
  </channel>
</rss>
