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-seo-audit

v0.3.3

Published

Score Astro SEO after every build with whole-site and single-page audits, regression gates, an interactive HTML dashboard, and SARIF.

Readme

Astro SEO Audit

npm version CI license

SEO checks that fit the way Astro ships.

Independent project: Astro SEO Audit is not affiliated with, endorsed by, or an official project of Astro or its maintainers.

Astro SEO Audit inspects the HTML your Astro site actually generates, gives it an explainable 0–100 health score, and catches technical and on-page SEO problems before they reach production.

Audit the whole site before a deploy or check one new page while you are writing it. Add a baseline to block only new regressions, then explore the results in the compact terminal output, a searchable standalone HTML dashboard, JSON, or GitHub Code Scanning through SARIF.

Nothing to host. No headless browser. No native binary. No telemetry.

Astro SEO Audit
────────────────────────────────────────────────

47 pages scanned
Astro SEO Audit health score: 87/100

✕ Errors       3
⚠ Warnings     14
ⓘ Notices      8
✓ Checks passed 328

Issues by type

✕ Broken internal link
  links.broken-internal · 3 findings · 3 affected URLs
  /food-wheel/  /meal-picker/  /dinner-wheel/

⚠ Missing canonical
  canonical.missing · 14 findings · 14 affected URLs
  /wheel-of-doom/  /yes-or-no-wheel/  /random-animal/  +11 more

Open the searchable report: npx astro-seo-audit --output astro-seo-report.html

The terminal stays intentionally compact even on sites with thousands of generated pages. It groups repeated findings by rule, samples affected URLs, and points to the searchable HTML dashboard for the complete list.

Why use it

Astro sites can generate metadata through layouts, integrations, Markdown, MDX, content loaders, or plain HTML. Source-code checks see only one implementation; Astro SEO Audit checks the final document delivered to search engines.

| Need | What Astro SEO Audit does | | ----------------------------------- | ------------------------------------------------------------------------ | | Check a site before deployment | Audits every generated page and the internal-link graph after the build | | Check only a new or updated page | Runs a fast route-level audit with its own 0–100 score | | Adopt checks on an established site | Baselines existing findings and fails only on newly introduced problems | | Understand what changed | Explains every finding, penalty, severity, and likely static source file | | Use results outside the terminal | Produces a searchable HTML dashboard, JSON, and SARIF 2.1 reports |

Under the hood, it combines:

  • final-output HTML inspection;
  • automatic auditing after astro build through a native Astro integration;
  • site-wide crawling and internal-link graph analysis;
  • conservative, rationale-backed SEO rules;
  • explainable 0–100 scoring and fast page-only audits;
  • terminal, JSON, standalone HTML, and SARIF reports;
  • adoption baselines that block only newly introduced regressions;
  • likely src/pages source-file hints for static routes;
  • deterministic CI quality gates.

It runs locally. There is no telemetry, analytics, content upload, or AI API.

What's new in v0.3.3

  • A compact terminal summary groups repeated findings instead of dumping every URL.
  • The standalone HTML report is now a searchable dashboard with severity filters, issue drill-down, page search, fixed 30-URL pagination, and detailed per-page inspection.
  • Page-only audits show an actual page score, evidence, why each issue matters, a suggested fix, and grouped passed areas.
  • Missing-build errors now distinguish an unbuilt site from a failed Astro build and tell the user what to run next.
  • Intentionally non-indexable pages no longer receive irrelevant description and social-preview warnings; generated 404 noindex directives are treated as expected.
  • The HTML parser dependency was simplified, removing the deprecated whatwg-encoding install warning.

Requirements

  • Node.js 20 or newer
  • generated static HTML (dist/ in Astro by default)

Installation

Let Astro install the package and update your configuration:

npx astro add astro-seo-audit

Or install it manually:

npm install --save-dev astro-seo-audit

Pick the workflow you need

Build the site first, then choose the smallest useful report:

| Goal | Command | Result | | -------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------- | | Check the complete site | npm run build && npx astro-seo-audit | Compact terminal summary with every generated page scanned | | Explore every URL visually | npx astro-seo-audit --output astro-seo-report.html | Searchable local dashboard with filters, 30-row pagination, and page drill-down | | Check one new page | npx astro-seo-audit --page /blog/new-post/ | Focused page score with evidence, explanations, suggested fixes, and passed areas | | Enforce SEO in CI | npx astro-seo-audit --fail-on warning | Non-zero exit when a warning or error is found |

Open the generated HTML report in any browser. It is one portable file with no server, account, remote assets, or content upload required. After writing the file, the CLI prints the correct command to open it on your operating system, so you do not have to remember the command below.

# Windows PowerShell
start .\astro-seo-report.html

# macOS
open ./astro-seo-report.html

# Linux
xdg-open ./astro-seo-report.html

Quick start: audit every build

Run the audit automatically at the end of every Astro build:

// astro.config.mjs
import { defineConfig } from "astro/config";
import seoAudit from "astro-seo-audit";

export default defineConfig({
  site: "https://example.com",
  integrations: [seoAudit()],
});

The integration audits Astro's resolved output directory, including custom outDir settings. It adds no client-side JavaScript and does not affect the generated site.

Prefer an on-demand audit? Build the site and run the CLI without changing astro.config.mjs:

npm run build && npx astro-seo-audit

The audit runs only if the Astro build succeeds. If the build fails, fix that build error first; no dist/ report can be audited yet.

Use it as a production quality gate and write a visual report:

seoAudit({
  failOn: "error",
  output: "reports/astro-seo-audit.html",
});

Set SKIP_ASTRO_SEO_AUDIT=1 for a build that intentionally needs to skip the audit. The CLI remains available for ad-hoc, single-page, and CI usage.

Astro SEO Audit detects a common Astro configuration, including literal site, trailingSlash, and outDir values. Astro config files are read statically and are never imported or executed.

Audit an explicit build directory:

npx astro-seo-audit ./dist
# equivalent
npx astro-seo-audit --dir ./dist

Audit only a newly generated page:

npx astro-seo-audit --page /blog/new-post/

Page mode resolves that route directly to its generated HTML file and reads only that page. It runs every page-level check while skipping site-wide checks that would require crawling the complete build, such as duplicate metadata, broken-link graphs, orphan pages, sitemaps, and robots.txt. This makes it suitable for a fast pre-publish check; keep the default full-site audit in CI for complete coverage.

See every option:

npx astro-seo-audit --help

CLI

astro-seo-audit [directory] [options]

--dir <path>          Audit a specific build directory
--page <route>        Audit one generated page and skip site-wide checks
--format <format>     terminal, json, html, or sarif
--output <file>       Write a report; .html selects HTML automatically
--baseline <file>     Report and fail only on findings absent from a baseline
--write-baseline <file>  Save current findings as an adoption baseline
--fail-on <severity>  error, warning, info, or none
--no-color            Disable ANSI colors
--quiet, -q           Print only the summary
--version, -v         Show the package version
--help, -h            Show help

NO_COLOR is respected automatically. Output is non-interactive and safe for CI logs.

--page accepts a generated route or a same-origin absolute URL. Query strings and fragments are ignored when locating the file:

npx astro-seo-audit --page /guides/getting-started/
npx astro-seo-audit --page https://example.com/guides/getting-started/
npx astro-seo-audit --dir ./custom-output --page /launch/

The site must be built first. Both Astro directory output (/about/about/index.html) and file output (/about.html) are supported.

CI quality gates

Fail only when technical errors exist:

- name: Build
  run: npm run build
- name: Audit generated SEO
  run: npx astro-seo-audit --fail-on error

Threshold behavior is inclusive:

| Value | Non-zero exit when findings include | | --------- | ----------------------------------- | | error | errors | | warning | warnings or errors | | info | any finding | | none | never because of findings |

Exit code 1 means the configured quality gate failed. Exit code 2 means the audit could not run, such as a missing build directory or invalid option.

Adopt it without fixing everything first

Create a baseline from the current site:

npx astro-seo-audit --write-baseline .astro-seo-audit-baseline.json

Commit that file, then block only newly introduced warnings or errors:

npx astro-seo-audit \
  --baseline .astro-seo-audit-baseline.json \
  --fail-on warning

The health score continues to describe the complete site. The baseline changes only which findings are displayed and used by the CI quality gate, so existing debt is never mistaken for a healthy score.

JSON output

Print JSON:

npx astro-seo-audit --format json

Write it to a file:

npx astro-seo-audit --output seo-report.json

The JSON is a machine-readable model rather than terminal text. It includes project discovery, the site score breakdown, summary counts, normalized page results with individual page scores, passed rule IDs, schema types, page findings, site findings, site-wide passed rules, and a flat findings array.

{
  "version": "0.3.3",
  "mode": "site",
  "score": 87,
  "scoreBreakdown": {
    "initial": 100,
    "penalty": 13,
    "weights": { "error": 8, "warning": 2, "info": 0.25 },
    "rulePenaltyCap": 12,
    "penaltiesByRule": {}
  },
  "pagesScanned": 47,
  "summary": {},
  "pages": [],
  "siteFindings": [],
  "findings": []
}

HTML report

Generate a standalone report that can be opened locally or uploaded as a CI artifact:

npx astro-seo-audit --output astro-seo-report.html

The responsive report behaves like a lightweight local SEO dashboard. It groups problems by rule, lets you filter by severity, searches routes and source hints, shows 30 URLs at a time with Previous/Next and compact page-number controls, filters down to URLs affected by one issue, and opens a detailed page view with:

  • the page's own 0–100 score and likely Astro source file;
  • every finding, including the value or evidence that triggered it;
  • a plain-language explanation of why the issue matters;
  • a specific suggested fix; and
  • grouped passed areas and detected structured-data types.

All pages and findings remain inside the report, but only one manageable page of rows is rendered at a time. The dashboard has no remote assets, makes no network requests, and does not upload site content.

GitHub annotations with SARIF

Generate a SARIF 2.1 report for GitHub Code Scanning and other compatible CI systems:

npx astro-seo-audit --output astro-seo-audit.sarif

Static routes are linked to their likely src/pages source file when one can be determined safely. Dynamic and generated routes fall back to their built HTML file rather than guessing.

Built-in checks

Each check is an independent rule with an ID, category, default severity, scope, description, help text, and evaluation function.

| Area | Checks | | ---------------- | -------------------------------------------------------------------------------------------------------------------- | | Title | missing, empty, multiple, duplicate, configurable editorial length | | Meta description | missing, empty, multiple, duplicate, configurable editorial length | | Canonical | missing, empty, multiple, relative, malformed, confident same-origin mismatch, duplicate target | | Indexability | noindex notice, nofollow notice, contradictory page directives | | Headings | missing H1, multiple H1 notice; full hierarchy is collected | | Images | missing alt; valid decorative alt="" is not flagged | | Internal links | malformed links, missing generated targets, orphan indexable pages | | Social | missing Open Graph fields and twitter:card, all at notice level | | Language | missing, empty, or obviously malformed html[lang] | | JSON-LD | empty blocks, invalid JSON, detected @type values including @graph | | Sitemap | absence, malformed XML/URLs, indexable generated pages missing from sitemap; generated sitemap indexes are supported | | robots.txt | absence, exact contradictory directives, wildcard full-site block |

The rules are deliberately conservative:

  • title and description ranges are guidance, not Google limits;
  • meta descriptions, Open Graph data, schema, sitemaps, and robots.txt are not required for indexing;
  • multiple H1 elements are not treated as a technical error;
  • noindex is a notice because intent cannot be inferred reliably;
  • empty image alt text is accepted as a valid decorative-image pattern; and
  • generated 404.html documents are recognized as not-found pages and excluded from indexability-dependent canonical, orphan, duplicate, and sitemap checks; and
  • JSON-LD parsing does not claim rich-result eligibility.

Configuration

Zero configuration works for typical static Astro builds. Optional settings can live in astro-seo-audit.config.json:

{
  "site": "https://example.com",
  "buildDir": "dist",
  "trailingSlash": "always",
  "ignoreRoutes": ["/drafts/**"],
  "orphanExclusions": ["/campaign/**"],
  "ignoredRules": ["twitter.card-missing"],
  "severityOverrides": {
    "description.missing": "info"
  },
  "titleLength": { "min": 25, "max": 65 },
  "descriptionLength": { "min": 60, "max": 170 },
  "failOn": "error"
}

The same object may be placed under the astro-seo-audit key in package.json. A standalone JSON file takes precedence. CLI options override file configuration.

JSON configuration is intentional: loading JavaScript or TypeScript configuration would execute project code. Static Astro discovery also recognizes only common literal values. Pass --dir or set JSON configuration when a computed Astro setting cannot be inferred safely.

Route patterns support * within one path segment and ** across segments.

Health score

The score is an Astro SEO Audit health score, not a Google ranking or Lighthouse score.

It starts at 100. Default penalties are:

  • error: 8 points;
  • warning: 2 points; and
  • info: 0.25 points.

Repeated findings from one rule are capped at 12 points. This prevents hundreds of minor repetitions from overwhelming the result. The final score is rounded to the nearest integer and never falls below zero. JSON output exposes every weight and per-rule penalty so score changes are explainable.

Severity overrides affect both reporting and scoring.

Programmatic API

The CLI is the primary interface, but the core is exported for tooling:

import { audit, renderJson } from "astro-seo-audit";

const report = await audit({ dir: "./dist" });
console.log(renderJson(report));

For a fast page-only audit:

const report = await audit({
  dir: "./dist",
  page: "/blog/new-post/",
});

Built-in pageRules and siteRules are exported for inspection and future composition. The engine is not coupled to Astro internals; only project discovery is Astro-specific.

Architecture

Astro integration or CLI
        ↓
Astro project discovery → generated HTML crawler → normalized page model → page rules
                                                              ↓
                                                     link/site model → site rules
                                                              ↓
                                  scoring → terminal / JSON / HTML → baseline gate

The core audits generated files. It does not require astro-seo, a particular layout, Content Collections, or any head component.

Limitations

  • The auditor inspects static generated HTML, not server-rendered routes that have no build-time HTML file.
  • Page mode intentionally skips site-wide rules. Duplicate metadata, internal-link graph, orphan, sitemap, and robots.txt checks require a full audit.
  • External links are not requested or validated.
  • Astro config detection is intentionally static and cannot evaluate variables, environment branches, or helper functions.
  • robots.txt support covers safe, high-confidence basics rather than every crawler-specific matching edge case.
  • Sitemap indexes are followed through generated local sitemap*.xml files; remote child sitemaps are not downloaded.
  • JSON-LD is parsed and typed, not validated against Schema.org or Google Rich Results requirements.
  • Redirects, hreflang, pagination, and HTTP headers are outside v0.1.

Roadmap

Potential future work includes a custom rule API, safe --fix operations, richer schema and hreflang validation, redirect analysis, external-link checking, and framework adapters.

Contributing

Contributions are welcome. See CONTRIBUTING.md, especially the small rule contract for adding checks.

License

MIT. Astro SEO Audit is an independent community project and is not an official Astro package.

Built by Naman Labs.