In lesson 06-01 you did the slow, honest work: walking through the Cursalia course page with keyboard, NVDA, zoom, and DevTools. It works, but it doesn't scale. Nobody is going to repeat that walkthrough by hand across 40 pages, on every deploy, on every pull request. That's where automated tools come in: they analyze the code (the already-rendered DOM) and find, in seconds, objective problems that would take a human half an hour. But before the first screenshot, burn this number into your forehead: automation detects only 30-40% of accessibility problems. It doesn't replace the manual testing from 06-01, nor the real users from 06-03. It's the first layer of a defence in depth, not the whole defence.
Contents
- What a machine can and can't see
- axe-core and axe DevTools (the extension)
- WAVE
- Lighthouse in Chrome DevTools
- Pa11y (command line)
- Accessibility Insights
- Linting during development: eslint-plugin-jsx-a11y
- CI integration: so nobody breaks what's been fixed
- Comparison table
- False positives and false negatives
- What a machine can and can't see
An automated analyzer is a program that walks the DOM tree and applies deterministic rules: "every <img> must have an alt attribute", "a form control must have an accessible name", "this contrast ratio is 2.9:1 and AA requires 4.5:1". These are binary, objective checks, and that's where machines are unbeatable: fast, tireless, and with no judgement of their own to lead them astray.
The problem is everything that requires human judgement:
| What a machine CAN detect | What it CANNOT detect |
|---|---|
A missing alt attribute |
Whether the alt describes the image well ("instructor photo" vs "IMG_2043") |
| Color contrast below the threshold | Whether the focus order is logical for the task |
A <label> with no associated for |
Whether the button's name makes sense in context |
aria-* with invalid values or a non-existent role |
Whether an error message is announced when it appears |
| Headings that skip a level (h1→h3) | Whether the page is actually usable with NVDA |
Missing page language (<html lang>) |
Whether an icon conveys something the text doesn't say |
Mental rule: the machine tells you the alt exists; only a human knows whether the alt is good. That's why it's 30-40%: almost everything qualitative slips past it.
- axe-core and axe DevTools (the extension)
axe-core (from Deque) is the most widely used accessibility rules engine in the world: it's open source and lives inside almost everything else (Lighthouse, Accessibility Insights, many test suites). Learning axe means learning the industry's common vocabulary.
The fastest way to start is the axe DevTools extension for Chrome/Firefox/Edge:
- Install the extension and open the Cursalia catalog.
- DevTools → axe DevTools tab → Scan all of my page.
- Read the list of Issues grouped by severity.
Reading a violation in the catalog
Suppose axe reports this about the course cards:
VIOLATION: Buttons must have discernible text (critical)
Rule: button-name
WCAG criterion: 4.1.2 Name, Role, Value (Level A)
Element: <button class="fav-btn"><i class="bi bi-heart"></i></button>
How to fix: the button has no text or aria-label; add an
accessible name ("Add to favorites").How to read an axe violation, field by field:
- Rule (
button-name): the technical identifier; useful for looking up documentation and for silencing false positives. - WCAG criterion (
4.1.2, level A): tells you which standard you're violating and with what priority. - Element: the exact selector in the DOM. It's the "favorite" heart icon with no text—exactly the "buttons with no accessible name" fault we anticipated in 06-01.
- Impact (critical/serious/moderate/minor): the prioritization hint we'll squeeze in 06-04.
- How to fix: the recommendation. The actual how (giving an icon an accessible name) you saw in Module 4.
- WAVE
WAVE (from WebAIM) is an extension that shows the results overlaid on the page itself with icons: errors in red, alerts in yellow, structural elements, ARIA. It's especially instructive because you see where each problem is without reading selectors.
On the Cursalia course page, WAVE is excellent for spotting at a glance: out-of-order headings, images with no alt, empty links, insufficient contrast, and regions/landmarks. Its Structure/Order view helps you see the heading hierarchy in one go. An important detail: the yellow icons are alerts, not errors—things that might be wrong and that a human must review. WAVE is honest about flagging when it isn't sure.
- Lighthouse in Chrome DevTools
Lighthouse comes built into Chrome (DevTools → Lighthouse tab → tick Accessibility → Analyze). It gives a score from 0 to 100 and uses axe-core under the hood.
Advantage: it's zero friction, you already have it. The dangerous trap: the score is misleading. A "95/100" on Cursalia does not mean "95% accessible"; it means "95% of the automated checks pass", and those checks are only that 30-40% of the total. You can have 100/100 and a page that's unusable with a screen reader. Use Lighthouse for a quick snapshot and to watch for regressions, never as a certificate of accessibility.
- Pa11y (command line)
Pa11y is an analyzer that runs from the terminal, without opening a browser by hand. That makes it ideal for automation and for dropping into scripts.
# Global installation
npm install -g pa11y
# Analyze a page of the Cursalia catalog
pa11y https://cursalia.example/catalog
# Choose the standard and JSON format (to process later)
pa11y --standard WCAG2AA --reporter json https://cursalia.example/catalogTypical output (abridged):
Results for URL: https://cursalia.example/catalog
• Error: This element has insufficient contrast at this
conformance level (4.35:1; required 4.5:1).
— WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail
— (#price-python-course)
• Error: Anchor element found with no link content.
— WCAG2AA.Principle4...H91.A.NoContent
— (.card-link)With Pa11y you can, for example, scan a list of Cursalia URLs in a loop and fail the process if any error shows up—the basis for the CI step in section 8.
- Accessibility Insights
Accessibility Insights (from Microsoft) also uses axe-core, but adds two very valuable things:
- FastPass: a quick automated scan (equivalent to axe) plus a guided tab order check that draws numbered arrows over the page. It's a great bridge between the automated and the manual work of 06-01.
- Assessment: a guided review, criterion by criterion, that walks you through the manual checks the machine can't do on its own. It explicitly acknowledges that automation isn't enough and forces you to bring the human eye.
- Linting during development: eslint-plugin-jsx-a11y
The tools above act on an already-rendered page. Linting acts earlier: while you're writing the code, in the editor. For React/JSX projects, eslint-plugin-jsx-a11y flags accessibility problems in the source code.
// .eslintrc.js (excerpt)
module.exports = {
extends: ['plugin:jsx-a11y/recommended'],
plugins: ['jsx-a11y'],
};Example: if a Cursalia developer writes the course card like this...
// The linter warns AS YOU TYPE:
// "img elements must have an alt prop" (jsx-a11y/alt-text)
<img src={course.cover} />...ESLint underlines it in red before you even save. It's the cheapest feedback possible: it costs nothing to fix something that hasn't left the editor yet. Limitation: it only sees static patterns in the code (a missing alt, an onClick on a <div> with no role), not the rendered result or the real contrast.
- CI integration: so nobody breaks what's been fixed
Fixing a fault once is easy; making sure it doesn't come back is the hard part. The solution is to run the automated analyses in continuous integration (CI): on every pull request, a robot scans and blocks the merge if new violations appear.
At a high level, an automated test with axe-core inside your test suite (Jest + jsdom, or Playwright/Cypress in a real browser) looks like this:
// Conceptual example with Playwright + @axe-core/playwright
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('the Cursalia catalog has no axe violations', async ({ page }) => {
await page.goto('https://cursalia.example/catalog');
const results = await new AxeBuilder({ page }).analyze();
// The test FAILS if there's any violation
expect(results.violations).toEqual([]);
});In a pipeline (GitHub Actions, GitLab CI…) this runs on its own on every push. Many teams start pragmatically: they don't block on everything, only on critical and serious violations, and temporarily tolerate the moderate ones while they work through them. The same can be achieved with Pa11y in CI mode (pa11y-ci).
- Comparison table
| Tool | Type | What it detects well | Limits | Where it fits in the flow |
|---|---|---|---|---|
| axe DevTools | Browser extension | Broad base of WCAG rules, very few false positives | Automated only; doesn't judge meaning/usability | Ad-hoc review in the browser |
| WAVE | Browser extension | Very visual; structure, headings, contrast | Less integrable; alerts need human judgement | Learning and reviewing visually |
| Lighthouse | In Chrome DevTools | Quick snapshot with a score; uses axe | The score is misleading; partial coverage | Quick look / watching for regressions |
| Pa11y | CLI | Automatable, multiple URLs, JSON output | No visual interface; initial setup | Scripts and CI |
| Accessibility Insights | Extension + guide | FastPass + tab order + guided review | The assessment part is manual | Automated↔manual bridge |
| eslint-plugin-jsx-a11y | Linter (code) | Errors in JSX as you write | Static only; doesn't see render or contrast | While you code |
| axe-core in CI | Automated test | Prevents regressions on every PR | ~30-40% coverage; needs setup | Quality gate in the pipeline |
Recommended combination for Cursalia: jsx-a11y while you code, axe-core in CI to avoid regressions, axe DevTools/WAVE for ad-hoc reviews, and always on top of it the manual testing (06-01) and the users (06-03).
- False positives and false negatives
No tool gets it 100% right:
- False positive: the tool flags an error that isn't one. A classic example: WAVE warns of "low contrast" on text that's actually hidden or over a decorative image; or axe flags an
ariathat's correct in your context. These can be silenced by rule and selector, but document why—an unjustified silence is hidden debt. - False negative (the dangerous one): the tool says "all OK" and there's a real problem it can't detect. A generic
alt="image"passes the analysis (the attribute exists) but is useless for Marta. An absurd focus order passes. An error message that isn't announced passes. The tool's green is not a pass.
That's why the healthy flow is: automated for the objective and repeatable → manual (06-01) for judgement → real users (06-03) for usability.
Common Mistakes and Tips
- Believing the Lighthouse score: "we have 98, we're accessible" is false. It covers only the automated part. Never put it in marketing as a seal of accessibility.
- Scanning only the home page: the enrollment modal, the quiz, and the player only appear after interaction. Many tools analyze the initial state; open the modal before scanning, or use tests that interact (Playwright).
- Ignoring the yellow alerts: in WAVE/axe, "needs review" isn't "passed". It's precisely where the human eye is needed.
- Silencing without documenting: every disabled rule must carry a comment and a reason, or it becomes a permanent hole.
- Putting nothing in CI: without an automated gate, what you fix today someone breaks next week. At the very least, block critical and serious issues.
- Tip: use several tools; each has a slightly different rule catalog, and together they cover more.
Exercises
Exercise 1. You run Lighthouse on the Cursalia course page and it scores 100/100 on accessibility. Your boss wants to announce "100% accessible website". What do you explain, and which two types of testing are missing before claiming that?
Exercise 2. axe reports on the catalog: image-alt (critical), element <img src="cover-python.webp">, WCAG 1.1.1 (A). A colleague "fixes" it by setting alt="image" and the analysis turns green. Why is this a false negative, and who does it still harm?
Exercise 3. Design the minimal automated strategy for the Cursalia team using three layers (during development, on every PR, and in ad-hoc review). Name one tool per layer and what each would do.
Solutions
Solution 1. You explain that Lighthouse only runs the automated checks, which cover roughly 30-40% of the criteria; the 100 means "the automated checks pass", not "the website is accessible". At a minimum, manual testing (keyboard + screen reader + zoom, lesson 06-01) and testing with real users of assistive technologies (06-03) are missing. Claiming "100% accessible" without them is incorrect and risky (even legally).
Solution 2. It's a false negative because the tool checks that the alt attribute exists, not that its content makes sense. alt="image" satisfies the rule but conveys nothing: NVDA will read "image" and Marta still won't know which course it is. The machine can't judge the quality of the alternative text; that's validated by hand (06-01) and decided with the alt decision tree from Module 5.
Solution 3. Example: (1) During development → eslint-plugin-jsx-a11y, which warns in the editor about images with no alt or clickable divs. (2) On every PR → a test with axe-core in Playwright that fails the build on critical/serious violations, preventing regressions. (3) Ad-hoc review → axe DevTools or WAVE in the browser before a big release, including states like the open modal. And on top of all three, the manual testing and the users.
Conclusion
Automated tools are your force multiplier: fast, objective, integrable into CI, and perfect for making sure no objective fault comes back. But they have a hard ceiling—that 30-40%—and a subtle danger: a green panel can give you a false sense of security. Neither the meaningful alt, nor the logical focus order, nor the real usability with a screen reader is seen by a machine. Only people validate that. In the next lesson, 06-03 User Testing with Assistive Technologies, we take the decisive leap: sitting Marta, Lucía, and Sofía—real users—in front of Cursalia and uncovering the problems that neither automation nor your own manual testing ever reached.
Web Accessibility Course
Module 1: Introduction to Web Accessibility
- What Is Web Accessibility?
- The Importance of Web Accessibility
- Overview of Accessibility Laws and Standards
- Introduction to WCAG
Module 2: Understanding Disabilities and Assistive Technologies
Module 3: Principles of Accessible Design
- Perceivable: Making Content Available to the Senses
- Operable: User Interface and Navigation
- Understandable: Information and Operation
- Robust: Compatibility with Current and Future Technologies
Module 4: Implementing Accessibility in HTML and CSS
Module 5: Accessibility in JavaScript and Multimedia
- Creating Accessible JavaScript Widgets
- Keyboard Accessibility
- Accessible Video and Audio Content
- Providing Text Alternatives for Images
Module 6: Accessibility Testing and Evaluation
- Manual Testing Techniques
- Automated Testing Tools
- User Testing with Assistive Technologies
- Interpreting Accessibility Reports
