Run the command, paste the number. A machine decides pass or fail.
Filters write their state to the URL
blocker
colibrity
Only when the page has a listing, archive or search with filters.
Changing a filter changes location.search. Reloading that URL restores the same result set and the same visible filter UI. Clearing a filter removes its parameter rather than leaving it empty. Copying the URL to another browser reproduces the view.
Build instruction: Keep one named list of filter parameters. On any filter change, write the active values into the query string with history.replaceState and delete the parameter when a filter is cleared. On load, read the query string back and restore both the filter UI and the result set before the first paint of results.
Ships in wp-starter/filter-url-state - import it rather than rebuilding it.
Why this rule exists, and how to satisfy it
Doctype and a correct lang attribute on every page
blocker
html
Every sampled page has the doctype and a lang attribute whose value matches the language of the visible copy.
Build instruction: Start every document with the HTML5 doctype and set lang on the html element to the page's actual language. On a multilingual site the value changes per page rather than being hard-coded in the header partial.
JavaScript and CSS stay inside their budgets
blocker
perf
The budget test passes, or a raised budget is accompanied by that note in the commit. Without repository access this is reported as unverified, never as a pass.
Build instruction: Assert a gzip budget per chunk in the build and fail the build when it is exceeded. Raising a budget is allowed, in the same commit, with a written note saying what the extra bytes bought.
Ships in wp-starter/bundle-size-test - import it rather than rebuilding it.
CLS at or under 0.1
blocker
perf
Median mobile CLS is 0.1 or less, and no visible shift occurs during a slow-network reload watched by eye.
Build instruction: Reserve space for everything that arrives late: width and height on every image and video, explicit dimensions on embeds and ads, and font fallbacks metric-matched to the web font.
LCP at or under 2.5 seconds on mobile
blocker
perf
Median of three or more mobile runs is 2.5s or less, and the identified LCP element is stated in the report alongside the number.
Build instruction: Identify the LCP element before touching payload. It is usually being discarded rather than loading slowly - an element that finishes loading while hidden is dropped permanently, and opacity zero, clip-path and overflow hidden are all treated the same way. You cannot fade in your largest above-the-fold element and have a fast LCP.
Why this rule exists, and how to satisfy it
No credential ever reaches the repository or the web root
blocker
practices
No credential appears in git history or in the deployed web root. Requesting the environment file over HTTP returns 403 or 404.
Build instruction: Keep every key, password, host and licence in an environment file that is git-ignored and excluded from deployment. Whatever the deploy filter does not exclude ends up served over HTTPS - a licence file has been fetched from a live site this way.
Why this rule exists, and how to satisfy it
Every indexable page declares a self-referencing canonical
blocker
seo
Each sampled page returns one canonical, absolute, on the live host, equal to the URL that was requested once redirects have resolved.
Build instruction: Emit exactly one canonical link per page pointing at that page's own absolute URL, on the production domain, with the scheme and host the site actually serves.
Automated check: seo-status:canonical
HTTPS is enforced and nothing loads over http
blocker
seo
http:// returns a single 301 to https://, and no sampled page contains an http:// asset URL.
Build instruction: Redirect http to https in one hop and make sure no stylesheet, script, image, font or iframe has a hard-coded http:// URL. These usually arrive with migrated content, not code.
Automated check: seo-status:https-redirect, seo-status:mixed-content
Production is indexable and staging is not
blocker
seo
The production home page carries no noindex in the meta robots or the X-Robots-Tag header, and its robots.txt does not disallow the whole site. Staging carries noindex everywhere.
Build instruction: Drive the noindex decision from the environment, never from a checkbox someone has to remember. Staging returns noindex on every response; production returns none.
Automated check: seo-status:home-index, seo-status:robots
Why this rule exists, and how to satisfy it
Paged views are canonical to themselves
required
colibrity
Only when the listing has more items than fit on one page.
The canonical on page two equals page two's own URL, and page two's title differs from page one's.
Build instruction: Point the canonical of /page/2/ at /page/2/, never back at page one, and put the page number in the title. Canonicalising every page to the first one tells the crawler the other pages do not exist.
Automated check: seo-status:canonical
Ids are unique on the rendered page
required
html
The validator reports no duplicate id on any sampled page, including pages that render the same block more than once.
Build instruction: Watch for ids baked into a partial that repeats. A repeated block with a hard-coded id silently breaks label association, aria references and anchor links.
No inline event handlers or javascript: URLs
required
html
No rendered page contains an on* event attribute or an href starting with javascript:.
Build instruction: Bind behaviour in scripts, not in onclick attributes. Inline handlers block any meaningful Content Security Policy and scatter behaviour across templates.
One h1 per page, and no skipped heading levels
required
html
Each sampled page has exactly one h1, and its heading outline never jumps a level going down, for example h2 straight to h4.
Build instruction: Give each page exactly one h1 naming the page. Descend one level at a time. If a heading looks wrong at its correct level, that is a styling problem, not a structure problem.
Every template produces valid HTML
required
html
The validator reports zero errors on the sampled pages. Warnings are read and either fixed or noted with a reason.
Build instruction: Run the W3C validator over a sample covering every template, not just the home page. Unclosed elements and duplicate ids break assistive technology and JavaScript long before they look wrong.
Static assets are compressed and cached far-future
required
perf
Content-Encoding is br or gzip on HTML, CSS and JS, and hashed assets carry a cache lifetime of a year with immutable.
Build instruction: Confirm what the host actually sends rather than assuming. Some hosts compress nothing, in which case every estimate made from a gzipped size is wrong. Fingerprinted assets take a one-year immutable cache header.
Why this rule exists, and how to satisfy it
TBT at or under 200ms and INP at or under 200ms
required
perf
Median mobile TBT is 200ms or less. Where field data exists, INP at the 75th percentile is 200ms or less.
Build instruction: Keep the main thread free during load. Defer non-critical scripts, break long tasks, and keep third-party tags off the critical path.
Below-the-fold images lazy load, the LCP image does not
required
perf
Every below-the-fold image has loading lazy, the LCP image has neither lazy nor async decoding and carries fetchpriority high.
Build instruction: Put loading lazy on images below the fold and never on the LCP image, which instead takes fetchpriority high. Lazy-loading the hero delays the very metric it is meant to help.
Why this rule exists, and how to satisfy it
Mobile performance score at or above 90
required
perf
Median of three or more mobile runs is 90 or above, quoted with the spread of the runs.
Build instruction: Treat the score as a summary of the metrics above, not a target of its own. Chasing the number rather than the metric is how a site ends up fast in a lab and slow for people.
Why this rule exists, and how to satisfy it
Multilingual sites declare reciprocal hreflang
required
seo
Only when the site serves more than one language.
Each language version lists every other version plus itself plus x-default, and following any alternate lands on a page that lists the original back.
Build instruction: Emit hreflang alternates on every translated page, including a self-reference and an x-default. Every alternate must point back, or search engines discard the whole set.
Automated check: seo-status:hreflang
No internal link is broken
required
seo
A crawl of the sampled pages returns no 404 and no 5xx on internal links, and no chain of more than one redirect.
Build instruction: Crawl internal links before handover. Broken links usually come from content entry and trailing-slash mismatches, not from templates, so this has to run against real content.
Automated check: seo-status:link-ok, seo-status:link
Open Graph and Twitter card tags are complete
required
seo
All eight tags are present on a sampled page, og:url matches the canonical, and the og:image URL is absolute and returns an image of at least 1200 by 630.
Build instruction: Emit og:title, og:description, og:type, og:site_name, og:locale, og:url and an absolute og:image, plus twitter:card. A relative og:image renders as no image at all when shared.
robots.txt exists and points at the sitemap
required
seo
/robots.txt returns 200, contains a Sitemap: line with an absolute URL that itself returns 200, and does not disallow any route that should rank.
Build instruction: Ship a robots.txt that disallows sandbox, styleguide and any internal preview route, and names the sitemap with an absolute URL.
Automated check: seo-status:robots
The sitemap lists every indexable URL and nothing else
required
seo
The sitemap index returns 200, every child returns 200, a sample of ten listed URLs returns 200 with no redirect, and no listed URL carries noindex.
Build instruction: Generate the sitemap rather than maintaining it by hand. Exclude anything that is noindex, redirected or gone. Hand-maintained sitemaps go stale the first week nobody remembers them.
Automated check: seo-status:sitemap, seo-status:tax-sitemaps
Titles and descriptions are present, unique and the right length
required
seo
No sampled page is missing a title or description, no two sampled pages share either, and lengths sit in range.
Build instruction: Give every template a title pattern and every published page a description. Titles run roughly 30 to 60 characters, descriptions 70 to 160. Do not ship the theme defaults.