Skip to content

docs: add a reference for running axe-core without installing it - #4

Merged
84em merged 1 commit into
mainfrom
docs/running-axe
Aug 5, 2026
Merged

docs: add a reference for running axe-core without installing it#4
84em merged 1 commit into
mainfrom
docs/running-axe

Conversation

@84em

@84em 84em commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

Method step 1 named axe-core but assumed a scanner was already installed. When one is not, the tempting move is adding @axe-core/cli to the project, which is wrong for a dev-time audit tool and puts a lockfile change in front of a reviewer for no reason.

references/running-axe.md documents injecting axe-core into the running page instead: a single page, a whole-sitemap run that loads each URL into a same-origin iframe from one host page, and how to validate the harness before trusting a clean result.

Most of the file is failure modes, because each produces a silently wrong answer rather than an error:

Failure Symptom Fix
Parent axe instance on a frame node TypeError: axe.run arguments are invalid Inject axe into the frame, call the frame's own
CDP evaluate cap (~45s) Call times out mid-scan Run the loop detached, poll for progress
Dev-server livereload window state wiped mid-run Checkpoint to localStorage, make the loop resumable
Host-tab degradation ~2 pages/sec falls to 1 per 45s while the server stays fast Reload the tab, resume from the checkpoint
Settle too short Contrast failures that do not reproduce Await fonts.ready plus a real delay; re-verify every hit

That last one is why the file insists each flagged page is re-verified individually before being reported. A batch loop is the wide net, not the evidence.

The file also states plainly that this is one pass of four and never supports a conformance claim on its own, consistent with the skill's existing position.

Test plan

  • node scripts/validate.mjs passes (A=31 AA=24 AAA=31 total=86)
  • Every snippet in the file was executed against a real 274-page site during the run that produced these notes, not written from memory
  • The iframe harness was cross-checked against a direct axe.run(document) on the same page; violations matched
  • No emdashes; validate.mjs now covers the new file alongside the four existing authored docs
  • Scanned for private or client-identifying content before committing, since this repo is public

Notes for review

The numbers quoted in the file (a 120ms settle producing four non-reproducing contrast pages in a 274-page run, the two-pages-per-second to one-per-45-seconds degradation) are observations from a single real run, not benchmarks. They are there to make the symptoms recognisable, and are described that way.

Method step 1 named axe-core but assumed a scanner was already installed.
When one is not, the tempting move is to add @axe-core/cli as a dependency,
which is wrong for a dev-time audit tool and puts a lockfile change in front
of a reviewer for no reason.

references/running-axe.md documents the alternative: inject axe-core into the
running page. Covers a single page, a whole-sitemap run that loads each URL
into a same-origin iframe from one host page, and how to validate the harness
before trusting a clean result.

Most of the file is failure modes, because each of them produces a silently
wrong answer rather than an error:

- The parent's axe.run() rejects a node from another document with "axe.run
  arguments are invalid". The frame needs its own axe instance.
- A CDP Runtime.evaluate call caps out around 45 seconds, far short of a
  site-wide scan, so the loop has to run detached and be polled.
- Hugo, Vite and webpack dev servers reload every open page on any file
  change, which wipes anything held on window. Checkpoint to localStorage
  after each page and make the loop resumable.
- The host tab degrades over a few hundred pages, from roughly two pages per
  second to one per 45 seconds, while the server still answers in single-digit
  milliseconds. Diagnose before blaming the server; reload the tab and resume.
- color-contrast measures rendered pixels, so too short a settle reports
  failures that do not reproduce. A 120ms settle produced four bogus pages in
  a 274-page run; all four were clean at 600ms, twice.

The last one is why the file insists every flagged page is re-verified
individually before it is reported. A batch loop is the wide net, not the
evidence.

Also states plainly that this is one pass of four and never supports a
conformance claim on its own.

validate.mjs now runs its emdash check over the new file as well.
@84em
84em merged commit 792755f into main Aug 5, 2026
2 checks passed
@84em
84em deleted the docs/running-axe branch August 5, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant