---
title: "SEO rules (seo/*)"
description: "All 60 seo rules void reports, each with severity, why it matters and how to fix it."
canonical: https://void-design.vercel.app/rules/seo
lastModified: 2026-09-16
---

# SEO rules

What search engines need from the raw response: status codes, titles and descriptions in <head>, self-referencing canonicals, one h1, crawlable links, Open Graph, icons, robots.txt and a sitemap with real dates. Run `void seo` or `void audit`.

| Rule | Severity | Problem |
| --- | --- | --- |
| [`seo/http-status`](https://void-design.vercel.app/rules/seo/http-status.md) | error | Page does not return HTTP 200 |
| [`seo/redirect-chain`](https://void-design.vercel.app/rules/seo/redirect-chain.md) | warn | URL reaches its content through more than one redirect |
| [`seo/redirect-temporary`](https://void-design.vercel.app/rules/seo/redirect-temporary.md) | warn | Temporary redirect (302/303/307) used |
| [`seo/client-redirect`](https://void-design.vercel.app/rules/seo/client-redirect.md) | warn | Redirect done with meta refresh or JavaScript |
| [`seo/noindex`](https://void-design.vercel.app/rules/seo/noindex.md) | error | Indexable page carries noindex |
| [`seo/robots-snippet-restricted`](https://void-design.vercel.app/rules/seo/robots-snippet-restricted.md) | info | nosnippet or a very low max-snippet limits previews |
| [`seo/soft-404`](https://void-design.vercel.app/rules/seo/soft-404.md) | error | Missing page returns HTTP 200 (soft 404) |
| [`seo/html-too-large`](https://void-design.vercel.app/rules/seo/html-too-large.md) | error | Uncompressed HTML is over Googlebot's 2 MB fetch limit |
| [`seo/rsc-payload-ratio`](https://void-design.vercel.app/rules/seo/rsc-payload-ratio.md) | info | Inline RSC flight payload dominates the HTML |
| [`seo/not-https`](https://void-design.vercel.app/rules/seo/not-https.md) | warn | Page served over plain HTTP |
| [`seo/origin-redirects`](https://void-design.vercel.app/rules/seo/origin-redirects.md) | error | http:// or www/apex variant doesn't redirect to the canonical origin in one hop |
| [`seo/html-lang`](https://void-design.vercel.app/rules/seo/html-lang.md) | error | <html lang> missing or not a valid BCP 47 tag |
| [`seo/viewport`](https://void-design.vercel.app/rules/seo/viewport.md) | error | Viewport meta missing, not device-width, or blocks zoom |
| [`seo/charset`](https://void-design.vercel.app/rules/seo/charset.md) | warn | Character encoding not declared early |
| [`seo/title-missing`](https://void-design.vercel.app/rules/seo/title-missing.md) | error | No single non-empty <title> in <head> |
| [`seo/title-length`](https://void-design.vercel.app/rules/seo/title-length.md) | warn | Title length outside 10–60 characters, or keyword-stuffed |
| [`seo/meta-description-missing`](https://void-design.vercel.app/rules/seo/meta-description-missing.md) | error | No meta description in <head> |
| [`seo/meta-description-length`](https://void-design.vercel.app/rules/seo/meta-description-length.md) | warn | Meta description length outside 50–160 characters |
| [`seo/metadata-in-body`](https://void-design.vercel.app/rules/seo/metadata-in-body.md) | error | Crawler receives <title>/canonical/description inside <body> (Next.js streaming metadata) |
| [`seo/canonical-missing`](https://void-design.vercel.app/rules/seo/canonical-missing.md) | error | No single rel=canonical in <head> |
| [`seo/canonical-invalid`](https://void-design.vercel.app/rules/seo/canonical-invalid.md) | error | Canonical URL is relative or contains a fragment |
| [`seo/canonical-broken`](https://void-design.vercel.app/rules/seo/canonical-broken.md) | error | Canonical points to a URL that returns 4xx/5xx |
| [`seo/canonical-conflict`](https://void-design.vercel.app/rules/seo/canonical-conflict.md) | error | Canonical target redirects, is noindex, or canonicalises elsewhere |
| [`seo/canonical-not-self`](https://void-design.vercel.app/rules/seo/canonical-not-self.md) | info | Canonical points to a different URL |
| [`seo/head-js-mutation`](https://void-design.vercel.app/rules/seo/head-js-mutation.md) | error | JavaScript changes canonical, robots, title or description after load |
| [`seo/h1-count`](https://void-design.vercel.app/rules/seo/h1-count.md) | error | Page doesn't have exactly one visible <h1> in the server HTML |
| [`seo/h1-title-mismatch`](https://void-design.vercel.app/rules/seo/h1-title-mismatch.md) | info | <h1> and <title> share little wording |
| [`seo/heading-skip`](https://void-design.vercel.app/rules/seo/heading-skip.md) | warn | Heading levels skip (h2 → h4) or headings are empty |
| [`seo/img-alt-missing`](https://void-design.vercel.app/rules/seo/img-alt-missing.md) | error | <img> without an alt attribute |
| [`seo/img-alt-quality`](https://void-design.vercel.app/rules/seo/img-alt-quality.md) | warn | Alt text is a filename, a generic word, or overly long |
| [`seo/links-not-crawlable`](https://void-design.vercel.app/rules/seo/links-not-crawlable.md) | error | Navigation uses elements crawlers can't follow |
| [`seo/link-text`](https://void-design.vercel.app/rules/seo/link-text.md) | warn | Links with generic or empty text |
| [`seo/broken-links`](https://void-design.vercel.app/rules/seo/broken-links.md) | warn | Internal links return 4xx/5xx (or go through redirects) |
| [`seo/trailing-slash`](https://void-design.vercel.app/rules/seo/trailing-slash.md) | error | Both trailing-slash and non-slash URLs serve 200 |
| [`seo/hreflang-invalid`](https://void-design.vercel.app/rules/seo/hreflang-invalid.md) | error | hreflang uses invalid codes or relative URLs |
| [`seo/hreflang-not-reciprocal`](https://void-design.vercel.app/rules/seo/hreflang-not-reciprocal.md) | error | hreflang set isn't self-referencing and reciprocal |
| [`seo/og-missing`](https://void-design.vercel.app/rules/seo/og-missing.md) | error | Required Open Graph tags missing (og:title, og:type, og:image, og:url) |
| [`seo/og-incomplete`](https://void-design.vercel.app/rules/seo/og-incomplete.md) | warn | og:description / og:site_name missing, or og:url ≠ canonical |
| [`seo/og-image-invalid`](https://void-design.vercel.app/rules/seo/og-image-invalid.md) | error | og:image isn't a reachable, absolute, raster image within size limits |
| [`seo/og-image-size`](https://void-design.vercel.app/rules/seo/og-image-size.md) | warn | og:image is smaller than 1200×630 or far from 1.91:1 |
| [`seo/og-image-meta`](https://void-design.vercel.app/rules/seo/og-image-meta.md) | warn | og:image:width/height missing or wrong, or og:image:alt missing |
| [`seo/twitter-card`](https://void-design.vercel.app/rules/seo/twitter-card.md) | warn | twitter:card missing |
| [`seo/favicon`](https://void-design.vercel.app/rules/seo/favicon.md) | error | No crawlable favicon in a Google-supported format |
| [`seo/apple-touch-icon`](https://void-design.vercel.app/rules/seo/apple-touch-icon.md) | warn | apple-touch-icon missing or not a 180×180 PNG |
| [`seo/manifest`](https://void-design.vercel.app/rules/seo/manifest.md) | info | Web app manifest missing or incomplete |
| [`seo/theme-color`](https://void-design.vercel.app/rules/seo/theme-color.md) | info | No theme-color meta |
| [`seo/robots-txt-unreachable`](https://void-design.vercel.app/rules/seo/robots-txt-unreachable.md) | error | robots.txt returns 5xx/429 or times out |
| [`seo/robots-txt-missing`](https://void-design.vercel.app/rules/seo/robots-txt-missing.md) | warn | No robots.txt |
| [`seo/robots-txt-invalid`](https://void-design.vercel.app/rules/seo/robots-txt-invalid.md) | warn | robots.txt serves HTML, exceeds 500 KiB, or has unparseable lines |
| [`seo/robots-blocks-all`](https://void-design.vercel.app/rules/seo/robots-blocks-all.md) | error | robots.txt disallows the site for * / Googlebot / Bingbot |
| [`seo/robots-blocks-resources`](https://void-design.vercel.app/rules/seo/robots-blocks-resources.md) | error | robots.txt blocks JS/CSS needed to render |
| [`seo/robots-sitemap-directive`](https://void-design.vercel.app/rules/seo/robots-sitemap-directive.md) | warn | robots.txt has no absolute Sitemap: line |
| [`seo/sitemap-missing`](https://void-design.vercel.app/rules/seo/sitemap-missing.md) | error | No reachable sitemap |
| [`seo/sitemap-invalid`](https://void-design.vercel.app/rules/seo/sitemap-invalid.md) | error | Sitemap isn't valid sitemap XML or exceeds protocol limits |
| [`seo/sitemap-url-invalid`](https://void-design.vercel.app/rules/seo/sitemap-url-invalid.md) | error | Sitemap <loc> is relative or on another host |
| [`seo/sitemap-lastmod`](https://void-design.vercel.app/rules/seo/sitemap-lastmod.md) | warn | <lastmod> invalid, in the future, or identical across entries |
| [`seo/sitemap-url-status`](https://void-design.vercel.app/rules/seo/sitemap-url-status.md) | error | Sitemap lists URLs that don't return 200 directly |
| [`seo/sitemap-url-not-indexable`](https://void-design.vercel.app/rules/seo/sitemap-url-not-indexable.md) | error | Sitemap lists noindex, robots-blocked or non-canonical URLs |
| [`seo/duplicate-title`](https://void-design.vercel.app/rules/seo/duplicate-title.md) | warn | Multiple pages share the same <title> |
| [`seo/duplicate-description`](https://void-design.vercel.app/rules/seo/duplicate-description.md) | warn | Multiple pages share the same meta description |
