Table of Contents
Add Broken Link Checking to Astro Framework with Astro Link Validator
· Travis Rodgers · 6 min read

When building static sites with the Astro framework, broken links are a common issue that can slip into production. Files get moved, URLs change during refactoring, or assets are reorganized. While you could manually click through every page, there’s a better way.
I recently built Astro Link Validator, an Astro integration that automatically validates links during the build process. Let’s look at how it works and why it can be valuable for your Astro projects.
The Challenge: Why Links Break in Astro Framework Projects
Broken links are particularly common in Astro sites due to how static site generation works:
- File Structure Changes – Moving pages in
/src/pages
changes generated URLs, but internal links may not get updated - Asset Path Issues – Images or styles referenced from different directory levels can break when output paths differ
- Build-Time Transformations – Astro’s build can change how URLs resolve (trailing slashes, base paths, etc.)
- Environment Differences – Links that work locally may break in production due to base URLs or deployment configs
Manually testing every link doesn’t scale, especially for content-heavy sites. Automation is the safer option.
Solution: Automated Link Validation with Astro Link Validator
Astro Link Validator hooks into the Astro build process and automatically validates all links in your generated HTML files. Here’s what it does:
- Build Hook Integration – Runs after the site is built using
astro:build:done
- HTML Parsing – Scans all
.html
files in thedist/
output - Link Extraction – Finds
href
,src
, andsrcset
attributes - Validation – Confirms internal links exist, optionally checks external URLs with HTTP requests
- Reporting – Outputs a detailed report showing which links are broken and why
Why This Approach Works
- ✅ Build-Time Validation: Issues are caught before deployment
- ✅ Zero Configuration: Works with sensible defaults out of the box
- ✅ Comprehensive: Handles pages, assets, images, and
srcset
URLs - ✅ Security-Aware: Includes path traversal protection
- ✅ Performance Optimized: Uses concurrent checks for speed
How to Add Astro Link Validator to Your Project
Installation
Since the integration isn’t published to npm yet, install directly from GitHub:
npm install github:rodgtr1/astro-link-validator
Important Notes:
- No Build Required: Prebuilt JavaScript files included — works immediately after installation
- TypeScript Support: Full type definitions included, but TypeScript is not required
- Updates: To update to a newer version, uninstall and reinstall:
npm uninstall astro-link-validator
npm install github:rodgtr1/astro-link-validator
Configuration
Add it to your Astro config:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import linkValidator from 'astro-link-validator';
export default defineConfig({
integrations: [
linkValidator()
],
});
Usage
Run your normal build:
npm run build
If broken links exist, the build fails and outputs details.
Link Detection and Validation Process
Astro Link Validator uses Cheerio (server-side jQuery) to parse HTML and extract links.
Checked Elements
Navigation links:
<a href="/about">About</a>
<a href="./contact.html">Contact</a>
<a href="#section-1">Jump</a>
Assets:
<img src="/images/hero.jpg" />
<link rel="stylesheet" href="/styles/main.css" />
<script src="/js/app.js"></script>
Responsive images:
<img src="small.jpg" srcset="medium.jpg 768w, large.jpg 1024w" />
External links (optional):
<a href="https://github.com/user/repo">GitHub</a> <link href="https://fonts.googleapis.com/css" />
Validation Rules
- Internal Links: Checked against filesystem with fallbacks (
.html
,index.html
, relative resolution) - External Links: HTTP HEAD requests (configurable, disabled by default for speed)
Skipped URLs
mailto:
tel:
javascript:
data:
/blob:
External Link Checking Performance
External link validation requires network requests and can significantly slow build times. Here’s the recommended approach:
For Regular Development
linkValidator({
checkExternal: false, // Skip external links for fast builds
});
For Periodic Validation
Run external link checking 1-2 times per month (or more frequently for sites with many external references):
// Run this configuration locally on a schedule
linkValidator({
checkExternal: true,
externalTimeout: 8000, // Allow more time for external requests
verbose: true, // See progress during long checks
});
Build Time Impact
- Without external checking: Builds complete in seconds
- With external checking: Can add minutes to build time depending on number of external links
- Recommendation: External checking frequency depends on your publishing schedule and external link volatility
Example Configurations
Development (fast feedback):
linkValidator({
checkExternal: false,
failOnBrokenLinks: false,
verbose: true,
});
Production (strict checks):
linkValidator({
checkExternal: true,
failOnBrokenLinks: true,
exclude: ['/admin/*', '/drafts/*'],
});
With redirects (Netlify/Cloudflare Pages):
linkValidator({
redirectsFile: '_redirects', // Both Netlify and Cloudflare Pages use this format
});
Output Example
When everything is fine:
🔗 Validating links...
✅ Checked 47 links across 12 files
🎉 No broken links found!
With issues:
❌ Found 3 broken links:
📄 blog/astro-tips.html:
🔗 /missing-page → File not found
📦 /images/missing.jpg → Asset not found
📄 about/index.html:
🔗 https://dead-link.example.com → 404 Not Found
Configuration Reference
linkValidator({
checkExternal: true,
externalTimeout: 10000,
failOnBrokenLinks: true,
verbose: false,
include: ['**/*.html'],
exclude: ['/admin/*', '/api/*', '*.pdf'],
base: 'https://mysite.com',
redirectsFile: '_redirects',
});
TypeScript Support
import linkValidator, { type LinkValidatorOptions } from 'astro-link-validator';
const config: LinkValidatorOptions = {
checkExternal: false,
verbose: true,
};
export default defineConfig({
integrations: [linkValidator(config)],
});
Programmatic Usage
import { checkLinks } from 'astro-link-validator';
const result = await checkLinks('./dist', {
checkExternal: true,
verbose: true,
});
console.log(`Broken links: ${result.brokenLinks.length}`);
GitHub Distribution Approach
Why Install from GitHub?
Currently, this integration is distributed directly from GitHub rather than npm. This approach has some implications:
Committed Build Files: The repository includes a dist/
folder with pre-built JavaScript and TypeScript definitions. This is uncommon for npm packages but necessary for GitHub installations to work without requiring users to build the package themselves.
Update Process: When updating to newer versions, npm may not always properly update GitHub-installed packages. If you encounter issues after an update, try:
npm uninstall astro-link-validator
npm install github:rodgtr1/astro-link-validator
Redirect Support Examples
The validator supports the _redirects
format used by both Netlify and Cloudflare Pages:
Netlify/Cloudflare Pages _redirects
file:
/old-page /new-page 301
/blog/:slug /posts/:slug 301
/api/* https://api.example.com/v1/* 200
/docs/* /documentation/:splat 301
This prevents false positives when links are redirected rather than actually broken.
Future Plans: Eventually, this integration will be published to npm, which will provide a cleaner update experience and remove the need for committed build files.
Security & Performance
- 🔒 Path Traversal Protection
- 🔒 URL Validation
- 🚀 Concurrent checks
- 🚀 Skip duplicate URLs
- 🚀 Configurable timeouts
Limitations and Future Improvements
Current Limitations
- External Link Checking: Disabled by default due to significant performance impact. Each external URL requires a network request, which can add substantial time to builds. For sites with many external links, enabling this can increase build times from seconds to minutes.
- Redirect Support: Currently supports Netlify/Cloudflare Pages
_redirects
format only (Vercel JSON format not yet supported) - Hash Links: Basic validation only - doesn’t verify that target elements exist
- JavaScript-Generated Links: Can’t validate links created dynamically by JavaScript
When to Use Astro Link Validator
- Medium to large Astro sites where manual link checking isn’t practical
- Content-heavy sites with frequent updates and reorganization
- CI/CD environments where you want to catch broken links before deployment
- Team environments where multiple people contribute content
Summary
The astro-link-validator
integration provides automated link validation for Astro sites by:
- Hooking into the build process using Astro’s integration API
- Parsing generated HTML files to extract all links
- Validating internal links against the filesystem with intelligent fallbacks
- Optionally checking external links via HTTP requests
- Reporting detailed errors that help you locate and fix broken links
Key Benefits:
- Zero configuration required for basic usage
- Build-time validation catches issues before deployment
- Security-hardened with path traversal protection
- Performance optimized with concurrent processing
- Full TypeScript support (but TypeScript not required)
Resources
- Source Code: GitHub Repository
- Issues / Feature Requests: GitHub Issues
- Astro Integration Docs: Astro Integrations Guide
The integration is released under the MIT license and is free to use in both personal and commercial projects.
This page may contain affiliate links. Please see my affiliate disclaimer for more info.