Threestudio

Bold ideas, shipped with quiet precision.

Loading 000
Threestudio

Design & UI Resources

How to Audit AI-Generated Frontend Code: A 2026 Checklist

hi3n

Think about the last time you accepted a building's keys without an inspection. You would not. The lobby looks great, the contractor finished early, and nobody…

Cover Image

How to Audit AI-Generated Frontend Code: A 2026 Checklist

Think about the last time you accepted a building's keys without an inspection. You would not. The lobby looks great, the contractor finished early, and nobody has checked the wiring. That is a useful analogy for accepting AI-generated frontend code without checking it.

The 2025 DORA report summary reports 90% AI adoption among surveyed software-development professionals, over 80% reporting productivity gains, and 30% expressing little or no trust. Separately, METR’s early-2025 randomized study found 16 experienced open-source developers took 19% longer across 246 tasks with AI allowed, despite estimating a 20% speedup afterward. That result describes this study’s developers, tasks and tools, not all AI-assisted development.

💡 Tip: This post is about auditing the code. If you want the visual-polish side, that is a different problem with a different checklist. See how to make AI-generated UI look professional.

Here is how to audit AI-generated frontend code in three passes that catch what a normal code review will not.

Key Takeaways

- 95.9% of the top million home pages had detected WCAG 2 failures in WebAIM's February 2026 Million analysis. That is the first regression in six years.- Deque reported about 57% automated coverage in its study of over 2,000 audits; that is not a universal ceiling. The highest-value checks are manual: keyboard, screen reader, alt-text judgment.- Field data reflects real-user experience, but a CrUX pass alone does not determine search ranking. CrUX reports metrics over a rolling 28-day collection window, so never judge a performance fix the same day.- Audit in three passes: accessibility, performance, semantics. Then count the five failure patterns to decide rescue or rebuild.

Why auditing AI-generated frontend code is different

Before the checklist, the diagnosis. This checklist groups potential frontend defects into three areas to inspect.

It passes the eye test and fails the keyboard test

The most recent WebAIM Million, reports February 2026 data from the top one million home pages. A staggering 95.9% had detected WCAG 2 failures. That is up from 94.8% the previous year, and the first regression in six years. The average page carried 56.1 errors, a 10.1% increase, and 1,437 elements, up 14.3% in a single year.

The six most common failures account for 96% of all detected errors:

Failure

Share of home pages

Low contrast text

83.9%

Missing image alt text

53.1%

Missing form labels

51%

Empty links

46.3%

Empty buttons

30.6%

Missing document language

13.5%

The AIMAC benchmark evaluates model-generated web pages with automated accessibility checks. Its model set and results change; use a dated snapshot rather than treating an older 35-of-37 count as current.

A W4A 2024 doctoral-consortium paper by Peya Mowar reports that Copilot reproduced accessibility patterns from the surrounding website and sometimes added unrequested, unlabeled video links. The author identifies a limited dataset, so this is a contextual observation rather than a result about every current model.

It is confidently, plausibly wrong

Stack Overflow's 2025 survey of roughly 49,000 developers found the top frustration with AI tools is not that the code is broken. It is that the code is "almost right, but not quite," cited by 66% of respondents to that question. Among those question respondents, 45.2% selected “Debugging AI-generated code is more time-consuming”.

This is the hardest class of defect to catch in review, because plausible code reads as correct. Hardcoded ARIA state is the clearest example: aria-expanded="false" written into JSX that never updates does not fail loudly. It quietly tells a screen reader the opposite of the truth.

The governance gap is real, and it is wide

Checkmarx’s 2026 report release describes a Censuswide survey of 2,350 CISOs, AppSec managers and developers across 14 countries. It reports 75% knowingly shipping vulnerable code, down from 81%, and 22% with formal AI governance policies. These are self-reported survey findings, not a direct audit of every organization’s code.

Veracode’s 2025 GenAI Code Security Report tested over 100 models across Java, JavaScript, Python and C#. About 45% of generated samples failed its security checks; larger or newer models did not reliably improve security in that evaluation. This is a benchmark result, not the vulnerability rate of all production AI code.

Performance should be assessed on the delivered architecture, assets and runtime behavior. This checklist does not establish that AI-authored sites are inherently slower than human-authored sites.

A separate study, Self-Admitted GenAI Usage in Open-Source Software, examined code churn in 151 repositories and found no general increase. Churn is a different outcome from accessibility or security, so this does not negate those studies; each result has its own scope.

The audit itself is mechanical, though. Start where the evidence is strongest.

Pass one: accessibility

Start with accessibility: automated checks can identify some barriers, while keyboard and screen-reader evaluation cover issues those checks miss.

Run the automated layer first

Four tools cover this well, and you do not need all of them.

axe-core (currently 4.13.0, released August 2026) powers a range of accessibility tools. Its rules cover ARIA validity, accessible names, contrast, labels, landmarks, and heading order. Wire it into whichever layer you already test:

// axe-core in an end-to-end test: checks automated rules tagged for WCAG 2.2 A/AA; manual evaluation is still required
import AxeBuilder from '@axe-core/playwright';

const results = await new AxeBuilder({ page })
  .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
  .analyze();

expect(results.violations).toEqual([]);

IBM Equal Access Accessibility Checker is another option. Its release history lists version 4.0.34 in September 2026. Compare its findings on your pages; this article does not benchmark it against axe for landmarks or table headers.

WAVE from WebAIM provides a visual way to show accessibility findings to a non-technical stakeholder.

pa11y-ci gives you a crawl-and-gate workflow:

# Crawl a sitemap and fail CI if more than 10 issues appear
npx pa11y-ci --sitemap https://your-domain.example/sitemap.xml --threshold 10

One scheduling note: axe-core 4.11.1 changed its luminance threshold constant and fixed oklch and oklab contrast handling in January 2026. If you are re-running an old audit, expect contrast results on modern color palettes to shift.

Then add human evaluation beyond automated coverage

Deque’s coverage study used over 2,000 audits, over 13,000 pages and nearly 300,000 issues. It reported about 57% of issues covered by its automated testing. Coverage depends on the pages, issue mix and tools; do not use that percentage as a fixed limit.

Lighthouse's accessibility score makes this worse in a subtle way. It is a weighted average, not a pass rate, and each audit is binary: partially passing scores zero. Critically, Lighthouse's own documentation lists trapped user focus, logical tab order, and keyboard-focusable controls as manual checks, which means the highest-value checks are the ones it explicitly will not score for you.

W3C states the limit plainly: no tool alone can determine whether a site meets accessibility standards, and knowledgeable human evaluation is required.

The manual checks that matter

Start with these three manual checks, then expand to the requirements of your interface.

1. Keyboard operability. Put the mouse away. Tab through the page. Can you reach every interactive element, in a logical order, and see where focus is at all times? This is where div-as-button fails hardest: a styled div with no role, no tabIndex, and no onKeyDown handler passes mouse review and is completely unreachable by keyboard.

2. Screen reader pass. Run one flow, the highest-value one, in NVDA with Firefox or VoiceOver with Safari.

3. Alt text judgment. Automation tells you alt text is missing. Appropriateness needs contextual judgment; a nonempty alt attribute is not proof that the text is useful. W3C's own guidance is explicit that determining whether alternative text is appropriate requires seeing the image and judging it in context.

The five failure patterns to grep for

Look for these patterns in generated components. Prioritize findings by their effect on users; keyboard behavior, focus, semantics, and ARIA state need to work together.

  1. Div-as-button. A div doing a button's job with none of the semantics.

  2. Hardcoded ARIA state. aria-expanded="false" that never updates is worse than no ARIA at all, because it lies.

  3. Broken modal-dialog focus management. No focus moved into the dialog, no trap, no return to the trigger on close.

  4. Native-element reconstruction. Rebuilding button, dialog, or select elements out of divs instead of using the platform primitive.

  5. Design-system stripping. Accessible wiring present on a base component, dropped during composition.

The principle underneath all five: a role without the matching keyboard interaction and state management is worse than no role at all. It promises assistive technology a contract the code does not honor.

Keyboard access is the foundation. Performance is what decides whether anyone stays long enough to use it.

Pass two: performance

Never judge a fix the same day

Field data reflects real-user experience, and its reporting window is slow to turn over. Google uses Core Web Vitals in its ranking systems, but good scores do not guarantee a high ranking. Chrome's CrUX API reports a rolling 28-day collection window, with Core Web Vitals assessed at the 75th percentile, and the data runs approximately two days behind today. Fix a Core Web Vitals problem on Monday and you may see changes as new daily data arrives, but the window still includes earlier visits until they roll out.

This matters because lab and field routinely disagree. PageSpeed Insights shows a lab score from a single throttled simulated load. The pass or fail at the top of the page is field data. A site can score 100 in the lab and fail in the field. In the Web Almanac 2025 dataset, only 48% of mobile and 56% of desktop sites passed Core Web Vitals. Home pages performed worst: 45% mobile, 47% desktop.

INP is the metric to audit. It replaced First Input Delay in March 2024 and observes qualifying click, tap and keyboard interactions across the visit, not just the first. The thresholds are at most 200 ms for good, above 200 through 500 ms for needs improvement, and above 500 ms for poor, measured at the 75th percentile.

Debug it in three phases: input delay, processing duration, and presentation delay. Each has a different fix, so attributing correctly is most of the work. The web-vitals library gives you field attribution:

// Capture INP attribution; reportAllChanges reports updates for debugging.
// Default reporting also considers visibility changes, not only unload.
import { onINP } from 'web-vitals/attribution';

onINP(console.log, { reportAllChanges: true });

Then look for main-thread contention

Two thresholds do most of this work.

Chrome’s forced-reflow insight recommends avoiding forced reflows longer than 30 ms. It happens when JavaScript reads geometry after a style or DOM change has invalidated layout. In a loop, it becomes layout thrashing:

// Interleaved layout reads and writes can force repeated recalculation
for (const box of boxes) {
  box.style.width = box.offsetWidth + 10 + 'px';
}

// Fixed: batch all reads first, then all writes
const widths = Array.from(boxes, (box) => box.offsetWidth);
boxes.forEach((box, i) => { box.style.width = widths[i] + 10 + 'px'; });

Third-party scripts can block the main thread. The legacy Lighthouse third-party-code audit flagged combined main-thread blocking above 250 ms. Its documentation says the audit moved into the Use efficient cache lifetimes insight in Lighthouse 13; check the audit available in your installed version. This criterion does not prove that the whole page fails or that AI authorship caused the scripts. Use DevTools Coverage to inspect unused code.

Reachability and speed handled, the final pass covers what the browser and the screen reader actually parse.

Pass three: semantics and code quality

Validate the rendered DOM, not the template

Include this step in your review: validate the rendered page, not only its source template.

The Nu Html Checker checks HTML conformance and helps identify unintended markup mistakes. The mistake is validating your source template. Anything injected at runtime through innerHTML or after hydration is invisible to that check.

Open the Elements panel, copy the outer HTML of the live page, and validate that. You will catch malformed structure that never appears in your source files.

Layer static analysis and bundle inspection

eslint-plugin-jsx-a11y catches a specific and useful set of issues in JSX: alt-text, anchor-has-content, aria-props, click-events-have-key-events, label-has-associated-control, tabindex-no-positive, and other documented rules. Its documented limitation matters: it only catches errors in static code, which is why it complements rather than replaces the rendered-DOM work above.

For bundles, run webpack-bundle-analyzer or rollup-plugin-visualizer and look for four specific things: the same package resolving to two node_modules paths, a full library imported for one function, CommonJS modules that your build retains unnecessarily, and development-only dependencies leaking into the client bundle.

Then close the loop with the Coverage tab. Low coverage during one recorded flow suggests code to investigate; it does not prove the code is unused in every route or interaction.

Check for token drift

Hardcoded values are the quiet maintainability killer in AI-generated UI, and here is the honest state of the tooling: the relevant source of truth is your own token definition and project rules. Named community tools are unverified, so do this one manually and reliably.

Normalize hex notation without discarding alpha channels, then exact-match against your token file, and sort results into two buckets: values that match a token, and values that match nothing. The second bucket is the finding. Either a token is missing from your design system, or the component has gone off-system. Do not fuzzy-match; you want a clean split, not a similarity score.

For the system-level view of why drift happens, see advanced UI design principles.

Watch for orphaned event listeners

removeEventListener only detaches a listener when the function reference, event type, and capture flag all match. This cleanup uses the same function reference and removes the registered listener:

// In a React component, register and clean up the same function.
useEffect(() => {
  window.addEventListener('resize', handler);
  return () => window.removeEventListener('resize', handler);
}, [handler]);

To detect leaks, take a heap snapshot, mount and unmount the component about ten times, force garbage collection, take a second snapshot, and compare sorted by delta. One caveat worth stating: a resource still alive after unmount is retention evidence, not proof of a leak, because garbage collection is not observable from a page.

With all three passes complete, the only question left is what to do about what you found.

Rescue or rebuild?

Three passes done. Now the decision, which is usually clearer than it feels.

Rebuild when the failure is structural: keyboard operability is absent across the whole app, semantics are unrecoverable, or the layout layer fights the browser. Compare repair and rebuild costs for the actual application; regeneration still needs requirements, testing and review.

Rescue when the failures are localized and enumerable: contrast, missing labels, a handful of hardcoded ARIA states. These are mechanical fixes with an obvious end state, and automated tools can verify their covered checks; finish with the required manual evaluation.

Counting recurring patterns can help estimate repair scope, but one or two versus four or five is not a validated decision threshold. Investigate requirements, prompts, context and implementation before choosing rescue or rebuild.

Conclusion

AI-generated frontend code needs the same production checks as other code. WebAIM's 2026 data shows the web failing accessibility at a rate that got worse for the first time in six years, and Checkmarx reported that 22% of organizations in its 2026 survey had a formal policy governing AI code use.

The fix is not to stop using AI. It is to audit AI-generated frontend code the way you would audit anything else that ships to production. Three passes, in order, with automation covering detectable failures and human evaluation addressing the remaining requirements.

Start with accessibility, combining automated checks with human evaluation. Add performance once the keyboard works. Finish with semantics, validating the rendered DOM rather than the template. Then decide whether you are rescuing or rebuilding, and if it is a rebuild, fix the prompt.

If you take one thing from this: put the mouse away and tab through your last AI-generated page. A short keyboard check can reveal barriers that an automated dashboard misses.

What did the keyboard test catch on your last build? Tell us, or read next on designing agentic UX workflows.

Author

hi3n

hi3n

Keep reading

Related Posts