
How I Made CeHDI WCAG Compliant: The Real Fixes Behind EAA and ADA
Published: April 27, 2026
I took over CeHDI.org from a developer who could not finish the project. CeHDI is The Global Center for Health Diplomacy and Inclusion, a policy and research organisation working on global access to healthcare, with a strong focus on Africa. Their entire reason for existing is to make sure healthcare reaches the people it currently does not. Shipping a website that locks out users with disabilities is the exact opposite of that. The site I inherited did exactly that.
This was not a "WCAG nice to have" job. Under the European Accessibility Act, enforceable since June 28, 2025, any business serving EU consumers carries real legal exposure. Under US ADA Title III lawsuits and the DOJ Title II Final Rule with its April 24, 2026 deadline for state and local entities serving 50,000 or more people, the same applies stateside. CeHDI works internationally, so both apply at once.
What follows is the actual list of what was wrong on the site I inherited, the fixes I shipped, and the specific WCAG success criteria each fix maps to. The work was the boring, unsexy semantic HTML kind. The kind 95.9% of the web never bothers with.
What I Inherited
The first pass through the codebase was depressing in a familiar way. Nothing was malicious. Nothing was exotic. It was the standard output of "ship fast, do not think about HTML." If you have ever inherited a Next.js project from a developer who shipped on visuals alone, you already know this list.
Semantic HTML was missing across the site. Headings were styled <div> blocks. Paragraphs were unstyled <div> containers. Links were <span> with click handlers. A screen reader user landing on the home page heard no structure, no landmarks and no headings. Just a wall of unlabelled text.
The <main> tag was placed incorrectly. It was nested inside other landmark regions instead of sitting at the top level as the single primary landmark. The "skip to main content" pattern, the one keyboard and screen reader users rely on to bypass site chrome, depends on <main> being where the spec says it should be.
The heading tree was broken. Multiple <h1> elements per page, <h3> followed directly by <h5>, sections without headings at all. Visually the page looked fine. To anyone navigating by headings, which is the primary way screen reader users scan a page, the document was incoherent.
Buttons were <div> with onClick. This is the single most common pattern I see on rescue projects. A <div onclick="..."> is invisible to keyboard users, invisible to screen readers as a button, has no :focus state and no Enter or Space activation. It also breaks every assistive tech pattern that expects a real button role.
Links were <div> with onClick instead of <a href>. This breaks browser features everyone takes for granted. Open in new tab, copy link, middle-click, prefetch, browser history, the screen reader link rotor. All gone the moment you swap a real link for a div with a handler.
No keyboard navigation through the main menu. Tab order skipped items. Focus indicators were styled away. The mobile menu had no focus trap, so opening it sent focus into the page behind the overlay. Users on a keyboard could not navigate the site without falling out of the visible area.
No accessible names for screen-reader-only context. Icon-only buttons had no aria-label. Decorative images were not marked decorative. Real content images had no alt.
The previous build was not built badly on purpose. It was built to look right on a Macbook screen on the developer's desk. Everything beyond that surface was missing.
Why CeHDI Specifically Could Not Ship This
CeHDI works on global access to healthcare. They run research and policy work on health equity, with a particular focus on regions where access is hardest to come by, especially across the African continent. They engage with international institutions, governments and NGOs across the EU, the US and beyond.
That makes the inaccessibility problem more than a compliance issue. An organisation whose entire research focus is access cannot credibly publish a site that locks out screen-reader users, keyboard-only users and users with motor disabilities. The mismatch between message and product is the kind of thing a journalist, a partner or a procurement reviewer notices in thirty seconds.
This is the part most agencies skip when they pitch accessibility. The "why now" is not just legal. It is positioning. An access-focused organisation needs an accessible product. CeHDI could not credibly do its work on the surface I inherited.
The Three Legal Frameworks This Fix Had to Pass
CeHDI operates across both jurisdictions, so the rebuild had to pass three overlapping bars.
EU: the European Accessibility Act, Directive 2019/882. The EAA has been enforceable since June 28, 2025. It applies to private businesses selling goods or services to EU consumers, with limited exemptions. The technical baseline is EN 301 549, which references WCAG 2.1 AA. Penalties vary by member state and real fines are already in effect. If you want the financial picture, I covered that in The €1M Risk: Real-World EAA Penalties in 2026.
US: the Americans with Disabilities Act, Title III plus the DOJ Title II Final Rule. ADA Title III has been used to sue private-sector websites for years, with 3,948 web accessibility lawsuits filed in 2025, a 23.84% increase over 2024. The DOJ Title II Final Rule sets a hard compliance date of April 24, 2026 for state and local government entities serving 50,000 or more people, requiring WCAG 2.1 AA. The DOJ has also stated explicitly that accessibility overlays do not ensure compliance.
WCAG itself, the standard both laws point at. The EAA points at EN 301 549, which points at WCAG 2.1 AA. ADA enforcement settlements consistently reference WCAG 2.1 AA. UK PSBAR, Canadian AODA and Australian DDA all converge on the same baseline. If you wonder why I framed this as one fix instead of three, that is why. Fix the HTML once, you cover the whole stack.
If the broader market context is useful, I wrote about it here: WCAG in the EU (2026): Why Waiting Is Now the Most Expensive Accessibility Strategy.
What I Fixed, Mapped to WCAG Criteria
Every fix below pairs with the specific WCAG success criterion it satisfies. This is the section that separates real audit work from agency-speak.
Restored semantic HTML across the site. <h1> through <h6> for headings, <p> for paragraphs, <a href> for links, <button> for buttons, <nav> for navigation, <main> for the primary content region, <footer> for the footer, <section> and <article> where they actually applied.
- WCAG 1.3.1 Info and Relationships (Level A)
- WCAG 4.1.2 Name, Role, Value (Level A)
Moved <main> to its correct position as the single, top-level primary landmark. Removed the nested wrappers that broke the landmark tree. Added a working "skip to main content" link as the first focusable element.
- WCAG 2.4.1 Bypass Blocks (Level A)
- WCAG 1.3.1 Info and Relationships (Level A)
Rebuilt the heading tree. A single <h1> per page representing the page topic. <h2> for section titles. <h3> for sub-sections. No skipped levels. Where a section needed a label that was not visually a heading, it received an aria-labelledby reference rather than a fake heading element.
- WCAG 2.4.6 Headings and Labels (Level AA)
- WCAG 1.3.1 Info and Relationships (Level A)
Replaced every <div onClick> button with a real <button>. Or with <a href> when the action was actually navigation, not a state change. Buttons regained native keyboard activation through Enter and Space, native focus rings (which I then visually styled rather than removed) and screen reader announcement as "button."
- WCAG 2.1.1 Keyboard (Level A)
- WCAG 4.1.2 Name, Role, Value (Level A)
- WCAG 2.4.7 Focus Visible (Level AA)
Replaced every <div onClick> link with a real <a href>. Open in new tab, copy link, middle-click, prefetch, screen reader link rotor and browser history all came back the moment the right primitive was in place.
- WCAG 2.1.1 Keyboard (Level A)
- WCAG 4.1.2 Name, Role, Value (Level A)
Built keyboard navigation through the main menu. Logical tab order across the header, visible :focus-visible styles on every interactive element, a real focus trap on the mobile menu so focus stays inside the open dialog, focus return to the trigger when the menu closes, Esc closes overlays.
- WCAG 2.1.1 Keyboard (Level A)
- WCAG 2.1.2 No Keyboard Trap (Level A)
- WCAG 2.4.3 Focus Order (Level A)
- WCAG 2.4.7 Focus Visible (Level AA)
Added accessible names to icon-only buttons through aria-label. Marked decorative images with alt="" so screen readers skip them. Real content images received descriptive alt text reflecting what the image actually communicated.
- WCAG 1.1.1 Non-text Content (Level A)
Set lang on <html>. A trivial fix that fails on a surprising number of sites. Without it, screen readers do not know which pronunciation engine to load.
- WCAG 3.1.1 Language of Page (Level A)
The pattern hiding underneath all of this: 90% of compliance is just writing HTML the way the spec was written.
The Code Pattern That Does Most of the Work
If you want to take one thing from this post into your own codebase, this is it.
The wrong pattern, repeated across most rescue projects:
<div className="btn" onClick={handleClick}>
Read more
</div>That one line of code violates at least three WCAG success criteria. It is not keyboard reachable. It is not announced to screen readers as a button or a link. It has no native focus state.
The right pattern, depending on intent:
If the element navigates somewhere, it is a link.
<Link href="/article">Read more</Link>If the element triggers an in-page action or state change, it is a button.
<button type="button" onClick={handleClick}>
Read more
</button>A few rules I apply on every rescue:
- Never remove the default focus ring without replacing it. Use
:focus-visibleto style focus on keyboard navigation only, not for mouse clicks. Removing the ring entirely is one of the most common WCAG 2.4.7 violations. role="button"on a<div>is not the fix. It is the AI-generated escape hatch. It tells the screen reader the element is a button but does not give the element keyboard handling, focus management orEnterandSpaceactivation. You then have to wire all of that manually. At which point you should have used<button>.- If the visual design wants a link to look like a button, that is a CSS problem. Do not change the HTML to match the look. Change the CSS to match the HTML.
What Changed After the Fix
The site now passes automated audits cleanly. Lighthouse, axe DevTools and WAVE all run green on the structural criteria. Useful as a baseline. Not useful as the end of the audit, because automated tools catch only 30 to 40% of real issues.
The manual screen-reader pass tells the real story. Full keyboard navigation works end to end. Landmarks announce. Headings announce in a tree that matches the visual hierarchy. The mobile menu opens, traps focus, closes on Esc and returns focus to the menu trigger.
There was a useful side effect on SEO. Semantic HTML, a correct heading tree and real <a href> links made the site more crawlable. Search engines parse the same HTML structure assistive tech does. When you fix one, you fix the other.
On the legal side, CeHDI now has a defensible site under EAA and ADA enforcement, not a target one. I am not claiming "100% WCAG 2.1 AA forever," because that requires ongoing manual audits on every release plus discipline on the content side, alt text on every CMS-uploaded image and no skipped headings in editor-authored articles. What I shipped is the structural baseline that makes the site auditable and closes the lawsuit-bait failures.
Why This Matters to Anyone Inheriting a Project
The pattern I described, divs as buttons, missing main, broken headings, no keyboard nav and no accessible names, is what most rescue projects look like. It is also what most "vibe coded" Next.js projects look like. Code that renders on the screen but skips the HTML semantics underneath.
The fix is rarely a rewrite. It is a structural pass. Open every interactive component, replace the wrong primitive with the right one, audit the heading tree, restore the landmark structure, wire focus management. A senior dev can do this in days, not months. Most agencies will quote you a rebuild because the rebuild is what their team is comfortable selling. It is almost always overkill.
If your previous developer left you with a site that "works visually" but you have no idea whether it is keyboard-navigable, screen-reader-accessible or EAA and ADA defensible, that is the problem I solve.
Conclusion
CeHDI inherited a site that violated the basics. Missing semantic HTML. Misplaced <main>. A broken heading tree. <div onClick> everywhere instead of <button> and <a href>. No keyboard navigation. No accessible names.
I rebuilt the structural layer to map cleanly to WCAG 2.1 AA, the same baseline EAA and US ADA enforcement converge on. There is no separate "EU build" and no separate "US build." Fix the HTML once and you cover both jurisdictions.
95.9% of the web fails this. The fix is not exotic. It is discipline.
Work With Me
Need a real WCAG audit? I run paid WCAG audits that map findings directly to specific success criteria and to the EAA plus ADA frameworks. Same process I ran on CeHDI. If you are selling into the EU or the US and your site shows any of the failures listed above, get in touch to scope an audit.
Inherited a broken Next.js project? I take over and rescue Next.js projects that previous developers could not finish. CMS integration, SSR, SEO, accessibility, the whole structural pass. Book a 30-minute assessment and I will tell you whether your project needs a rescue or a rebuild.
Sources
- WebAIM Million 2026, 95.9% home page failure rate: https://webaim.org/projects/million/
- European Accessibility Act, Directive 2019/882: https://eur-lex.europa.eu/eli/dir/2019/882/oj/eng
- EN 301 549, EAA technical baseline: https://www.etsi.org/standards
- US DOJ ADA Title II Final Rule, April 2024: https://www.ada.gov/resources/2024-03-08-web-rule/
- ADA web accessibility lawsuit statistics 2025, 3,948 cases, +23.84% YoY: https://wcagsafe.com/blog/ada-lawsuit-statistics
- WCAG 2.1 specification: https://www.w3.org/TR/WCAG21/
- WAI WCAG quick reference, success criteria index: https://www.w3.org/WAI/WCAG21/quickref/
- CeHDI live site: https://www.cehdi.org/