@fulldotdev/check
v0.4.0
Published
Static checks of a built website's files: HTML and accessibility markup, links, assets and fragments, also in Markdown, feeds and web manifests, SEO tags, structured data syntax, sitemap and robots.txt, file sizes and sensitive files.
Maintainers
Readme
@fulldotdev/check
Static checks of a built website. Run it on the output folder after the build; it only reads the files in that folder. It runs none of their code, starts no browser or server and makes no requests.
- HTML: html-validate with its
standardanda11yrules, a nonempty title and the page'slang, a doctype, a label for each form control, and IDs thatfor,aria-labelledby,aria-describedbyand other attributes name. Anaria-controlsmay name what a script mounts, such as a closed dialog. - Links: every page and stylesheet, also those no other page links to, against the files in the build: links, images (also
srcset), media, scripts, stylesheets,<link>s, meta refreshes, OpenGraph and Twitter URLs, SVG<use>and<image>, and CSSurl()s and@imports in stylesheets,<style>andstyleattributes. Also the links and images of Markdown files andllms.txt, the links of RSS and Atom feeds, and a web manifest's start URL, icons, screenshots and shortcuts.#fragmentsof pages must name an ID or<a name>. Absolute links to the site's own origin are checked against the build. - SEO: each page has a valid
lang, one nonempty meta description and one absolute canonical URL. Pages with robotsnoindexneed no description or canonical; redirect pages (a meta refresh to a URL) need neither. A canonical URL of another page is that page's own canonical URL, not a redirect page or one withnoindex. JSON-LD is valid JSON and an object or an array of objects, whose@ids are strings,@types strings or arrays of strings,@graphs objects or arrays of objects and@contexts URLs, objects or arrays of them. - Sitemap and robots.txt, when the build has them: robots.txt's sitemaps exist, and each sitemap URL is listed once, is a built page without
noindexor a redirect, is its own canonical URL and is allowed by robots.txt. Alastmod, when present, is a W3C date no more than a day in the future. - Other files:
llms.txtstarts with an H1 title, a feed is XML and a web manifest a JSON object. Environment and credential files, private keys and version control folders are not in the build, also as dotfiles that hosts do not serve. - Other findings: an
hreflangthat is no language tag orx-default, a built page it points to that does not link back or has anotherlang, and indexable pages in the same language with the same title or meta description, unless their canonical URL is another page's. An indexable page, other than the homepage, that no other page links to, or that no sitemap lists when the build has one. A linked image over 1 MiB, or script, stylesheet or font over 500 KiB. A<link rel="preload">withoutas, or a font's withoutcrossorigin. A.DS_Store.
Install
It needs Node.js 24 or later:
npm install --save-dev @fulldotdev/checkUse
fulldev-check # checks ./dist
fulldev-check build # another folder
fulldev-check --json # the issues as JSON
fulldev-check --fail-on warning # a stricter build thresholdCheck and Fulldev Scan share condition defaults from @fulldotdev/check/policy:
critical: a missing internal navigation page, exposed credentials or private keys, a homepage withnoindex, Googlebot blocked from the homepage, or an HTTP form submission.warning: broken resources, missing titles, descriptions, labels or alt text, invalid SEO metadata, and file size budgets.hint: HTML standard violations without a more specific impact rule, orphan pages, sitemap duplicates and unlisted pages.
Severity describes impact. A service agreement determines which warnings and hints must be handled; it does not change their severity. Critical findings always fail Check. The default threshold is critical; --fail-on warning also blocks warnings, and --fail-on hint blocks all findings. There is no threshold that permits critical findings.
It exits 1 at the selected threshold or when execution fails, 0 below that threshold, and 2 on wrong usage. Missing builds and other execution failures are errors on stderr, outside customer finding counts. Measurement limitations remain visible with limitation: true and do not count as customer defects.
Astro's error, warning and hint diagnostics remain separate source-code checks. Their labels and counts do not describe the same customer impact or coverage.
Version 0.4 changes the public severity values from error | warning to critical | warning | hint, adds condition code and confidence, and changes the default build threshold. Reclassified findings are not fixed defects. Scan groups occurrences and uses live evidence, so its counts can differ even with shared defaults. Its evidence-dependent severity overrides remain in Scan.
--json prints a sorted array of issues:
[
{
"rule": "links/broken",
"code": "broken-pages",
"severity": "critical",
"confidence": "confirmed",
"file": "about/index.html",
"line": 12,
"message": "Broken link: /contact/ (not in the build)"
}
]file is relative to the folder, line is there when known, and rule starts with html/, links/, seo/, sitemap/, robots/, llms/, feed/, manifest/, perf/, security/ or security/.
From code:
import { checkSite } from "@fulldotdev/check"
const issues = await checkSite({ dist: "dist" })
// Declare only known framework routes. These remain unverified until a live
// check confirms their response; missing static pages are still findings.
const hybridIssues = await checkSite({
dist: "dist",
serverRoutes: [/^\/vacancies\/?$/],
})How it works
A link resolves as in a browser, against the page's URL or its <base href>, and points to the file a static host serves at its path: /about and /about/ find about/index.html and about.html, the query is ignored, percent-encoded characters are decoded, and letter case must match exactly, as on Linux hosts. Dotfiles other than those in .well-known are not served.
A fragment is found as a browser finds it, also percent-decoded; #, #top and text fragments (#:~:text=) need no ID. IDs inside <template> are not the page's.
The site's origin is that of the homepage's canonical URL, or else the one origin of all other canonical URLs.
Markdown is read as CommonMark: its inline, reference and image links count, and its frontmatter, code and HTML do not. Feeds are the files that pages link to as RSS or Atom, .rss and .atom files, and XML files with an RSS or Atom root; their URLs resolve against xml:base, and guids and IDs are not links. Web manifests are the files that pages link to as such and .webmanifest files.
An indexable page has no robots noindex, is no redirect page, is its own canonical URL and is not the 404.html that hosts serve for missing pages. A page links to another with a link, an area, a form or a meta refresh, also in a <template>.
Limits
- Links to other hosts, HTTP statuses, links that JavaScript creates or handles, rendering, contrast and other computed styles are not checked; Fulldev Scan checks the live site.
- The site is served from the root of its domain; a site under a subpath, such as
https://example.com/docs/, is not supported. - Host features such as redirect rules, rewrites, custom headers and server routes are not emulated. The API can declare known
serverRoutesas regular expressions; unresolved links to them are unverified measurements. All other missing paths remain findings. Hosted image services also need live verification. - Fragments of other files, such as an SVG's or a PDF's, and of redirect pages are not checked.
- What JSON-LD's types and properties mean, and whether its IDs exist, is not checked.
- Size budgets are those of the files, not what a browser downloads, which depends on the screen,
srcsetand compression. - Automated checks find part of the accessibility problems, not all.
License
MIT
