<?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: Alex Quill</title>
    <description>The latest articles on DEV Community by Alex Quill (@alexquill).</description>
    <link>https://dev.to/alexquill</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%2F4073893%2Fbdddd52e-b0e9-4c5b-a6d1-ea2ae737a612.png</url>
      <title>DEV Community: Alex Quill</title>
      <link>https://dev.to/alexquill</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexquill"/>
    <language>en</language>
    <item>
      <title>Why your link preview is a blank grey box (and the 6 tags that fix it)</title>
      <dc:creator>Alex Quill</dc:creator>
      <pubDate>Wed, 12 Aug 2026 06:34:47 +0000</pubDate>
      <link>https://dev.to/alexquill/why-your-link-preview-is-a-blank-grey-box-and-the-6-tags-that-fix-it-53mk</link>
      <guid>https://dev.to/alexquill/why-your-link-preview-is-a-blank-grey-box-and-the-6-tags-that-fix-it-53mk</guid>
      <description>&lt;p&gt;You paste your link into Slack, or Twitter, or iMessage, and instead of a nice card with a title and an image you get… a blank grey box. Maybe the raw URL. Maybe your site's name in tiny letters and nothing else.&lt;/p&gt;

&lt;p&gt;This is one of those bugs that never shows up in your test suite, never breaks a page, and quietly costs you clicks on every single share for the entire life of the site. Here's exactly what's happening and how to fix it in about ten minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happens when you paste a link
&lt;/h2&gt;

&lt;p&gt;Every platform that renders a link preview does roughly the same thing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It fetches your URL with its own bot user-agent (&lt;code&gt;Twitterbot&lt;/code&gt;, &lt;code&gt;facebookexternalhit&lt;/code&gt;, &lt;code&gt;Slackbot-LinkExpanding&lt;/code&gt;, &lt;code&gt;Discordbot&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;It reads &lt;strong&gt;only the HTML that comes back in that first response&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It looks for Open Graph &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tags in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If it finds an image URL, it fetches that separately and caches the whole thing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two consequences fall straight out of that list, and they explain the majority of blank previews:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It does not run your JavaScript.&lt;/strong&gt; If your meta tags are injected client-side by React/Vue/Svelte after hydration, the crawler sees an empty &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; and gives you nothing. This is the single most common cause.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It only reads the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/strong&gt; Tags placed in the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;, or after a large inline script that breaks parsing, get ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The four tags that do 95% of the work
&lt;/h2&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, under 60 characters"&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 sentence, 110-140 characters, written for a human."&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://example.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;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://example.com/the-canonical-url"&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;Note &lt;code&gt;property=&lt;/code&gt;, not &lt;code&gt;name=&lt;/code&gt;. Open Graph uses RDFa, so &lt;code&gt;&amp;lt;meta name="og:title"&amp;gt;&lt;/code&gt; is silently ignored by most parsers. This trips up people constantly because it &lt;em&gt;looks&lt;/em&gt; right.&lt;/p&gt;

&lt;p&gt;Add two more and you have full coverage:&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;"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;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:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"website"&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;&lt;code&gt;twitter:card&lt;/code&gt; is the one people forget. Without it, X/Twitter defaults to the small square thumbnail rather than the big banner card — same tags, a fraction of the visual footprint. And yes, &lt;code&gt;twitter:*&lt;/code&gt; uses &lt;code&gt;name=&lt;/code&gt; while &lt;code&gt;og:*&lt;/code&gt; uses &lt;code&gt;property=&lt;/code&gt;. It's inconsistent. Just copy it correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the image right
&lt;/h2&gt;

&lt;p&gt;The image is where most "I added the tags and it still looks bad" cases end up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Absolute URL, always.&lt;/strong&gt; &lt;code&gt;/og.png&lt;/code&gt; will not work. Crawlers do not resolve relative paths reliably. It must start with &lt;code&gt;https://&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1200x630&lt;/strong&gt; is the size to use. That's the 1.91:1 ratio every large-card renderer expects. Anything squarer gets cropped, usually straight through your text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep it under ~1MB.&lt;/strong&gt; Some crawlers have a hard timeout and simply give up on a 4MB hero PNG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No redirects on the image URL.&lt;/strong&gt; Several crawlers won't follow them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It must be publicly reachable.&lt;/strong&gt; If your image sits behind auth, a signed CDN URL that expires, or a &lt;code&gt;staging.&lt;/code&gt; host that requires basic auth, the crawler gets a 401 and shows nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put readable text in the image.&lt;/strong&gt; The card is a billboard, not a decoration. Title plus logo beats an abstract gradient every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The JavaScript problem, concretely
&lt;/h2&gt;

&lt;p&gt;If you're on a client-rendered SPA, &lt;code&gt;react-helmet&lt;/code&gt; and friends update the DOM &lt;em&gt;in the browser&lt;/em&gt;. The crawler never gets there. Your options, roughly in order of how much work they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSR or SSG.&lt;/strong&gt; Next.js, Nuxt, SvelteKit, Astro, Remix — all of them put the tags in the initial HTML. This is the real fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prerendering.&lt;/strong&gt; A build step or middleware that serves static HTML snapshots to bot user-agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge middleware.&lt;/strong&gt; Cloudflare Workers / Netlify Edge injecting the tags into the response before it ships.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quickest way to know which camp you're in — fetch your own page the way a crawler does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'og:'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that prints nothing but the tags are visible in devtools, your tags are client-side only. That's your answer. Devtools shows you the &lt;em&gt;hydrated&lt;/em&gt; DOM; &lt;code&gt;curl&lt;/code&gt; shows you what the crawler actually receives. Always trust &lt;code&gt;curl&lt;/code&gt; here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching: why your fix "didn't work"
&lt;/h2&gt;

&lt;p&gt;You fixed the tags, you re-pasted the link, and it's still the old broken preview. That's caching, not failure. Every platform caches aggressively — often for days.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Facebook / Instagram:&lt;/strong&gt; Sharing Debugger → "Scrape Again".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn:&lt;/strong&gt; Post Inspector.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X/Twitter:&lt;/strong&gt; no longer offers a public flush; changing the URL (add &lt;code&gt;?v=2&lt;/code&gt;) forces a fresh fetch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack / Discord:&lt;/strong&gt; cache per-URL for hours; the &lt;code&gt;?v=2&lt;/code&gt; trick works there too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Test with a brand-new URL you've never shared, and you'll see the true current state.&lt;/p&gt;

&lt;h2&gt;
  
  
  A five-minute audit for a site you already shipped
&lt;/h2&gt;

&lt;p&gt;Run through this list once per site:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;curl -sL yoursite.com | grep -i 'og:\|twitter:'&lt;/code&gt; — do the tags exist in the raw HTML?&lt;/li&gt;
&lt;li&gt;Are they inside &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;og:image&lt;/code&gt; an absolute &lt;code&gt;https://&lt;/code&gt; URL?&lt;/li&gt;
&lt;li&gt;Does that image URL return &lt;strong&gt;200&lt;/strong&gt; on its own, with no redirect? (&lt;code&gt;curl -sI &amp;lt;image-url&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Is it roughly 1200x630?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;twitter:card&lt;/code&gt; set to &lt;code&gt;summary_large_image&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;og:url&lt;/code&gt; the canonical URL, not the staging host? (Genuinely common — a hardcoded &lt;code&gt;staging.&lt;/code&gt; in &lt;code&gt;og:url&lt;/code&gt; sends every click on every share to a dead host.)&lt;/li&gt;
&lt;li&gt;Do your &lt;strong&gt;inner&lt;/strong&gt; pages have their own tags, or does every URL share one generic homepage card?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last one is worth dwelling on. Plenty of sites set OG tags once on the homepage and call it done. Then every blog post, every product page, every deep link shares the identical card, and nobody clicks because the preview tells them nothing about the page they were actually sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it's worth the ten minutes
&lt;/h2&gt;

&lt;p&gt;A link preview is the only advertisement you get that costs nothing and appears every time someone recommends you. It shows up in the DM where a customer forwards you to a colleague, in the Slack channel where someone drops your docs, in the tweet where somebody vouches for you. A grey box in those moments reads as broken or abandoned — and a link that looks broken doesn't get clicked, no matter how good the thing behind it is.&lt;/p&gt;

&lt;p&gt;Ten minutes, six tags, one correctly-sized image. Nothing else on your pre-launch list has that ratio.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I got tired of checking this by hand on every site I ship, so I built a free tool that does it for me: &lt;a href="https://smeltworks.com/launchaudit" rel="noopener noreferrer"&gt;LaunchAudit&lt;/a&gt; fetches your page like a crawler does and grades OG/Twitter cards alongside security headers, mobile viewport, robots/sitemap, structured data and broken links — one 0-100 launch-readiness score, no signup. Paste a URL and you'll know in ten seconds whether your previews are actually there.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdevseojavascriptbeginners</category>
    </item>
    <item>
      <title>The 28-point checklist I run before calling a site launched</title>
      <dc:creator>Alex Quill</dc:creator>
      <pubDate>Wed, 12 Aug 2026 01:46:06 +0000</pubDate>
      <link>https://dev.to/alexquill/the-28-point-checklist-i-run-before-calling-a-site-launched-2k97</link>
      <guid>https://dev.to/alexquill/the-28-point-checklist-i-run-before-calling-a-site-launched-2k97</guid>
      <description>&lt;p&gt;Every time I ship a site I tell myself I'll "do the SEO and security stuff later." Later never comes, and three weeks in I find out the staging &lt;code&gt;noindex&lt;/code&gt; is still there, or the link preview on Twitter is a blank grey box.&lt;/p&gt;

&lt;p&gt;So I wrote the checklist down. This is the 28-point pass I now run on every site before I call it launched, grouped by how badly it bites you if you skip it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security headers (5)
&lt;/h2&gt;

&lt;p&gt;Missing headers are the cheapest win on this whole list — most are one line in your reverse proxy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTTPS everywhere&lt;/strong&gt;, and &lt;code&gt;http://&lt;/code&gt; actually 301s to &lt;code&gt;https://&lt;/code&gt;. Test the bare apex &lt;em&gt;and&lt;/em&gt; &lt;code&gt;www&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HSTS&lt;/strong&gt; — &lt;code&gt;Strict-Transport-Security: max-age=31536000; includeSubDomains&lt;/code&gt;. Without it your first request is still hijackable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content-Security-Policy.&lt;/strong&gt; Even a loose starter policy beats nothing. Start with &lt;code&gt;default-src 'self'&lt;/code&gt; and loosen until things work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X-Frame-Options: DENY&lt;/strong&gt; (or CSP &lt;code&gt;frame-ancestors 'none'&lt;/code&gt;) — stops clickjacking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X-Content-Type-Options: nosniff.&lt;/strong&gt; One line, kills a whole class of MIME-confusion attacks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bonus: strip headers that leak your stack version (&lt;code&gt;Server: nginx/1.18.0&lt;/code&gt;, &lt;code&gt;X-Powered-By: Express&lt;/code&gt;). Free recon for anyone scanning you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crawlability (5)
&lt;/h2&gt;

&lt;p&gt;This is the category that silently costs you the most, because nothing &lt;em&gt;looks&lt;/em&gt; broken.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No stray &lt;code&gt;noindex&lt;/code&gt;.&lt;/strong&gt; The number one launch bug. Check the meta tag &lt;em&gt;and&lt;/em&gt; the &lt;code&gt;X-Robots-Tag&lt;/code&gt; header — staging configs love to set the header version where you won't see it in "view source."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;robots.txt exists&lt;/strong&gt; and doesn't &lt;code&gt;Disallow: /&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sitemap.xml exists&lt;/strong&gt; and is referenced from robots.txt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canonical URL&lt;/strong&gt; on every page, absolute not relative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick one hostname.&lt;/strong&gt; &lt;code&gt;www&lt;/code&gt; and non-&lt;code&gt;www&lt;/code&gt; should not both serve 200 — redirect one to the other or you're splitting your own ranking.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Metadata and previews (6)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;&lt;/strong&gt;, unique per page, roughly 50–60 characters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;meta name="description"&amp;gt;&lt;/code&gt;&lt;/strong&gt;, 140–160 characters. Google rewrites it sometimes, but not having one guarantees a bad snippet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exactly one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;&lt;/strong&gt; per page that actually describes the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Graph tags&lt;/strong&gt; — &lt;code&gt;og:title&lt;/code&gt;, &lt;code&gt;og:description&lt;/code&gt;, &lt;code&gt;og:image&lt;/code&gt;, &lt;code&gt;og:type&lt;/code&gt;. This is what Slack, LinkedIn, iMessage and Facebook render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Twitter card&lt;/strong&gt; — &lt;code&gt;twitter:card&lt;/code&gt; at minimum, otherwise your link is a naked URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A favicon.&lt;/strong&gt; Yes, really. A default globe icon in the tab reads as "unfinished."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Test 14 and 15 by actually pasting the link into a Slack DM to yourself. It takes five seconds and I catch a broken &lt;code&gt;og:image&lt;/code&gt; path about half the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile and performance (7)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;meta name="viewport" content="width=device-width, initial-scale=1"&amp;gt;&lt;/code&gt;.&lt;/strong&gt; Without it phones render at 980px and zoom out. Instant bounce.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No horizontal scroll at 390px.&lt;/strong&gt; Open devtools, set an iPhone width, and swipe. One &lt;code&gt;min-width&lt;/code&gt; on a table does it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tap targets ≥ 44px.&lt;/strong&gt; Fat fingers, small buttons, no conversions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TTFB under ~600ms.&lt;/strong&gt; If it's worse, it's usually a cold container or an N+1 query on the homepage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression on&lt;/strong&gt; — gzip or brotli. Check &lt;code&gt;Content-Encoding&lt;/code&gt; in the response headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Cache-Control&lt;/code&gt; on static assets.&lt;/strong&gt; Long max-age plus a content hash in the filename.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Width and height on &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;.&lt;/strong&gt; Prevents layout shift, which is both a ranking factor and genuinely annoying.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Content integrity (5)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No broken internal links.&lt;/strong&gt; Crawl your own site once. There's always one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;404s return an actual 404 status,&lt;/strong&gt; not a 200 with "not found" text. Soft-404s get your error pages indexed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alt text on meaningful images.&lt;/strong&gt; Accessibility first, SEO second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON-LD structured data&lt;/strong&gt; for your page type (Organization, Product, Article). This is what earns rich results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load the site logged out, in a private window.&lt;/strong&gt; You will be amazed what was only working because of your session cookie.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Running it
&lt;/h2&gt;

&lt;p&gt;Doing all 28 by hand takes me about 40 minutes with devtools, curl and a Slack DM. That was annoying enough often enough that I automated it: &lt;strong&gt;&lt;a href="https://smeltworks.com/launchaudit" rel="noopener noreferrer"&gt;LaunchAudit&lt;/a&gt;&lt;/strong&gt; runs every check on this list against a live URL and gives you a 0–100 score plus a shareable report. It's free, there's no signup, and it takes about ten seconds.&lt;/p&gt;

&lt;p&gt;It makes real HTTP requests against the actual page — no crawl queue, no "we'll email you the results."&lt;/p&gt;

&lt;p&gt;Either way, run the list. The &lt;code&gt;noindex&lt;/code&gt; one alone has cost me more traffic than every other item combined.&lt;/p&gt;

&lt;p&gt;What's on your pre-launch checklist that I've missed here? I'd genuinely like to add to this.&lt;/p&gt;

</description>
      <category>webdevseobeginnerssecurity</category>
    </item>
  </channel>
</rss>
