What Is QA Testing?
(And How I Added It to Stackless)
When developers finish building something, they don't just ship it and hope for the best. They run tests first. These tests catch broken links, missing pages, features that stopped working, and a dozen other things you'd only notice if you checked every page manually.
This process is called QA — Quality Assurance. It sounds corporate and technical, but the idea is simple: before real users see your work, make a machine check it for you.
I built Stackless without writing code. But that doesn't mean I get to skip QA. Every time Claude edits a file and I push to GitHub, something could break. A link pointing to the wrong place. A page that loads a missing stylesheet. A nav link someone might click and hit a 404.
So I added automated QA to Stackless. Here's what I learned.
What is QA, in plain English?
QA (Quality Assurance) is the process of checking that something works as expected before releasing it to users. In web development, QA usually means running automated scripts that visit every page and flag anything broken — dead links, missing images, pages that don't exist. Think of it as a robot that clicks around your site so you don't have to.
Why QA Matters More When You're Not a Developer
If you write code yourself, you often catch bugs as you go. You're reading the code, you understand what changed, you notice when something looks off.
When AI writes your code, you're working at a higher level. You describe what you want, review the output, and ship it. That's the whole point — it's faster. But it also means you might not notice if an old link breaks, or if a nav item now points to a page that was renamed two commits ago.
I ran into exactly this. A blog post referenced a tutorial that had been moved. The link in the post still pointed to the old path. Nobody clicked it, so nobody noticed. It just sat there, broken, for a week.
QA is the safety net that catches the things you'd only find if a user reported a bug.
The Two Main Approaches
There are two tools people usually reach for when automating web QA:
Link Checkers
These crawl your site and check that every URL actually exists and returns a valid response. Fast, simple, lightweight. They won't tell you if your site looks wrong, but they'll tell you if something is missing or points nowhere. Good for static sites like Stackless.
Browser Automation (Playwright, Cypress)
These tools open a real browser and simulate user behaviour — clicking buttons, filling forms, navigating between pages. Much more powerful, but also more complex to set up and maintain. Better suited to apps with user logins, shopping carts, or interactive features.
For Stackless — a static HTML site with no backend — a link checker is the right tool. It'll catch 90% of what could go wrong, with almost no setup.
Behind the Build: Adding a Link Checker to Stackless
Behind the Build
This section walks through the actual decisions I made and prompts I used. You can follow along and do the same for your own site.
The tool I used is called lychee — a fast, open-source link checker that runs on the command line. Claude walked me through the whole setup. Here's how it went.
Step 1: Choose Your Checker
I asked Claude: "What's the simplest way to run automated link checking on a static HTML site? I don't want to install anything complicated." The recommendation was lychee — free, fast, works on Windows, and gives clear output.
Other options exist (Broken Link Checker as a Node package, or even just running your site through an online checker) but lychee integrates cleanly with GitHub Actions, which meant I could automate it to run every time I push a change.
Step 2: Install and Run Locally
On Windows, the easiest way to install lychee is via winget (Windows Package Manager). Claude gave me this command to paste into a terminal:
Once installed, I ran it against the Stackless folder:
This tells lychee to check every HTML file in the site folder. It crawls through them, finds every link, and checks whether each one resolves. The output looks something like this:
✅ 831 links OK
⚠️ 3 redirects
❌ 13 errors
Thirteen errors. That's thirteen links that would have given a user a broken experience. I had no idea.
Step 3: Read the Report
The output includes a table of broken links with their source file and the error type. Here's a simplified version of what I saw:
| File | Broken Link | Status |
|---|---|---|
| blog/post-7.html | ../shop/index.html#dashboards | 404 |
| about.html | projects.html#curlmagic | 404 |
| index.html | blog/post-5.html | OK |
Most of the errors were anchor links — links that point to a specific section within a page using a # symbol. When those sections get renamed or removed, the link still looks valid but lands nowhere. Lychee catches these too.
Step 4: Automate It with GitHub Actions
Running a check manually is useful, but the real value is having it run automatically every time you push a change. GitHub Actions lets you do this for free.
I asked Claude to write a GitHub Actions workflow file. The result was a file I saved at .github/workflows/link-check.yml:
on:
push:
branches: [master]
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am
jobs:
link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check links
uses: lycheeverse/lychee-action@v2
with:
args: --no-progress './stackless-site/**/*.html'
fail: true
Now, every time I push to GitHub — which happens after every session — the link checker runs automatically. If it finds errors, it flags the commit as failed, and I get a notification. The site still deploys (Render doesn't know about the check), but I know something needs fixing.
The schedule line also sets it to run every Monday morning, so even if nothing changed in my code, it'll catch any external links that have gone stale.
One gotcha: External links (links to other websites) sometimes fail the checker for reasons that aren't actually broken — some sites block automated crawlers and return a 403 error. You can tell lychee to skip specific domains or only check internal links. I configured mine to ignore a few known noisy domains.
Step 5: Fix What It Finds
The workflow I've now settled into:
- Claude makes changes, we commit and push.
- GitHub Actions runs the link check automatically.
- If the check passes, the commit gets a green tick.
- If it fails, I get a notification with the report. I ask Claude to fix the broken links and push again.
The whole thing takes about 90 seconds to run. I don't have to think about it. It just runs.
What QA Doesn't Catch
A link checker is powerful but narrow. It only checks links. It won't tell you:
- Whether a page looks broken in dark mode
- Whether a button doesn't do anything when clicked
- Whether text is readable at different screen sizes
- Whether your email form actually sends emails
For those things, you'd need browser automation tools like Playwright, or you'd need to check manually. For a site like Stackless, I've decided the link checker covers the most important risks, and I do a quick visual check whenever I make significant layout changes.
That split — automated for the things that are quick to check automatically, manual for everything else — is how most small teams handle QA too.
The Bigger Lesson
QA isn't about catching every possible bug before anyone sees your site. That's impossible. It's about reducing the most common, embarrassing, user-facing failures — broken links, missing pages, stuff that makes your site look unmaintained — so they don't reach real visitors.
Adding a link checker took me about 30 minutes. It will save me from looking unprofessional every single week for as long as the site exists.
If you're shipping anything to the public — a blog, a portfolio, a tool — it's worth setting up. Even a simple online link checker (no install needed) is better than nothing.
Want to try it?
You can run a free online link check at deadlinkchecker.com or validator.w3.org/checklink — no setup required. Paste your URL and see what comes back. If you want automated checks on every push, ask your AI assistant to help you set up a GitHub Actions workflow like the one in this post.
More from Stackless