npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

astro-link-validator

v1.2.2

Published

An Astro integration that validates links during build time

Readme

🔗 Astro Link Validator

Astro Link Validator Man

Automatically validates links during your Astro build process with security-hardened validation and high-performance concurrent processing.

npm version GitHub GitHub stars GitHub issues

🚀 Quick Start

Step 1: Install from npm

npm install astro-link-validator

Step 2: Add to your Astro config

// astro.config.mjs
import { defineConfig } from 'astro/config';
import linkValidator from 'astro-link-validator';

export default defineConfig({
  integrations: [
    linkValidator()  // ← Add this line
  ],
});

Step 3: Build and check

npm run build  # Link checking runs automatically!

💡 Pro tip: Works with any Astro project - no additional setup required!

🔧 Requirements

  • Node.js 18+
  • Astro 4.0+, 5.0+, 6.0+, or 7.0+

TypeScript Support: Full TypeScript definitions included, but TypeScript is not required to use this integration. Works perfectly with JavaScript-only projects.

✨ Key Features

✅ Path Traversal Protection - Secure validation prevents malicious link attacks
✅ High Performance - Concurrent processing up to 10x faster than sequential
✅ Zero Configuration - Works out of the box with sensible defaults
✅ Beautiful Output - Color-coded error reports with exact locations
✅ CI/CD Ready - Perfect for GitHub Actions and automated builds
✅ TypeScript Support - Full type definitions included
✅ Comprehensive Checking - Internal links, assets, responsive images, and more

✅ Verify Installation

After installing and configuring, verify it's working:

  1. Check your package.json - You should see astro-link-validator listed in dependencies
  2. Run a build - npm run build should show "🔗 Checking links..." in the output
  3. Test with a broken link - Add <a href="/nonexistent">Test</a> to any page and rebuild

You should see something like:

❌ Found 1 broken links:
📄 index.html:
  🔗 /nonexistent
    File not found: nonexistent

📚 Example Output

When you run npm run build, you'll see:

🔗 Checking links...
✅ Checked 23 links across 4 files
🎉 No broken links found!

Or if there are issues:

❌ Found 2 broken links:

📄 about/index.html:
  🔗 /missing-page
    File not found: missing-page
    Text: "Click here"
  📦 /images/logo.png
    File not found: images/logo.png

Build failed: Found 2 broken links

⚙️ Configuration Options

| Option | Type | Default | Description | When to Use | |--------|------|---------|-------------|-------------| | checkExternal | boolean | false | Enable checking of external HTTP(S) links | Production builds, comprehensive testing | | failOnBrokenLinks | boolean | true | Whether to fail the build when broken links are found | CI/CD pipelines, production deploys | | exclude | string[] | [] | Link patterns to skip, matched against the link's href | Skip admin areas, APIs, external CDNs | | include | string[] | ['**/*.html'] | File patterns to check, matched against paths relative to the build directory | Custom build outputs, specific directories | | externalTimeout | number | 5000 | Timeout in milliseconds for external link requests | Slow networks, comprehensive external checking | | verbose | boolean | false | Show detailed logging information | Debugging, development, progress monitoring | | redirectsFile | string | undefined | Path to redirects file (e.g., '_redirects', 'vercel.json') | Netlify/Cloudflare/Vercel deployments with redirects | | base | string | Astro's base config | Base path prefix stripped from root-relative links | Only when calling checkLinks directly — the integration reads it from your Astro config |

Pattern Matching

Both exclude and include accept wildcard patterns where * matches any run of characters, including /:

| Pattern | Matches | |---------|---------| | /admin/* | /admin/users, /admin/settings/advanced (but not /admin itself) | | *.pdf | /docs/manual.pdf, /whitepaper.pdf | | https://analytics.google.com/* | Any URL on that host |

An exclude pattern with no * is matched as a plain substring, so exclude: ['/drafts'] skips every link whose href contains /drafts.

include patterns are matched against each file's path relative to the build directory, using / as the separator on every platform. A leading **/ also matches the root, so the default **/*.html covers both index.html and blog/post/index.html. An include pattern with no * must match the path exactly (e.g. index.html).

🛮️ Usage Examples

Development vs Production

// Development: Fast & forgiving
linkValidator({
  checkExternal: false,
  failOnBrokenLinks: false,
  verbose: true
})

// Production: Comprehensive & strict  
linkValidator({
  checkExternal: true,
  failOnBrokenLinks: true,
  exclude: ['/admin/*', '*.pdf']
})

Complete Configuration (All Options)

// astro.config.mjs - Showing ALL available options
import { defineConfig } from 'astro/config';
import linkChecker from 'astro-link-validator';

export default defineConfig({
  integrations: [
    linkValidator({
      // External link checking
      checkExternal: false,            // Enable/disable external link checking
      externalTimeout: 5000,           // Timeout for external requests (ms)
      
      // Build behavior
      failOnBrokenLinks: true,         // Fail build on broken links
      verbose: false,                  // Show detailed progress
      
      // File inclusion/exclusion
      include: ['**/*.html'],          // File patterns to check
      exclude: [                       // Link patterns to skip
        '/admin/*',                    // Skip admin pages
        '/api/*',                      // Skip API routes
        '*.pdf',                       // Skip PDFs
        'https://analytics.google.com/*' // Skip tracking
      ],
      
      // Advanced options
      redirectsFile: '_redirects'      // Path to redirects file (Netlify/Cloudflare/Vercel)
    })
  ],
});

TypeScript Configuration

// astro.config.mts - With full TypeScript support
import { defineConfig } from 'astro/config';
import linkChecker, { type LinkValidatorOptions } from 'astro-link-validator';

const linkCheckerConfig: LinkValidatorOptions = {
  checkExternal: false,
  verbose: true,
  exclude: ['/admin/*'],
};

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

Sites Deployed to a Subpath (base)

If your astro.config.mjs sets base (e.g. for GitHub Pages), the integration picks it up automatically — no extra configuration needed:

export default defineConfig({
  base: '/docs',
  integrations: [linkValidator()]
});

Astro prefixes generated URLs with the base (/docs/about/) while the output files stay at the root of dist/. The validator strips the prefix before resolving links to files. A root-relative link that omits the prefix (e.g. a hardcoded /about/) is reported as broken, because it would 404 on the deployed site. If such a link is intentional — say it points at another app on the same domain — add it to exclude.

Redirects Support

If your site uses redirects (Netlify, Vercel, Cloudflare Pages, etc.), you can configure the link checker to respect them:

// For Netlify _redirects file
linkValidator({
  redirectsFile: '_redirects'  // Path relative to build directory
})

// For Cloudflare Pages _redirects file (same format as Netlify)
linkValidator({
  redirectsFile: '_redirects'  // Cloudflare Pages uses same format
})

// For Vercel or custom location
linkValidator({
  redirectsFile: '/path/to/redirects.json'  // Absolute path
})

Platform-Specific Examples

Netlify _redirects file:

/old-page /new-page 301
/blog/:slug /posts/:slug 301
/api/* https://api.example.com/v1/* 200
/docs/* /documentation/:splat 301

Cloudflare Pages _redirects file:

# Same format as Netlify
/old-blog/* /blog/:splat 301
/admin /dashboard 302
/api/v1/* https://api.mysite.com/v1/:splat 200

Vercel vercel.json redirects:

{
  "redirects": [
    {
      "source": "/old-page",
      "destination": "/new-page",
      "permanent": true
    }
  ]
}

Note: Currently supports Netlify/Cloudflare _redirects format. Vercel JSON support coming soon.

This prevents false positives when links are redirected rather than broken.

Redirect chains are followed up to 10 hops. If a link exceeds that — because two rules point at each other, or a rule redirects to itself — it's reported as broken with the reason invalid rather than being followed forever.

🚀 CI/CD Integration

Good news: Since link checking runs automatically during npm run build, it works out-of-the-box with all deployment platforms (Netlify, Cloudflare Pages, Vercel, etc.). No special configuration needed! 🎉

🔍 When CI/CD Configuration Matters

1. Build Failure Control

// Development: Don't fail builds on broken links
linkValidator({
  failOnBrokenLinks: false  // Let builds succeed for previews
})

// Production: Fail builds to prevent broken deployments
linkValidator({
  failOnBrokenLinks: true   // Block deployment if links are broken
})

2. Environment-Specific Checking

// Different configs for different environments
linkValidator({
  checkExternal: process.env.NODE_ENV === 'production',
  verbose: process.env.NODE_ENV === 'development',
  exclude: process.env.NODE_ENV === 'production' 
    ? ['/admin/*', '/drafts/*']  // Production: exclude more
    : ['/admin/*']               // Development: minimal exclusions
})

3. Pull Request vs Main Branch

# GitHub Actions example for different branch behavior
- name: Build with link checking
  run: npm run build
  env:
    # Strict checking on main, lenient on PRs
    LINK_CHECK_MODE: ${{ github.ref == 'refs/heads/main' && 'strict' || 'lenient' }}

4. Large Site Optimization

// Skip external links in CI for speed, but check locally
linkValidator({
  checkExternal: !process.env.CI,  // Only check external links locally
  verbose: !!process.env.CI        // Verbose in CI for debugging
})

🔍 What Gets Checked

✅ Checked

  • Internal page links: /about, ./contact.html, ../index.html
  • Asset references: /images/logo.png, /styles.css, /script.js
  • External links (when enabled): https://example.com
  • Responsive images: All URLs in srcset attributes
  • Multiple elements: <a>, <img>, <script>, <link>, <iframe>, etc.

❌ Skipped

  • JavaScript URLs: javascript:void(0)
  • Email/phone links: mailto:, tel:
  • Data URLs: data:image/png;base64,...
  • Blob URLs: blob:https://example.com/...

🆘 Troubleshooting

🔧 Installation Issues

  • Build failures during install? Check you have Node.js 18+ and npm/yarn latest version

🔍 Link Checking Issues

  • Too many false positives? Add URLs to exclude array
  • Build too slow? Set checkExternal: false
  • Want more details? Set verbose: true
  • Path traversal errors? This is a security feature - check your links for ../ patterns
  • CI/CD failing? Ensure the build directory exists before link checking runs

💻 Programmatic Usage

import { checkLinks } from 'astro-link-validator';

const result = await checkLinks('./dist', {
  checkExternal: true,
  verbose: true
});

console.log(`Found ${result.brokenLinks.length} broken links`);

🔄 Updating

To get the latest version:

npm update astro-link-validator

🏗️ How It Works

  1. Build Hook: Uses Astro's astro:build:done hook to run after your site is built
  2. HTML Parsing: Scans all HTML files in the output directory using Cheerio
  3. Link Extraction: Finds all href and src attributes from relevant HTML elements
  4. Validation: Checks internal links against the file system and optionally validates external links via HTTP requests
  5. Reporting: Provides detailed, colored output showing exactly which links are broken and why

📝 License

MIT License - see the LICENSE file for details.


Made with ❤️ for the Astro community