Back to Blog
Technical

From axe-core Report to Fixed Code in 5 Minutes (Step-by-Step Workflow)

certvo.com TeamMay 1, 20269 min read

axe-core gives you a JSON report that tells you what is broken. What it does not give you is the fix. That gap — between “here is the problem” and “here is the working code” — is where developers spend most of their accessibility debugging time. This article walks through the process from start to finish: reading the report, understanding the violation, writing the fix, and verifying it.

Step 1: Read the axe-core Output

Here is a realistic slice of an axe-core JSON report. This is what you get when you run axe against a page using the browser extension or the Node.js API:

{
  "violations": [
    {
      "id": "image-alt",
      "impact": "critical",
      "tags": ["wcag2a", "wcag111", "section508", "TTv5"],
      "description": "Ensures <img> elements have alternate text or a role of none or presentation",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.8/image-alt",
      "nodes": [
        {
          "html": "<img src=\"/products/backpack.jpg\">",
          "target": ["#product-hero > img"],
          "failureSummary": "Fix any of the following:\n  Element does not have an alt attribute\n  aria-label attribute does not exist or is empty"
        }
      ]
    },
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": ["wcag2aa", "wcag143"],
      "description": "Ensures the contrast between foreground and background colors meets WCAG 2 AA minimum thresholds",
      "nodes": [
        {
          "html": "<span class=\"price-label\">$89.99</span>",
          "target": [".product-card .price-label"],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.82 (foreground color: #aaaaaa, background color: #ffffff, font size: 12pt, font weight: normal)"
        }
      ]
    },
    {
      "id": "label",
      "impact": "critical",
      "tags": ["wcag2a", "wcag332"],
      "description": "Ensures every form element has a label",
      "nodes": [
        {
          "html": "<input type=\"email\" placeholder=\"Email address\">",
          "target": ["#newsletter-form input[type='email']"]
        }
      ]
    }
  ]
}

Step 2: Triage by Impact Level

axe-core uses four impact levels: critical, serious, moderate, minor. Fix in that order. All three violations above are either critical or serious — they would all fail WCAG 2 Level A or AA. Here is the triage:

Priority 1 (Critical — WCAG A failures):
  - image-alt: #product-hero > img
  - label: #newsletter-form input[type='email']

Priority 2 (Serious — WCAG AA failures):
  - color-contrast: .product-card .price-label

Step 3: Look Up the WCAG Criterion, Then Write the Fix

The tags on each violation map to WCAG criteria. “wcag111” is WCAG 1.1.1 Non-text Content. “wcag143” is WCAG 1.4.3 Contrast (Minimum). “wcag332” is WCAG 3.3.2 Labels or Instructions.

Fix for image-alt:

<!-- Before (failing) -->
<img src="/products/backpack.jpg">

<!-- After (passing) -->
<img src="/products/backpack.jpg" alt="Navy blue TrailPro 32L hiking backpack with padded shoulder straps">

Fix for color-contrast:

/* Before (failing): #aaaaaa on #ffffff = 2.82:1 */
.price-label { color: #aaaaaa; }

/* After (passing): #767676 on #ffffff = 4.54:1 — just over the 4.5:1 threshold */
.price-label { color: #767676; }

/* Even better: #595959 on #ffffff = 7:1 — passes AAA too */
.price-label { color: #595959; }

Fix for missing form label:

<!-- Before (failing) -->
<input type="email" placeholder="Email address">

<!-- After (passing) -->
<label for="newsletter-email">Email address</label>
<input type="email" id="newsletter-email" name="email" placeholder="you@example.com">

<!-- Alternative: visually hidden label if design can't accommodate visible label -->
<label for="newsletter-email" class="sr-only">Email address</label>
<input type="email" id="newsletter-email" placeholder="Email address">

Step 4: Re-Test with axe-core

After making your fixes, run axe again to verify the violations are gone. From Node.js:

const { chromium } = require('playwright');
const axeCore = require('axe-core');
const { createHtmlReport } = require('axe-html-reporter');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('http://localhost:3000/products/backpack');

  await page.addScriptTag({ content: axeCore.source });
  const results = await page.evaluate(() => axe.run());

  console.log('Violations: ' + results.violations.length);
  results.violations.forEach(v => {
    console.log('[' + v.impact + '] ' + v.id + ': ' + v.nodes.length + ' instance(s)');
  });

  await browser.close();
})();

The Manual Process vs. Certvo

The workflow above works. But it takes time — typically 15-30 minutes per page for a developer unfamiliar with accessibility, longer if the component is complex. For a 50-page site, that is days of work.

Here is what the same workflow looks like with Certvo:

# Text-based workflow diagram

axe report output
       │
       ▼
  [Certvo scan]
       │
       ├──► Issue list with WCAG tags and impact
       │
       ├──► AI-generated code fix for each issue
       │         (with confidence score)
       │
       ├──► One-click "Copy fix" to clipboard
       │
       └──► Re-scan to verify fix applied

Total time per page: ~5 minutes vs. 15-30 minutes manual

Certvo runs axe-core under the hood (plus additional rules), then passes each violation to the AI fix engine described in the AI code fixes article. You get the violation and the fix in the same interface, without having to context-switch between a JSON report, the WCAG spec, and your editor.

Integrating Into Your CI Pipeline

For ongoing enforcement, you want accessibility checks in your CI pipeline. Here is a minimal GitHub Actions step using axe-core:

# .github/workflows/accessibility.yml
name: Accessibility Check
on: [push, pull_request]

jobs:
  axe:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run build
      - run: npx serve -l 3000 out &
      - run: npx wait-on http://localhost:3000
      - run: npx axe http://localhost:3000 --exit

This will fail the build if critical or serious accessibility violations are found. Add the Certvo API endpoint to get AI fix suggestions when the build fails, so your developers do not just see a red light — they see the fix too.

Check Your Website's Accessibility

Run a free scan and get AI-powered fix suggestions in minutes.

Start Free Scan