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

@consilioweb/payload-seo-analyzer

v1.21.1

Published

Payload CMS SEO plugin — 50+ checks, dashboard, Lexical JSON support, Flesch FR/EN readability, i18n

Readme

MIT License npm Node.js Payload Tests TypeScript

📑 Table of Contents

✨ Features

🔍 50+ On-Page Checks

A deterministic, offline engine across ~21 rule groups: title, meta, content, headings, images, linking, readability, schema, E-E-A-T and more.

🤖 SEO 2026 Ready

Entities & topical authority (sameAs/knowsAbout), AI/GEO extractability, real per-type JSON-LD validation, and GSC-driven content grading.

📊 9-View Admin Dashboard

Site-wide audit, link graph (with crawl budget), redirect manager, schema builder, cannibalization, keyword research, performance and config.

🌍 Bilingual & i18n

FR/EN readability scoring (Flesch + Kandel–Moles), 39-language meta labels, FR/EN dashboard auto-locale, and per-locale audit/caching.

🔐 Hardened & Typed

RBAC gate, SSRF protections, open-redirect/robots sanitization, bounded cache and rate limiting — fully typed, with 391 tests.

⚡ Built for Real Hosts

Single-flight, throttled background audit; paginated loading; bounded LRU cache; LLM timeouts — stays responsive on constrained shared hosting.

🚀 Quick Start

// payload.config.ts
import { buildConfig } from 'payload'
import { seoAnalyzerPlugin } from '@consilioweb/payload-seo-analyzer'

export default buildConfig({
  plugins: [
    seoAnalyzerPlugin({
      collections: ['pages', 'posts'],
      siteUrl: 'https://example.com',
    }),
  ],
})
pnpm payload generate:importmap
pnpm dev

Open /admin/seo for the dashboard, or edit any page/post to see the live SEO score in the sidebar.

📦 Installation

npm

npm install @consilioweb/payload-seo-analyzer

yarn

yarn add @consilioweb/payload-seo-analyzer

pnpm

pnpm add @consilioweb/payload-seo-analyzer

Peer dependencies: payload@^3, @payloadcms/next@^3 (and optionally @payloadcms/ui@^3, react@^18 || ^19). After adding admin components, run pnpm payload generate:importmap.

💻 Usage

Basic

seoAnalyzerPlugin({ collections: ['pages', 'posts'] })

Advanced

seoAnalyzerPlugin({
  collections: ['pages', 'posts', 'products'],
  globals: ['home'],
  siteUrl: 'https://example.com',
  locale: 'fr',
  features: {
    gscApi: true,      // Google Search Console (OAuth)
    aiFeatures: true,  // AI assists (needs ANTHROPIC_API_KEY)
    alerts: true,      // monitoring digest (webhook/email)
  },
})

Frontend metadata (Next.js)

import { buildSeoMetadata } from '@consilioweb/payload-seo-analyzer'

export const generateMetadata = ({ doc }) =>
  buildSeoMetadata(doc, { siteUrl: 'https://example.com' })

🔌 API Reference

seoAnalyzerPlugin(config)

The Payload plugin. Adds SEO fields, admin views, editor components and API endpoints.

seoAnalyzerPlugin(config: SeoPluginConfig): Plugin

analyzeSeo(input, config)

Runs the full engine programmatically and returns the score, level and checks.

analyzeSeo(input: SeoInput, config?: SeoConfig): SeoAnalysis

Frontend helpers

buildSeoMetadata(doc, opts): Metadata            // Next.js <head> metadata
buildJsonLd(type, values): Record<string, unknown> // schema.org JSON-LD
renderJsonLdScript(jsonLd): string                 // <script type="application/ld+json">

Key HTTP endpoints (under /api/seo-plugin, auth required)

| Method | Path | Purpose | |---|---|---| | GET/POST | /validate | Full per-document analysis. | | GET | /audit | Site-wide audit (background, throttled). | | GET | /indexation-audit | Cross-page indexation hygiene. | | GET | /link-graph | Internal link graph + crawl budget. | | GET | /content-grade | GSC-driven coverage grade (opt-in). | | POST | /ai-optimize, /ai-alt-text, /ai-content-brief | AI assists (opt-in). | | GET | /robots.txt, /sitemap.xml, /llms.txt | Public, generated. |

⚙️ Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | collections | string[] | ['pages','posts'] | Collections to analyze. | | globals | string[] | [] | Globals to analyze. | | siteUrl | string | env | Base URL (canonical, GSC, sitemaps). | | locale | 'fr' \| 'en' | 'fr' | Analysis language. | | features | SeoFeatures | all true | Granular feature flags. | | disabledRules | RuleGroup[] | [] | Disable rule groups. | | thresholds | SeoThresholds | defaults | Override numeric thresholds. |

Environment variables

| Env var | Default | Description | |---------|---------|-------------| | ANTHROPIC_API_KEY | — | Enables AI assists (server-side). Heuristic fallback without it. | | SEO_AI_MODEL | claude-sonnet-4-6 | Model override (claude-opus-4-8 = max quality, claude-haiku-4-5 = cheapest). | | SEO_REQUIRE_ADMIN_ROLE | — | 1 disables the RBAC fail-open. | | SEO_FETCH_MAX_DOCS | 5000 | Memory cap for site-wide analysis. | | SEO_STRICT_READ_ACCESS | — | 1 makes single-document reads respect the caller's collection/field-level ACL (overrideAccess: false). | | SEO_LLMS_TXT | — | 1 enables the opt-in /llms.txt generator. | | SEO_GSC_ENCRYPTION_KEY | — | 32-byte key to encrypt GSC tokens at rest (recommended). | | SEO_AUDIT_DOC_DELAY_MS | 10 | Per-document pause during the audit build — gentler on the CPU so the site stays responsive (raise on rich-content sites; 0 = fastest build). | | SEO_AUDIT_* / SEO_ALERT_* | see docs | Audit throttling (batch size/delay/depth/max-docs) & monitoring digest. |

⚡ Performance

Engineered to stay responsive on constrained shared hosting (no fabricated benchmarks — characteristics depend on your content volume and host):

| Concern | Approach | |---------|----------| | Site-wide audit | Single-flight, background-built, throttled (env-tunable); never blocks or OOM-kills the process. | | Heavy endpoints | Periodic event-loop yielding + rate limiting (keyed by user id). | | Document loading | Paginated with a memory cap (SEO_FETCH_MAX_DOCS). | | Caching | LRU-bounded, locale-aware invalidation; Core Web Vitals cached to protect the PSI quota. | | External APIs | LLM calls have timeouts and retry/backoff. |

Tune via the SEO_AUDIT_* env vars on the tiniest hosts.

📚 Examples

Disable a rule group and re-weight another

seoAnalyzerPlugin({
  collections: ['pages'],
  disabledRules: ['ecommerce'],
  overrideWeights: { social: 1 },
})

Custom thresholds

seoAnalyzerPlugin({
  collections: ['posts'],
  thresholds: { TITLE_LENGTH_MAX: 65, META_DESC_LENGTH_MAX: 165 },
})

❓ FAQ

No. The core analysis is offline and deterministic. Google Search Console and AI assists are opt-in and use your own credentials.

Node.js 18+, Payload 3.x, and React 18 or 19.

Yes — the package is fully typed and ships its own type definitions; IntelliSense works out of the box.

The base plugin is free and offline. Only AI assists (Anthropic) and PageSpeed/GSC quotas involve your own external usage.

See the Contributing section. Bug reports, ideas and pull requests are all welcome.

🔧 Troubleshooting

Admin components not updating

Solution: regenerate the import map.

pnpm payload generate:importmap

SQLITE_BUSY during imports

Solution: the plugin serializes its own writes; ensure your seed/import scripts also write sequentially on SQLite.

Audit feels heavy on a small host

Solution:

  • Raise SEO_AUDIT_BATCH_DELAY_MS
  • Set SEO_AUDIT_DEPTH=0
  • Disable features.warmCache

🔐 Security

Security is a first-class concern. The plugin reads secrets only from environment variables (never the DB), encrypts GSC tokens at rest, validates redirect targets, sanitizes robots.txt rules, and protects outbound fetches against SSRF (private-IP allowlist, DNS-rebinding guard, manual redirect re-validation).

Reporting Security Issues

Please email [email protected] instead of opening a public issue.

Best Practices

  • ✅ Keep the plugin up-to-date
  • ✅ Set SEO_GSC_ENCRYPTION_KEY and SEO_REQUIRE_ADMIN_ROLE=1 in production
  • ✅ Read all secrets from environment variables
  • ✅ Enforce a rate limit at your reverse proxy

🤝 Contributing

Contributions are very welcome!

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'feat: add AmazingFeature')
  4. Push the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Run the checks before submitting:

pnpm typecheck && pnpm test && pnpm build

📝 Changelog

See CHANGELOG.md for the full history.

[1.21.0]

  • 🗃️ Build-time audit cache: pre-compute the site-wide audit at CI via buildAuditToFile() and serve it in prod through the new auditCacheFile option — no heavy live rebuild on memory-constrained hosts. Stale-guarded (ignored once content changes); runtime kill-switch SEO_AUDIT_FILE_CACHE=0.

[1.19.0]

  • ✨ SEO 2026: entities & topical authority, AI/GEO extractability, GSC-driven content grade, indexation hygiene, crawl-budget analysis, opt-in llms.txt.
  • ⚡ Performance: paginated loading, bounded LRU cache, event-loop yielding, LLM timeouts/retries.
  • 🔐 Security: IDOR allowlists, open-redirect & robots sanitization, residual-SSRF fix, user.id rate limiting, SEO_REQUIRE_ADMIN_ROLE.
  • 1.18.2 — Fix: false "broken links" & "orphan pages" for posts linked via /posts/<slug>
  • 1.18.1 — Fix: dashboard audit returned HTTP 429 mid-build (polling throttled itself)
  • 1.18.0 — Accurate readability on list-heavy content (sentence boundaries at block ends)
  • 1.17.3 — Audit build no longer freezes the site (per-document yield)
  • 1.17.2 — Fix: admin tools 403 for legit admins on role-less setups
  • 1.17.1 — Fix: GSC panels showed "Error 404" when the feature is off
  • 1.17.0 — Audit throttling (no more server saturation)
  • 1.16.0 — IndexNow (proactive indexing)
  • 1.15.0 — Module health / observability
  • 1.14.0 — One-click "Optimize site" + per-locale audit
  • 1.13.0 — CTR opportunities (GSC data → targeted meta rewrite)
  • 1.12.0 — Bulk meta correction (preview/export/apply) + audit hardening
  • 1.11.0 — AI content brief, News/Image/Video sitemaps, multi-location local SEO
  • 1.10.0 — Rank tracking, frontend render helpers, monitoring alerts, AI alt-text
  • 1.9.0 — AI SEO Optimize + dashboard OOM hardening
  • 1.8.0–1.8.1 — SEO 2026 "desintox" pass + low-memory audit
  • 1.3.0–1.7.0 — Early releases (core engine, i18n, dashboard)

See CHANGELOG.md for full details of every release.

🗺️ Roadmap

  • [x] SEO-2026 feature set (entities, GEO, content grade, indexation hygiene)
  • [x] Security & performance hardening
  • [x] End-to-end UI test harness — admin views (e2e/)
  • [x] Optional strict field-level access control — opt-in via SEO_STRICT_READ_ACCESS=1
  • [x] Entity input fields in the Schema Builder — author sameAs, Organization knowsAbout
  • [ ] Lazy-loading of the heaviest admin views — deferred: needs live-admin verification (the current RSC / single client-bundle architecture would require a build-time entry split)

☕ Support

If this plugin saves you time, consider buying me a coffee!

📄 License

Licensed under the MIT License. See the LICENSE file for details.