# Add Broken Link Checking to Astro Framework with Astro Link Validator

'https://travismedia.gumlet.io/src/assets/images/2025/09/astro-broken-link-validator-thumb.jpg';

<Image src={validatorMan} alt="superhero flexing muscles representing broken links" />

When building static sites with the [**Astro framework**](https://astro.build/), 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**](https://github.com/rodgtr1/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:

1. **Build Hook Integration** – Runs after the site is built using `astro:build:done`
2. **HTML Parsing** – Scans all `.html` files in the `dist/` output
3. **Link Extraction** – Finds `href`, `src`, and `srcset` attributes
4. **Validation** – Confirms internal links exist, optionally checks external URLs with HTTP requests
5. **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:

```bash
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:

```bash
npm uninstall astro-link-validator
npm install github:rodgtr1/astro-link-validator
```

### Configuration

Add it to your Astro config:

{/* prettier-ignore */}
```js
// astro.config.mjs


export default defineConfig({
  integrations: [
    linkValidator()
  ],
});
```

### Usage

Run your normal build:

```bash
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**:

```html
<a href="/about">About</a>
<a href="./contact.html">Contact</a>
<a href="#section-1">Jump</a>
```

**Assets**:

```html
<img src="/images/hero.jpg" />
<link rel="stylesheet" href="/styles/main.css" />
<script src="/js/app.js"></script>
```

**Responsive images**:

```html
<img src="small.jpg" srcset="medium.jpg 768w, large.jpg 1024w" />
```

**External links** (optional):

```html
<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

```js
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):

```js
// 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):**

```js
linkValidator({
  checkExternal: false,
  failOnBrokenLinks: false,
  verbose: true,
});
```

**Production (strict checks):**

```js
linkValidator({
  checkExternal: true,
  failOnBrokenLinks: true,
  exclude: ['/admin/*', '/drafts/*'],
});
```

**With redirects (Netlify/Cloudflare Pages):**

```js
linkValidator({
  redirectsFile: '_redirects', // Both Netlify and Cloudflare Pages use this format
});
```

## Output Example

When everything is fine:

```bash
🔗 Validating links...
✅ Checked 47 links across 12 files
🎉 No broken links found!
```

With issues:

```bash
❌ 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

```js
linkValidator({
  checkExternal: true,
  externalTimeout: 10000,
  failOnBrokenLinks: true,
  verbose: false,
  include: ['**/*.html'],
  exclude: ['/admin/*', '/api/*', '*.pdf'],
  base: 'https://mysite.com',
  redirectsFile: '_redirects',
});
```

## TypeScript Support

```ts


const config: LinkValidatorOptions = {
  checkExternal: false,
  verbose: true,
};

export default defineConfig({
  integrations: [linkValidator(config)],
});
```

## Programmatic Usage

```js


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:

```bash
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:

1. **Hooking into the build process** using Astro's integration API
2. **Parsing generated HTML files** to extract all links
3. **Validating internal links** against the filesystem with intelligent fallbacks
4. **Optionally checking external links** via HTTP requests
5. **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](https://github.com/rodgtr1/astro-link-validator)
- **Issues / Feature Requests**: [GitHub Issues](https://github.com/rodgtr1/astro-link-validator/issues)
- **Astro Integration Docs**: [Astro Integrations Guide](https://docs.astro.build/en/guides/integrations-guide/)

The integration is released under the MIT license and is free to use in both personal and commercial projects.