<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Grant Drew</title>
    <description>The latest articles on DEV Community by Grant Drew (@screevie).</description>
    <link>https://dev.to/screevie</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3982312%2F4988f161-9995-4456-b068-a41d0947fcea.png</url>
      <title>DEV Community: Grant Drew</title>
      <link>https://dev.to/screevie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/screevie"/>
    <language>en</language>
    <item>
      <title>I built a free WCAG scanner because I kept shipping accessibility regressions</title>
      <dc:creator>Grant Drew</dc:creator>
      <pubDate>Sat, 13 Jun 2026 07:17:37 +0000</pubDate>
      <link>https://dev.to/screevie/i-built-a-free-wcag-scanner-because-i-kept-shipping-accessibility-regressions-2goj</link>
      <guid>https://dev.to/screevie/i-built-a-free-wcag-scanner-because-i-kept-shipping-accessibility-regressions-2goj</guid>
      <description>&lt;p&gt;The pattern that pushed me to build this: I'd fix an accessibility issue, ship, and a&lt;br&gt;
few deploys later it would quietly come back. A contrast tweak undone here, a label&lt;br&gt;
dropped there. I never found out until someone told me, and by then it was in production.&lt;/p&gt;

&lt;p&gt;So I built AxeGuard. Paste any public URL, it loads the page in a real headless browser&lt;br&gt;
(Playwright), runs axe-core against it, and gives you the violations grouped by rule with&lt;br&gt;
the WCAG success criterion, the affected elements, and fix guidance for each. Free, no&lt;br&gt;
signup, results in about 30 seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://axeguard.dev" rel="noopener noreferrer"&gt;https://axeguard.dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does and doesn't do
&lt;/h2&gt;

&lt;p&gt;I want to be straight about this, because the accessibility-tool space is full of&lt;br&gt;
overpromising. Automated checks catch a subset of WCAG issues. The figure people usually&lt;br&gt;
cite is somewhere between a third and a half. A scanner can tell you an image has no alt&lt;br&gt;
attribute. It cannot tell you whether "IMG_1234.jpg" is meaningful alt text, or whether&lt;br&gt;
your focus order makes sense, or whether your captions match the audio.&lt;/p&gt;

&lt;p&gt;So AxeGuard never uses the word "compliant." It is not a compliance certificate and it&lt;br&gt;
will not make a demand letter go away. What it does is find the machine-checkable issues&lt;br&gt;
fast, so the human review you still have to do starts from a cleaner baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's built
&lt;/h2&gt;

&lt;p&gt;Nothing exotic. Next.js, axe-core running inside Playwright Chromium, one small Fly.io&lt;br&gt;
machine, SQLite for storage. The part that took the most care was SSRF protection, since&lt;br&gt;
the entire app is "type a URL and we will fetch it." It resolves DNS and rejects private,&lt;br&gt;
loopback, and link-local ranges, strips credentials out of URLs, blocks cloud metadata&lt;br&gt;
endpoints, and re-checks every redirect and subresource the page tries to load. You cannot&lt;br&gt;
point it at internal infrastructure.&lt;/p&gt;

&lt;p&gt;The result page groups findings by rule, sorts critical down to minor, and links each rule&lt;br&gt;
to the Deque docs so you can read the full explanation and the suggested fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it's going
&lt;/h2&gt;

&lt;p&gt;The scanner is the free part. What I am actually testing is whether people want&lt;br&gt;
monitoring: weekly re-scans, an alert when a deploy introduces a new issue, and a CI check&lt;br&gt;
that fails the build on a regression. That is the thing that would have saved me from the&lt;br&gt;
bug-comes-back loop in the first place.&lt;/p&gt;

&lt;p&gt;If that sounds useful, there is an email field on the results page. And if you work in&lt;br&gt;
accessibility and the output gets something wrong, I want to hear it. Tear it apart.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
