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

vercel-seo-audit

v2.4.0

Published

CLI tool that diagnoses SEO and indexing issues for Next.js/Vercel websites

Readme

vercel-seo-audit

npm version npm downloads CI licence

If you're using Vercel and Google hates your site, this is for you.

A fast, developer-friendly CLI that explains why Google isn't indexing your Next.js site — beyond the vague stuff in Search Console. It detects the misconfigs that silently kill crawling and indexing: redirect traps (308), missing robots/sitemap, noindex headers, canonical mismatches, and Vercel/Next.js quirks.


Quick start

npx vercel-seo-audit https://your-site.com

Install globally (optional):

npm i -g vercel-seo-audit
vercel-seo-audit https://your-site.com

Example output

SEO Audit Report for https://example.com/
  Completed in 1118ms at 2026-01-31T12:30:54.448Z

  Summary:
    ✖ 1 error
    ⚠ 3 warnings
    ℹ 2 info
    ✔ 4 passed

  REDIRECTS
  ────────────────────────────────────────
  ✖ [ERROR] Redirect chain detected (3 hops)
    → Reduce to a single redirect: http://example.com → https://example.com/

  ROBOTS
  ────────────────────────────────────────
  ⚠ [WARNING] robots.txt not found
    → Create a robots.txt at /robots.txt

  SITEMAP
  ────────────────────────────────────────
  ⚠ [WARNING] sitemap.xml not found
    → Add app/sitemap.ts in Next.js App Router

  METADATA
  ────────────────────────────────────────
  ⚠ [WARNING] Canonical URL mismatch
    → Canonical points to https://www.example.com/ but page is https://example.com/
  ✔ [PASS] Title tag present
  ✔ [PASS] Meta description present

Common pitfalls we catch

These are the issues that silently tank your rankings on Next.js/Vercel:

  • Next.js 308 trailing-slash trapstrailingSlash: true creates 308 redirect loops that waste crawl budget and confuse Google.
  • www / non-www domain redirects — serving the same content on both domains without a redirect splits link equity and causes duplicate-content issues.
  • Middleware rewrites & redirects affecting crawlers — Next.js middleware can rewrite or redirect in ways that only affect bots, breaking indexing without any visible symptoms in a browser.
  • Canonical mismatch — the <link rel="canonical"> points to a different URL than the page actually lives at, telling Google to ignore the page.
  • Sitemap / robots issues — missing sitemap.xml, empty sitemaps, robots.txt blocking Googlebot, or Sitemap: directive pointing to the wrong URL.

Usage

# Basic audit
vercel-seo-audit https://your-site.com

# JSON output (pipe to jq, save to file, feed to CI)
vercel-seo-audit https://your-site.com --json

# Verbose mode — raw HTTP details for each finding
vercel-seo-audit https://your-site.com --verbose

# Custom timeout (default: 10s)
vercel-seo-audit https://your-site.com --timeout 15000

# Check specific pages for redirect issues
vercel-seo-audit https://your-site.com --pages /docs,/team,/careers

# Audit as Googlebot
vercel-seo-audit https://your-site.com --user-agent googlebot

# Audit as Bingbot
vercel-seo-audit https://your-site.com --user-agent bingbot

# Custom crawler user-agent
vercel-seo-audit https://your-site.com --user-agent "Googlebot-Image/1.0"

# Write report to file (json, md, or html)
vercel-seo-audit https://your-site.com --report json
vercel-seo-audit https://your-site.com --report md
vercel-seo-audit https://your-site.com --report html

# Compare against a previous report to detect regressions
vercel-seo-audit https://your-site.com --diff previous-report.json

# Diff with JSON output
vercel-seo-audit https://your-site.com --diff previous-report.json --json

# Crawl all sitemap URLs and audit each page (default: 50 pages)
vercel-seo-audit https://your-site.com --crawl

# Crawl with a custom limit
vercel-seo-audit https://your-site.com --crawl 100

Config file

Create a .seoauditrc.json in your project root to set defaults:

{
  "url": "https://your-site.com",
  "strict": true,
  "verbose": false,
  "userAgent": "googlebot",
  "pages": ["/docs", "/team", "/careers"],
  "report": "json",
  "timeout": 15000
}

Then just run vercel-seo-audit with no arguments. CLI flags always override config values.


What it checks

Redirects

  • Redirect chains & loops (homepage + common pages)
  • HTTP → HTTPS redirect
  • Trailing slash consistency (catches Next.js 308 traps)
  • Meta refresh redirects (<meta http-equiv="refresh">)
  • Samples common routes: /about, /contact, /blog, /pricing (customisable with --pages)

robots.txt

  • Missing robots.txt
  • Disallow: / (blocks everything)
  • Googlebot-specific blocks
  • Missing Sitemap: directive

Sitemap

  • Missing or malformed sitemap.xml
  • Sitemap redirects (some crawlers won't follow)
  • Empty sitemap / broken URLs (samples up to 10)
  • Sitemap index support
  • Cross-check with robots.txt Sitemap: directive

Metadata

  • Canonical URL presence & mismatch
  • noindex via meta tags and X-Robots-Tag header
  • Missing title, description, charset, viewport
  • Open Graph basics: og:title, og:description, og:image
  • Broken or relative og:image URL validation
  • Twitter Card: twitter:card, twitter:image presence and validation

Favicon

  • Missing favicon entirely
  • /favicon.ico exists but no <link> tag
  • Conflicting favicon declarations (multiple icons)

Structured Data

  • Missing JSON-LD blocks entirely
  • Invalid JSON syntax in <script type="application/ld+json">
  • Missing @context or @type properties
  • Missing required fields for known types (Article, FAQPage, Product, Organisation, etc.)

Image SEO

  • Missing alt attributes (accessibility + SEO)
  • Empty alt on potentially non-decorative images
  • Not using next/image component on Next.js sites
  • Missing loading="lazy" on below-fold images
  • Oversized images (> 200 KB via HEAD request)
  • Missing width/height attributes (causes layout shift)

Crawl Mode (--crawl)

When --crawl is enabled, every URL from the sitemap is fetched and audited for:

  • Non-2xx status codes (broken pages)
  • noindex directives (meta tag or X-Robots-Tag header)
  • Missing <title> tag
  • Missing meta description
  • Missing or mismatched canonical URL
  • Missing JSON-LD structured data

Progress is printed to stderr as each page is crawled.

Internationalisation (hreflang)

  • Missing hreflang tags entirely (informational for single-language sites)
  • Invalid language/region codes
  • Missing self-referencing hreflang entry
  • Missing x-default fallback
  • Duplicate hreflang values
  • Missing reciprocal links (page A→B but B doesn't→A)

Security Headers

  • Missing Strict-Transport-Security (HSTS)
  • Missing X-Content-Type-Options: nosniff
  • Missing frame protection (X-Frame-Options or CSP frame-ancestors)
  • Missing Referrer-Policy

Performance Hints

  • HTML document size (warning > 1 MB, info > 500 KB)
  • Render-blocking <script> tags in <head> without async/defer
  • Large inline <style> blocks (> 50 KB)
  • Missing <link rel="preconnect"> for third-party origins

Next.js / Vercel

  • Detect Vercel deployment
  • Detect Next.js trailing slash redirect behaviour
  • Middleware rewrite/redirect headers (best-effort)

Severity & exit codes

Findings are categorised by severity:

| Icon | Severity | Meaning | | ---- | ----------- | ---------------------------------- | | | error | Actively hurting SEO — fix now | | | warning | Likely causing problems — fix soon | | | info | Useful context | | | pass | Looks good |

Exit codes:

| Code | Meaning | | ---- | ------------------------------------------ | | 0 | No errors found (warnings/info don't fail) | | 1 | One or more errors found | | 2 | Crash / invalid input |


CI / GitHub Actions

Using the GitHub Action

name: SEO Audit
on:
  push:
    branches: [main]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: JosephDoUrden/vercel-seo-audit@v1
        with:
          url: https://your-site.com
          strict: true
          report: json

All inputs:

| Input | Required | Default | Description | |-------|----------|---------|-------------| | url | yes | — | URL to audit | | strict | no | false | Fail on warnings too | | user-agent | no | — | googlebot, bingbot, or custom string | | pages | no | — | Comma-separated page paths | | report | no | — | Write report file: json, md, or html | | crawl | no | — | Crawl sitemap URLs (number = page limit, default 50) | | timeout | no | 10000 | Request timeout in ms | | verbose | no | false | Show detailed output |

Outputs: exit-code, report-path

Using npx directly

name: SEO Audit
on:
  push:
    branches: [main]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npx vercel-seo-audit https://your-site.com --strict --report json

Strict mode & reports in CI

Use --strict (-S) to fail CI on warnings as well as errors — useful for enforcing SEO standards on every deploy:

# Fail on any warning or error
npx vercel-seo-audit https://your-site.com --strict

# Generate a JSON report and fail strictly
npx vercel-seo-audit https://your-site.com --strict --report json

# Generate a Markdown report for PR comments
npx vercel-seo-audit https://your-site.com --report md

[!TIP] If you want warnings to fail CI too, add a --strict or -S flag.


Roadmap

Completed

  • [x] ~~--strict (warnings fail with exit code 1)~~
  • [x] ~~--pages to customise sampled paths~~
  • [x] ~~--user-agent presets (googlebot, bingbot)~~
  • [x] ~~--report to write report.json / report.md~~
  • [x] ~~GitHub Action marketplace wrapper~~
  • [x] ~~--diff to compare two audit runs and detect regressions~~
  • [x] ~~Structured data / JSON-LD validation~~
  • [x] ~~--crawl mode to audit all pages from sitemap~~
  • [x] ~~i18n / hreflang validation~~
  • [x] ~~Image SEO checks (missing alt, next/image, lazy loading)~~
  • [x] ~~Config file (.seoauditrc.json) for project-level defaults~~
  • [x] ~~Open Graph & Twitter Card image validation (#36)~~
  • [x] ~~Security headers audit (#37)~~
  • [x] ~~Performance hints (resource size, render-blocking) (#38)~~
  • [x] ~~HTML report format with interactive dashboard (#39)~~

Up next

  • [ ] --ignore flag and .seoauditignore support (#41) good first issue
  • [ ] GitHub Actions PR comment integration (#44) good first issue
  • [ ] --fix flag with auto-fix suggestions (#40)
  • [ ] Internal broken link checker (#42)

Future

  • [ ] Page speed score via PageSpeed Insights API (#43)
  • [ ] Accessibility basics audit (#45)
  • [ ] Multi-URL batch auditing (#46)
  • [ ] Plugin system for custom audit checks (#47)

FAQ

Does this replace Google Search Console? No — it explains & verifies the things Search Console often reports vaguely.

Will it scan my entire site? No. It checks critical endpoints + samples common pages to stay fast. Use --crawl for a full sitemap audit.

Does it work on non-Next.js sites? Yes for most checks (redirects/robots/sitemap/metadata). Some checks are Next.js/Vercel-specific.


Contributing

Contributions are welcome! Please read the Contributing Guide before opening a PR.

If you're looking for a place to start, check out issues labelled good first issue.

If you're reporting a false positive, include:

  • the URL (or a reproducible HTML sample)
  • expected behaviour
  • actual output

Releasing

Releases are automated with release-please. Merge conventional commits to main and release-please opens a release PR that bumps the version and updates CHANGELOG.md. Merging that PR creates a GitHub Release, which triggers npm publish automatically.

See docs/RELEASING.md for the full process, commit message format, and required secrets.


Licence

MIT