Rules

seolint checks every page with the rules below. Each rule belongs to a built-in plugin, and runs unless your config turns it off.

Configure a rule

Set rules in the rules field of seolint.config.ts:

import * as config from "seolint/config";

export default config.define({
  rules: {
    "html.favicon": false, // turn a rule off
    "heading.order": "error", // change its severity
    "title.content.length": { max: 70 }, // change some options
    "link.external.limit": ["warn", { max: 10 }], // both
    "og.*": "error", // every rule that matches a pattern
  },
});
Setting Effect
false Turns the rule off.
true Turns the rule on, with its default severity and options.
"error" or "warn" Turns the rule on, with that severity.
{ ... } Turns the rule on, and overrides some of its options.
["warn", { ... }] Sets the severity and some options.

Run seolint --rules to list every rule with its current setting.

html

Rules about the document as a whole.

RuleDefaultChecks
html.doctype error A page starts with <!doctype html>.
html.lang error The <html> element has a valid lang attribute.
html.charset error A page declares the utf-8 encoding near the top.
html.favicon warn A page links to a favicon.
html.refresh warn A page does not redirect with a meta refresh.

title

Rules about the <title> element, which search results show as the link text.

RuleDefaultChecks
title.exists error A page has a <title> element in its <head>.
title.single error A page has only one <title> element.
title.content.html error The title has no HTML tags in its text.
title.content.undefined error The title does not include the word "undefined".
title.content.null error The title does not include the word "null".
title.content.length warn The title length is within a range of characters.

description

Rules about <meta name="description">, which search results often show below the title.

RuleDefaultChecks
description.exists error A page has a <meta name="description"> tag.
description.single error A page has only one description tag.
description.content.empty error The description is not empty.
description.content.html error The description has no HTML tags in its text.
description.content.title warn The description shares at least one meaningful word with the title.
description.content.undefined error The description does not include the word "undefined".
description.content.null error The description does not include the word "null".
description.content.length warn The description length is within a range of characters.

canonical

Rules about <link rel="canonical">, which tells search engines the main URL of a page.

RuleDefaultChecks
canonical.exists error A page has a <link rel="canonical"> tag.
canonical.single error A page has only one canonical link.
canonical.href.exists error The canonical link has a non-empty href.
canonical.href.absolute error The canonical href is an absolute URL.
canonical.href.lowercase warn The canonical href has no uppercase letters.
canonical.href.https error The canonical href uses https://.
canonical.href.fragment error The canonical href has no #fragment.
canonical.href.match error The canonical href uses the site hostname.
canonical.href.self warn The canonical href points at the page itself.
canonical.head error The canonical link is inside <head>.

viewport

Rules about <meta name="viewport">, which controls how a page fits on phones.

RuleDefaultChecks
viewport.exists error A page has a <meta name="viewport"> tag.
viewport.single error A page has only one viewport tag.
viewport.content.empty error The viewport content is not empty.
viewport.content.device error The viewport content includes "width=device-width".
viewport.content.scale error The viewport content includes "initial-scale=1".
viewport.content.zoom error The viewport does not stop users from zooming.

heading

Rules about headings, which show search engines how a page is organized.

RuleDefaultChecks
heading.exists error A page has an <h1>.
heading.single warn A page has only one <h1>.
heading.order warn Headings start at <h1> or <h2>, and do not skip levels, such as an <h4> after an <h2>.

robots

Rules about <meta name="robots"> and <meta name="googlebot">.

RuleDefaultChecks
robots.noindex error A page does not ask search engines to leave it out of results.
robots.nofollow error A page does not ask search engines to ignore its links.

image

Rules about <img> elements.

RuleDefaultChecks
image.alt.exists error An <img> has an alt attribute. alt="" is allowed, for decorative images.
image.alt.content.html error The alt text has no HTML tags.
image.alt.content.undefined error The alt text does not include the word "undefined".
image.alt.content.null error The alt text does not include the word "null".

Rules about <a> elements. A link is internal when it is relative, or when its hostname matches the host. Without a host, every absolute link counts as external. Except for link.href.exists and link.text.exists, links to a section of the same page, such as #install, and links to mailto: and javascript: are skipped, and each href is checked once per page. Links to a section of the same page also skip link.text.vague.

RuleDefaultChecks
link.href.exists error A link has an href attribute.
link.href.empty error A link href is not empty.
link.internal.trailing error An internal link ends with a slash for a folder page, and without one for a file page.
link.internal.lowercase warn An internal link has no uppercase letters.
link.internal.nofollow error An internal link does not use rel="nofollow".
link.internal.pretty off An internal link does not end with ".html".
link.internal.absolute off An internal link starts with /, //, or a protocol.
link.internal.https error An internal link uses https:// or a root-relative path.
link.external.limit off A page has at most a number of external links.
link.blank.noopener off A link with target="_blank" uses rel="noopener".
link.blank.noreferrer off An external link with target="_blank" uses rel="noreferrer".
link.text.exists error A link has text, an aria-label, or an image with alt text.
link.text.vague warn A link text describes its target, unlike "click here".

mixed

RuleDefaultChecks
mixed.content error An https:// page loads no resources over http://.

hreflang

Rules about <link rel="alternate" hreflang>, which point search engines to translated versions of a page. They only run on pages with such links.

RuleDefaultChecks
hreflang.code error An hreflang value is a valid language code, or x-default.
hreflang.absolute error An hreflang link uses an absolute URL.
hreflang.default warn Pages with hreflang links also have an x-default link.
hreflang.self error Pages with hreflang links also link to themselves.
hreflang.return error A page that an hreflang link points to links back to the page.

og

Rules about Open Graph tags, which social networks and chat apps use for link previews. They do not change search ranking, so they default to warn. Set "og.*": "error" to require them.

RuleDefaultChecks
og.title warn A page has an og:title, for link previews.
og.description warn A page has an og:description, for link previews.
og.image warn A page has an og:image, for link previews.
og.image.secure warn The og:image is an absolute https:// URL.
og.url warn A page has an og:url that matches its canonical URL.

twitter

RuleDefaultChecks
twitter.card warn A page has a valid twitter:card, for link previews.

jsonld

Rules about JSON-LD, the structured data in <script type="application/ld+json"> that Google reads for rich results.

RuleDefaultChecks
jsonld.valid error Each JSON-LD script is valid JSON, with an @context and an @type.

site

Rules that compare pages across the whole site. They run when you lint a folder, or URLs, with seolint public or run(). They do not run for lint(), which checks one page.

Two rules of other plugins also compare pages: link.internal.trailing reads the built files, and hreflang.return compares the linted pages.

RuleDefaultChecks
site.title.unique error Every page has a different title.
site.description.unique error Every page has a different description.
site.link.exists error Internal links point to files that exist in the build.
site.canonical.exists error A canonical link to the site points to a page of the build.
site.page.linked warn Every page has a link from another page.
site.robots warn A robots.txt exists, and does not block every crawler.
site.robots.noindex error robots.txt does not block a page with noindex, so search engines see it.
site.sitemap warn A sitemap exists, and lists every page.
site.sitemap.entries warn A sitemap lists only https pages of the build that search engines can index and crawl.