Dev.to WebDev 🛠 Dev 👁 0 📖 4 min read

A static site SEO checklist I ran on my own site (and what it found)

I moved a 21-page static site from a subdirectory to a domain root last week, and it broke more things than I expected. Here is the checklist I ended up running, in the order that found actual problems. 1. Does

I moved a 21-page static site from a subdirectory to a domain root last week, and it broke more things than I expected. Here is the checklist I ended up running, in the order that found actual problems.

1. Does the crawler see the same page a human does?

Fetch your page with a crawler user agent and compare the rendered text to what you see in a browser:

const UA = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
const r = await fetch(url, { headers: { "User-Agent": UA } });
const html = await r.text();
const text = html.replace(/<script[\s\S]*?<\/script>/g, "")
                 .replace(/<[^>]*>/g, " ")
                 .replace(/\s+/g, " ").trim();
console.log(r.status, text.length, text.slice(0, 80));

If the crawler text is much shorter than what you see, something is client-rendered and you have a problem.

Also check x-robots-tag. A header-level noindex will silently kill a page even when the HTML has nothing wrong with it.

2. Does every page render without JavaScript?

Disable JS and reload. For a content site, everything that matters — headings, paragraphs, tables — should still be there.

I write calculators as progressive enhancement for this reason. The page contains a real table of numbers; the JS only adds the interactive layer on top. The food storage lookup is a good example: without JS it is a readable 24-row table, with JS it filters as you type.

3. Is the sitemap actually valid, or does it just look valid?

Three things that caught me out:

  • A BOM at the start of the file. Check the first bytes — they should be 3c 3f 78 (<?x), not ef bb bf.
  • The wrong content type. It should be application/xml, not text/plain.
  • The wrong URL. If your property is a subdirectory and you submit sitemap.xml, make sure you know what it resolves to. Fetch the resolved URL yourself rather than assuming.
const buf = Buffer.from(await (await fetch(url)).arrayBuffer());
console.log(buf.slice(0, 3).toString("hex"));  // 3c3f78 = good

4. If you move URLs, do the old ones redirect?

A meta refresh plus a canonical is the only option on a static host with no server config:

<link rel="canonical" href="https://example.com/new-path">
<meta http-equiv="refresh" content="0; url=https://example.com/new-path">
<meta name="robots" content="noindex, follow">
<script>location.replace("https://example.com/new-path");</script>

The noindex, follow combination is the part people miss. You want the old URL dropped from the index but its link equity passed on, and noindex without follow throws that away.

5. Is there a hub page linking to everything?

This was my biggest structural mistake. I had 21 pages, all reachable from a nav bar, but no single page that linked to all of them with context. Google had indexed exactly one page — the homepage — and had not followed through to the rest.

A hub with a one-line description per link fixed the structure:

<li>
  <a href="/companion-planting-chart.html"><strong>Companion Planting Chart</strong></a><br>
  <span class="d">A practical table of what to plant together, and the pairings that are folklore.</span>
</li>

You can see the result on the hub page — 46 guides, each with a description rather than a bare link.

6. Is anything actually answering the query in the first sentence?

This is content advice, but it is measurable. Open your page and read only the first sentence after the H1.

If it says "Herbal remedies have been used for centuries..." you have written an introduction, not an answer. Compare:

Most sore throats are viral and settle in 3–7 days. These remedies reduce the pain while that happens.

That is the sore throat page. The answer is in the first line; everything after it is detail.

7. Are the tables usable on a phone?

Reference tables are the most common thing to break on mobile. A table that is 700px wide on a 390px screen forces horizontal scrolling for the whole page unless you wrap it:

<div class="table-scroll"><table>...</table></div>
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

Cheap, and it stops the layout breaking on the device where most of your traffic will arrive.

What I would do in a different order

If I did it again: build the hub page first, then write content. I wrote 21 pages and only later created the page that ties them together, which meant the crawl path did not exist for weeks.

The other thing I would not skip is the crawler-UA check. It takes two minutes and it is the only way to know for certain that what you published is what a crawler receives.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.