seo-gravity-mcp 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +118 -105
  2. package/dist/adapters/adapterRegistry.d.ts +7 -0
  3. package/dist/adapters/adapterRegistry.js +30 -0
  4. package/dist/adapters/astroAdapter.d.ts +17 -0
  5. package/dist/adapters/astroAdapter.js +191 -0
  6. package/dist/adapters/nextAppAdapter.d.ts +17 -0
  7. package/dist/adapters/nextAppAdapter.js +265 -0
  8. package/dist/adapters/nextPagesAdapter.d.ts +17 -0
  9. package/dist/adapters/nextPagesAdapter.js +209 -0
  10. package/dist/adapters/remixAdapter.d.ts +16 -0
  11. package/dist/adapters/remixAdapter.js +118 -0
  12. package/dist/adapters/staticAdapter.d.ts +16 -0
  13. package/dist/adapters/staticAdapter.js +117 -0
  14. package/dist/adapters/svelteKitAdapter.d.ts +16 -0
  15. package/dist/adapters/svelteKitAdapter.js +122 -0
  16. package/dist/adapters/types.d.ts +39 -0
  17. package/dist/adapters/types.js +1 -0
  18. package/dist/adapters/viteReactAdapter.d.ts +16 -0
  19. package/dist/adapters/viteReactAdapter.js +189 -0
  20. package/dist/benchmark/correlationBenchmark.d.ts +1 -0
  21. package/dist/benchmark/correlationBenchmark.js +96 -0
  22. package/dist/benchmark/invariantBenchmark.d.ts +1 -0
  23. package/dist/benchmark/invariantBenchmark.js +47 -0
  24. package/dist/cli.d.ts +8 -0
  25. package/dist/cli.js +162 -0
  26. package/dist/index.d.ts +3 -1
  27. package/dist/index.js +8 -646
  28. package/dist/invariants/registry.d.ts +12 -0
  29. package/dist/invariants/registry.js +178 -0
  30. package/dist/invariants/types.d.ts +38 -0
  31. package/dist/invariants/types.js +1 -0
  32. package/dist/providers/providerRegistry.d.ts +65 -0
  33. package/dist/providers/providerRegistry.js +64 -0
  34. package/dist/providers/types.d.ts +22 -0
  35. package/dist/providers/types.js +1 -0
  36. package/dist/server/registry.d.ts +3 -0
  37. package/dist/server/registry.js +559 -0
  38. package/dist/server/server.d.ts +70 -0
  39. package/dist/server/server.js +53 -0
  40. package/dist/server/types.d.ts +7 -0
  41. package/dist/server/types.js +1 -0
  42. package/dist/test.js +108 -138
  43. package/dist/tools/orchestration.js +23 -21
  44. package/dist/types/canonical.d.ts +64 -0
  45. package/dist/types/canonical.js +1 -0
  46. package/dist/types/findings.d.ts +22 -0
  47. package/dist/types/findings.js +1 -1
  48. package/dist/types/seo.d.ts +24 -0
  49. package/dist/utils/astLocator.d.ts +14 -0
  50. package/dist/utils/astLocator.js +137 -0
  51. package/dist/utils/cacheManager.d.ts +29 -0
  52. package/dist/utils/cacheManager.js +60 -0
  53. package/dist/utils/experimentEngine.d.ts +26 -0
  54. package/dist/utils/experimentEngine.js +41 -0
  55. package/dist/utils/findingEngine.d.ts +2 -1
  56. package/dist/utils/findingEngine.js +1 -0
  57. package/dist/utils/gitDiffEngine.d.ts +28 -0
  58. package/dist/utils/gitDiffEngine.js +109 -0
  59. package/dist/utils/opportunityEngine.d.ts +19 -0
  60. package/dist/utils/opportunityEngine.js +61 -0
  61. package/dist/utils/projectScanner.d.ts +4 -2
  62. package/dist/utils/projectScanner.js +14 -346
  63. package/dist/utils/sarifExporter.d.ts +64 -0
  64. package/dist/utils/sarifExporter.js +81 -0
  65. package/dist/utils/snapshotEngine.d.ts +3 -1
  66. package/dist/utils/snapshotEngine.js +232 -94
  67. package/package.json +8 -5
package/README.md CHANGED
@@ -1,18 +1,18 @@
1
- # 🚀 SEO Gravity MCP (v1.0.2)
1
+ # 🚀 SEO Gravity (v1.2.0)
2
2
 
3
3
  <div align="center">
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/seo-gravity-mcp?style=for-the-badge&logo=npm&color=CB3837)](https://www.npmjs.com/package/seo-gravity-mcp)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/seo-gravity-mcp?style=for-the-badge&logo=npm&color=CB3837)](https://www.npmjs.com/package/seo-gravity-mcp)
7
7
  ![MCP Protocol](https://img.shields.io/badge/MCP-Protocol-blue?style=for-the-badge&logo=anthropic)
8
+ ![SARIF Ready](https://img.shields.io/badge/SARIF-GitHub_Code_Scanning-success?style=for-the-badge)
9
+ ![CLI Ready](https://img.shields.io/badge/CLI-CI%2FCD_Ready-success?style=for-the-badge)
8
10
  ![TypeScript](https://img.shields.io/badge/TypeScript-5.7+-3178C6?style=for-the-badge&logo=typescript&logoColor=white)
9
- ![Node.js](https://img.shields.io/badge/Node.js-18+-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)
10
- ![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge)
11
11
  ![Zero API Cost](https://img.shields.io/badge/Zero_API_Cost-100%25_Free-orange?style=for-the-badge)
12
12
 
13
- **The Universal SEO Intelligence, Source-Code Correlation & Remediation Engine for AI Coding Agents.**
13
+ **The SEO Engineering Infrastructure Layer for AI Coding Agents & CI/CD Pipelines.**
14
14
 
15
- [⚡ Instant Start](#-instant-start) • [🤖 Client Setup](#-ai-ide--mcp-client-setup) • [🧠 5-Stage Autonomous Loop](#-the-5-stage-autonomous-remediation-loop) • [🛠 Tool Catalog (35 Tools)](#-complete-tool-catalog-35-tools) • [📄 License](#-license)
15
+ [⚡ Instant Start](#-instant-start) • [💻 CLI & CI/CD](#-command-line--cicd-runner) • [🛡️ Invariant Truth Layer](#-formal-seo-invariant-registry) • [🏛 5-Layer Architecture](#-5-layer-system-architecture) • [🧩 Framework Adapters](#-modular-framework-adapters) • [🛠 Tool Catalog (35 Tools)](#-complete-tool-catalog) • [📄 License](#-license)
16
16
 
17
17
  </div>
18
18
 
@@ -20,67 +20,132 @@
20
20
 
21
21
  ## 🌟 What is SEO Gravity?
22
22
 
23
- **SEO Gravity** gives AI coding agents (Antigravity, Cursor, Claude Code, Windsurf, Cline, Roo Code, etc.) the autonomous ability to **understand, audit, fix, and continuously verify the SEO of the websites they build.**
23
+ **SEO Gravity** is an **SEO engineering infrastructure layer** designed specifically for AI coding agents (Antigravity, Cursor, Claude Code, Windsurf, Cline, Roo Code) and automated CI/CD pipelines.
24
24
 
25
- Instead of acting as a passive "SEO metrics dump", SEO Gravity connects **rendered web signals** directly to your **source code components** (Next.js App Router, Astro, Vite/React, Remix, SvelteKit), ranks issues by impact-to-effort priority, generates code fix blueprints, and verifies that commits introduce **zero regressions**.
25
+ Instead of operating as a passive reporting tool, SEO Gravity connects **rendered web observations** directly to **source code AST nodes and line numbers** across modern web frameworks (Next.js App/Pages Router, Astro, Vite/React, Remix, SvelteKit), generates actionable code fix blueprints, and enforces invariant-based regression checks.
26
26
 
27
27
  ```text
28
28
  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
29
29
  │ 1. DISCOVER │ ──▶ │ 2. OBSERVE │ ──▶ │ 3. DIAGNOSE │ ──▶ │ 4. FIX │ ──▶ │ 5. VERIFY │
30
- │ Framework │ │ Live/Dev SSR │ │ Root Causes │ │ AI Modifies │ │ Re-crawl &
31
- Routes │ │ SERP & Comp. │ │ Prioritized │ │ Source Code │ │ Regression │
32
- │ Source Map │ │ Crawl Graph │ │ Action Plan │ │ Components │ │ Diff Check
30
+ │ Framework │ │ Live/Dev SSR │ │ AST Line Nos │ │ AI Modifies │ │ Invariant
31
+ Adapters │ │ Crawl Graph │ │ Prioritized │ │ Components │ │ Regression │
32
+ │ Source Map │ │ Provenance │ │ Action Plan │ │ Snippets │ │ Git Stamping
33
33
  └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
34
34
  ```
35
35
 
36
36
  ---
37
37
 
38
- ## 💡 Key Architectural Pillars
38
+ ## 🏛 5-Layer System Architecture
39
39
 
40
- 1. **Source-to-URL Correlation**: Directly maps audited URLs (`/blog/my-post`) to source files (`app/blog/[slug]/page.tsx`), identifying missing metadata exports or canonical tags.
41
- 2. **Canonical Finding Model**: Every audit issue produces a normalized finding with `id`, `severity`, `confidence` ($0.0-1.0$), `evidenceType` (*Observed*, *Derived*, *Heuristic*, *Predictive*), `effort`, `priorityScore`, and verification steps.
42
- 3. **Crawl Graph & Site Architecture**: Computes BFS click depths, orphan pages, hub pages, circular link loops, and internal link equity (PageRank heuristic).
43
- 4. **Multidimensional Health Scoring**: Breaks scores into 7 discrete dimensions (Technical, Content, Discoverability, Authority, Entity, Performance, AI Readiness) with confidence levels.
44
- 5. **SEO Regression & Snapshot System**: Creates snapshots (`seo.gravity/v1`) before commits/PRs and validates that changes introduced 0 regressions.
45
- 6. **Zero Paid API Requirement**: 100% functional out-of-the-box using local AST parsing, cheerio, JSDOM, Google Autocomplete, and standard web extraction.
40
+ ```text
41
+ ┌─────────────────────────────────────────────────────────────┐
42
+ │ 1. AGENT & CLI INTERFACE │
43
+ │ MCP Server (35 tools) + Standalone CLI (`seo-gravity`)
44
+ ├─────────────────────────────────────────────────────────────┤
45
+ │ 2. INTELLIGENCE & REASONING LAYER │
46
+ │ Root-cause diagnosis, deterministic priority, fix plans │
47
+ ├─────────────────────────────────────────────────────────────┤
48
+ │ 3. ANALYSIS & INVARIANT LAYER │
49
+ │ SEO Invariants (HTTP 200, canonical, schema, noindex) │
50
+ ├─────────────────────────────────────────────────────────────┤
51
+ │ 4. OBSERVATION LAYER (Factual Raw State) │
52
+ │ Observations ≠ Findings; AST inspection, headers, DOM │
53
+ ├─────────────────────────────────────────────────────────────┤
54
+ │ 5. PROVIDER & ADAPTER LAYER │
55
+ │ Framework Adapters (Next, Astro, Vite), Providers, Cache │
56
+ └─────────────────────────────────────────────────────────────┘
57
+ ```
46
58
 
47
59
  ---
48
60
 
49
- ## Instant Start
61
+ ## 🛡️ Formal SEO Invariant Registry
62
+
63
+ SEO Gravity enforces strict **semantic invariants** rather than heuristic score drops. A regression occurs only when a previously satisfied invariant is violated:
50
64
 
51
- Run instantly with `npx`:
65
+ | Invariant ID | Name | Target Scope | Description |
66
+ | :--- | :--- | :--- | :--- |
67
+ | `INV-HTTP-200` | HTTP Success Status | Route | Published routes must return HTTP 200 OK without 4xx/5xx errors. |
68
+ | `INV-CANONICAL-RESOLVES` | Canonical URL Declaration | Page | Indexable pages must declare a canonical URL to prevent duplicate indexing. |
69
+ | `INV-TITLE-PRESENT` | Title Tag Metadata | Page | Pages must declare unique, descriptive title metadata in AST components. |
70
+ | `INV-LINK-ACCESSIBLE` | Link Reachability | Crawl Graph | Public pages must be reachable via internal links (0 orphan pages). |
71
+ | `INV-ROBOTS-ALLOWED` | Robots Configuration | Site | Project must provide `robots.txt` or `robots.ts` specifying bot directives. |
72
+ | `INV-SITEMAP-PRESENT` | XML Sitemap Configuration | Site | Project must publish `sitemap.xml` or dynamic `sitemap.ts`. |
73
+ | `INV-LLMS-TXT` | AI Context Documentation | Site | Project should provide `/llms.txt` for AI agent discovery. |
74
+
75
+ ---
76
+
77
+ ## 🧩 Modular Framework Adapters & Benchmark
78
+
79
+ Tested with **100% correlation accuracy** across 7 web application frameworks:
80
+
81
+ | Framework Adapter | Detection | Route Discovery | AST Inspection | Benchmark |
82
+ | :--- | :--- | :--- | :--- | :---: |
83
+ | **`NextAppAdapter`** | `next` + `app/` | App Router hierarchy, route groups `(group)`, dynamic `[slug]` | Pinpoints `metadata` export & `generateMetadata()` lines | **100%** |
84
+ | **`NextPagesAdapter`** | `next` + `pages/` | Pages router hierarchy, dynamic `[id]` | Scans `<Head>` & `<NextSeo>` JSX components | **100%** |
85
+ | **`AstroAdapter`** | `astro` + `src/pages` | `.astro`, `.md`, `.mdx` pages | Scans Astro frontmatter & `<title>` tags | **100%** |
86
+ | **`ViteReactAdapter`** | `vite` / `react` | `index.html` + React Router routes | Scans `<Helmet>` & route definition trees | **100%** |
87
+ | **`RemixAdapter`** | `@remix-run/react` | `app/routes/` | Inspects `meta` and `links` export functions | **100%** |
88
+ | **`SvelteKitAdapter`** | `@sveltejs/kit` | `src/routes/` (`+page.svelte`) | Scans `<svelte:head>` components | **100%** |
89
+ | **`StaticAdapter`** | Static HTML files | Recursive HTML directory traversal | Direct DOM / meta element inspection | **100%** |
90
+
91
+ ---
92
+
93
+ ## 💻 Command-Line & CI/CD Runner (SARIF Ready)
94
+
95
+ SEO Gravity includes a standalone CLI binary (`seo-gravity`) with native **SARIF v2.1.0** export for GitHub Code Scanning:
52
96
 
53
97
  ```bash
54
- npx -y seo-gravity-mcp
98
+ # 1. Audit project (Terminal / JSON / SARIF)
99
+ npx seo-gravity-mcp audit --project ./my-app
100
+ npx seo-gravity-mcp audit --project ./my-app --format sarif --output seo-findings.sarif
101
+
102
+ # 2. Create baseline snapshot
103
+ npx seo-gravity-mcp snapshot --project ./my-app --output baseline.json
104
+
105
+ # 3. Check for SEO regressions in CI/CD PR gate (Exits with 0 or 1)
106
+ npx seo-gravity-mcp check --project ./my-app --baseline baseline.json
107
+
108
+ # 4. Targeted Semantic Git differential audit on modified routes only
109
+ npx seo-gravity-mcp diff --project ./my-app --base-ref origin/main
55
110
  ```
56
111
 
57
- Or install globally:
112
+ ### GitHub Actions CI/CD Integration
58
113
 
59
- ```bash
60
- npm install -g seo-gravity-mcp
114
+ ```yaml
115
+ name: SEO Quality Gate
116
+
117
+ on: [push, pull_request]
118
+
119
+ jobs:
120
+ seo-check:
121
+ runs-on: ubuntu-latest
122
+ steps:
123
+ - uses: actions/checkout@v4
124
+ - uses: actions/setup-node@v4
125
+ with:
126
+ node-version: 20
127
+
128
+ - name: Run SEO Invariant Regression Check
129
+ run: npx seo-gravity-mcp check --project . --baseline .seo-baseline.json --format sarif --output results.sarif
130
+
131
+ - name: Upload SARIF to GitHub Security Tab
132
+ uses: github/codeql-action/upload-sarif@v3
133
+ if: always()
134
+ with:
135
+ sarif_file: results.sarif
61
136
  ```
62
137
 
63
138
  ---
64
139
 
65
- ## 🤖 AI IDE & MCP Client Setup
66
-
67
- ### 1. 🟣 Claude Desktop
68
- Add to `claude_desktop_config.json`:
140
+ ## Instant Start (MCP Server)
69
141
 
70
- ```json
71
- {
72
- "mcpServers": {
73
- "seo-gravity": {
74
- "command": "npx",
75
- "args": ["-y", "seo-gravity-mcp"]
76
- }
77
- }
78
- }
142
+ ```bash
143
+ npx -y seo-gravity-mcp
79
144
  ```
80
145
 
81
- ### 2. Cursor
82
- Add to `.cursor/mcp.json`:
146
+ ### AI Client Configurations
83
147
 
148
+ #### Cursor (`.cursor/mcp.json`)
84
149
  ```json
85
150
  {
86
151
  "mcpServers": {
@@ -92,9 +157,7 @@ Add to `.cursor/mcp.json`:
92
157
  }
93
158
  ```
94
159
 
95
- ### 3. 🌊 Antigravity / Windsurf / VS Code Cline
96
- Add to `mcp_config.json`:
97
-
160
+ #### Claude Desktop (`claude_desktop_config.json`)
98
161
  ```json
99
162
  {
100
163
  "mcpServers": {
@@ -108,81 +171,31 @@ Add to `mcp_config.json`:
108
171
 
109
172
  ---
110
173
 
111
- ## 🛠 Complete Tool Catalog (35 Tools)
174
+ ## 🛠 Complete Tool Catalog
112
175
 
113
176
  ### Layer 0: Agent Orchestration & Remediation (Flagship)
114
177
  | Tool Name | Operational Class | Description |
115
178
  | :--- | :--- | :--- |
116
179
  | `seo_project_audit` | **Planning / Audit** | Scans workspace framework, discovers routes, correlates source files, builds crawl graph, and computes multidimensional SEO health. |
117
- | `seo_diagnose` | **Planning / Diagnose** | Deep root-cause inspection linking an observed issue/URL back to specific source code files with ready-to-use fix blueprints. |
180
+ | `seo_diagnose` | **Planning / Diagnose** | Deep root-cause AST inspection linking an observed issue/URL back to specific source code line ranges with ready-to-use fix blueprints. |
118
181
  | `seo_prioritize` | **Planning / Strategy** | Ranks findings into Quick Wins, Critical Blockers, and Architectural Improvements using `(Impact × Confidence × Reach) / Effort`. |
119
182
  | `seo_fix_plan` | **Planning / Execution** | Generates an end-to-end code modification and verification plan for AI coding agents. |
120
- | `seo_snapshot_create` | **Verification** | Creates and saves a project SEO baseline snapshot adhering to canonical schema `seo.gravity/v1`. |
121
- | `seo_snapshot_compare` | **Verification** | Diffs two snapshots to compute resolved findings, new regressions, and multidimensional score deltas. |
183
+ | `seo_snapshot_create` | **Verification** | Creates and saves a project SEO baseline snapshot with Git commit stamping adhering to schema `seo.gravity/v1`. |
184
+ | `seo_snapshot_compare` | **Verification** | Invariant-based diffing of two snapshots to isolate resolved findings, new regressions, and multidimensional score deltas. |
122
185
  | `seo_regression_check` | **Verification / CI** | Automated pass/fail regression check with alert messages for CI/CD gates and PR bots. |
123
186
 
124
- ### Layer 1: SERP & Competitor Intelligence
125
- | Tool Name | Description |
126
- | :--- | :--- |
127
- | `seo_serp_analyze` | Live Google SERP scraper returning rankings, snippets, People Also Ask (PAA), and SERP features. |
128
- | `seo_competitor_content_gap` | Compares target page against top 3-5 competitors for missing TF-IDF entities, subtopics, and word count deltas. |
129
- | `seo_competitor_profile` | Deep extraction of competitor heading tree (H1-H4), schema types, reading grade, and link ratios. |
130
- | `seo_competitor_diff` | 25-factor side-by-side scorecard comparing your page vs #1 competitor. |
131
- | `seo_forum_discussions_pulse` | Scrapes Reddit & Quora threads ranking for a query to extract user pain points and consensus. |
132
-
133
- ### Layer 2: Generative Engine Optimization (GEO & AEO)
134
- | Tool Name | Description |
135
- | :--- | :--- |
136
- | `seo_geo_ai_readiness_audit` | Audits content for AI Overviews & Perplexity citation readiness with structured retrieval signals and evidence tiers. |
137
- | `seo_llms_txt_generate` | Generates standard `/llms.txt` and `/llms-full.txt` markdown context files for AI search bots. |
138
- | `seo_ai_bots_robots_audit` | Audits robots.txt permissions specifically for AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended). |
139
-
140
- ### Layer 3: Information Gain & E-E-A-T
141
- | Tool Name | Description |
142
- | :--- | :--- |
143
- | `seo_information_gain_score` | Quantifies content novelty vs top 10 SERPs to prevent generic AI fluff penalties. |
144
- | `seo_eeat_audit` | Audits Google E-E-A-T trust signals (Person schema, author bylines, sameAs Wikidata/LinkedIn, publish/modified dates). |
145
-
146
- ### Layer 4: On-Page & Content Strategy
147
- | Tool Name | Description |
148
- | :--- | :--- |
149
- | `seo_onpage_audit` | Deep on-page audit of pixel width, meta CTR, heading hierarchy, image alt, and slug optimization. |
150
- | `seo_content_brief_generate` | Generates data-backed Content Outline & Brief with target word count, H1/H2/H3 structure, and FAQs. |
151
- | `seo_readability_score` | Computes Flesch Reading Ease, Flesch-Kincaid Grade Level, and Gunning Fog index. |
152
-
153
- ### Layer 5: Technical SEO & JavaScript Hydration
154
- | Tool Name | Description |
155
- | :--- | :--- |
156
- | `seo_technical_audit` | Inspects HTTP status codes, redirect chains, canonical consistency, meta robots (`noindex` leaks), and SSL. |
157
- | `seo_js_rendering_diff` | Compares raw server HTML vs hydrated client DOM (JavaScript SEO) to detect client-only content or broken tags. |
158
- | `seo_robots_txt_validate` | Validates bot crawlability against specific paths and User-Agents. |
159
- | `seo_sitemap_inspect` | Validates XML sitemaps, sitemap indexes, lastmod timestamps, and URL limit constraints. |
160
- | `seo_internal_links_analyze` | Analyzes internal link equity distribution, anchor texts, generic anchors, and nofollow flags. |
161
-
162
- ### Layer 6: Keyword Research & Intent
163
- | Tool Name | Description |
164
- | :--- | :--- |
165
- | `seo_keyword_suggestions` | Generates keyword suggestions using Google Autocomplete and Alphabet Soup expansion. |
166
- | `seo_questions_find` | Finds question queries asked by users across Google (Who, What, Where, When, Why, How, Can). |
167
- | `seo_keyword_cluster` | Clusters keyword lists into Topic Pillars and Supporting Articles using semantic similarity. |
168
- | `seo_search_intent_classify` | Classifies keywords into Informational, Navigational, Commercial, or Transactional intent. |
169
-
170
- ### Layer 7: Schema & Entity Graph
171
- | Tool Name | Description |
172
- | :--- | :--- |
173
- | `seo_entity_salience_map` | Extracts named entities, computes salience scores, and generates SPO relationship triples. |
174
- | `seo_schema_generate` | Generates validated Schema.org JSON-LD scripts (Article, FAQPage, Product, LocalBusiness, Organization). |
175
- | `seo_schema_validate` | Validates structured data against Schema.org and Google Rich Result criteria. |
176
-
177
- ### Layer 8: Performance & Maintenance
178
- | Tool Name | Description |
179
- | :--- | :--- |
180
- | `seo_pagespeed_audit` | Checks Core Web Vitals (LCP, FCP, CLS, TTFB) with performance optimization fixes. |
181
- | `seo_indexnow_submit` | Submits newly created or updated URLs directly to Bing & Yandex via the IndexNow API protocol. |
182
- | `seo_content_decay_audit` | Scans content for freshness decay (stale year references, outdated stats, broken external links). |
187
+ ### Layers 1–8: Specialized SEO & GEO Engines
188
+ - **Layer 1 (SERP & Competitors)**: `seo_serp_analyze`, `seo_competitor_content_gap`, `seo_competitor_profile`, `seo_competitor_diff`, `seo_forum_discussions_pulse`
189
+ - **Layer 2 (GEO & AI Search)**: `seo_geo_ai_readiness_audit`, `seo_llms_txt_generate`, `seo_ai_bots_robots_audit`
190
+ - **Layer 3 (Info Gain & E-E-A-T)**: `seo_information_gain_score`, `seo_eeat_audit`
191
+ - **Layer 4 (On-Page)**: `seo_onpage_audit`, `seo_content_brief_generate`, `seo_readability_score`
192
+ - **Layer 5 (Technical SEO)**: `seo_technical_audit`, `seo_js_rendering_diff`, `seo_robots_txt_validate`, `seo_sitemap_inspect`, `seo_internal_links_analyze`
193
+ - **Layer 6 (Keywords & Intent)**: `seo_keyword_suggestions`, `seo_questions_find`, `seo_keyword_cluster`, `seo_search_intent_classify`
194
+ - **Layer 7 (Schema & Entity)**: `seo_entity_salience_map`, `seo_schema_generate`, `seo_schema_validate`
195
+ - **Layer 8 (Speed & Maintenance)**: `seo_pagespeed_audit`, `seo_indexnow_submit`, `seo_content_decay_audit`
183
196
 
184
197
  ---
185
198
 
186
199
  ## 📄 License
187
200
 
188
- MIT License. Free for open-source and commercial use.
201
+ MIT License. Copyright (c) 2026 thedevbob005. Free for open-source and commercial use.
@@ -0,0 +1,7 @@
1
+ import { FrameworkAdapter } from './types.js';
2
+ export declare class AdapterRegistry {
3
+ private adapters;
4
+ getAdapterForProject(projectDir: string): FrameworkAdapter;
5
+ getAdapterById(id: string): FrameworkAdapter | undefined;
6
+ }
7
+ export declare const defaultAdapterRegistry: AdapterRegistry;
@@ -0,0 +1,30 @@
1
+ import { NextAppAdapter } from './nextAppAdapter.js';
2
+ import { NextPagesAdapter } from './nextPagesAdapter.js';
3
+ import { AstroAdapter } from './astroAdapter.js';
4
+ import { ViteReactAdapter } from './viteReactAdapter.js';
5
+ import { RemixAdapter } from './remixAdapter.js';
6
+ import { SvelteKitAdapter } from './svelteKitAdapter.js';
7
+ import { StaticAdapter } from './staticAdapter.js';
8
+ export class AdapterRegistry {
9
+ adapters = [
10
+ new NextAppAdapter(),
11
+ new NextPagesAdapter(),
12
+ new AstroAdapter(),
13
+ new RemixAdapter(),
14
+ new SvelteKitAdapter(),
15
+ new ViteReactAdapter(),
16
+ new StaticAdapter() // fallback
17
+ ];
18
+ getAdapterForProject(projectDir) {
19
+ for (const adapter of this.adapters) {
20
+ if (adapter.detect(projectDir)) {
21
+ return adapter;
22
+ }
23
+ }
24
+ return this.adapters[this.adapters.length - 1]; // fallback static
25
+ }
26
+ getAdapterById(id) {
27
+ return this.adapters.find(a => a.id === id);
28
+ }
29
+ }
30
+ export const defaultAdapterRegistry = new AdapterRegistry();
@@ -0,0 +1,17 @@
1
+ import { FrameworkAdapter, MetadataLocationInfo, CanonicalLocationInfo, SchemaLocationInfo } from './types.js';
2
+ import { DiscoveredRoute, ProjectFrameworkInfo, RouteSourceMapping } from '../types/findings.js';
3
+ export declare class AstroAdapter implements FrameworkAdapter {
4
+ id: string;
5
+ name: string;
6
+ detect(projectDir: string): boolean;
7
+ getProjectInfo(projectDir: string): ProjectFrameworkInfo;
8
+ discoverRoutes(projectDir: string): DiscoveredRoute[];
9
+ mapRouteToSource(targetUrl: string, routes: DiscoveredRoute[]): RouteSourceMapping;
10
+ findMetadataImplementation(projectDir: string, route: DiscoveredRoute): Promise<MetadataLocationInfo>;
11
+ findCanonicalDeclaration(projectDir: string, route: DiscoveredRoute): Promise<CanonicalLocationInfo>;
12
+ findSchemaDeclaration(projectDir: string, route: DiscoveredRoute): Promise<SchemaLocationInfo>;
13
+ findRobotsConfig(projectDir: string): string | null;
14
+ findSitemapConfig(projectDir: string): string | null;
15
+ findLlmsTxt(projectDir: string): string | null;
16
+ private extractDynamicParams;
17
+ }
@@ -0,0 +1,191 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ export class AstroAdapter {
4
+ id = 'astro';
5
+ name = 'Astro Framework';
6
+ detect(projectDir) {
7
+ const hasConfig = fs.existsSync(path.join(projectDir, 'astro.config.mjs')) ||
8
+ fs.existsSync(path.join(projectDir, 'astro.config.ts'));
9
+ if (hasConfig)
10
+ return true;
11
+ const pkgPath = path.join(projectDir, 'package.json');
12
+ if (fs.existsSync(pkgPath)) {
13
+ try {
14
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
15
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
16
+ return Boolean(deps['astro']);
17
+ }
18
+ catch { }
19
+ }
20
+ return false;
21
+ }
22
+ getProjectInfo(projectDir) {
23
+ const pkgPath = path.join(projectDir, 'package.json');
24
+ let pkg = {};
25
+ if (fs.existsSync(pkgPath)) {
26
+ try {
27
+ pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
28
+ }
29
+ catch { }
30
+ }
31
+ const hasSrcPages = fs.existsSync(path.join(projectDir, 'src/pages'));
32
+ const routesDir = hasSrcPages ? 'src/pages' : 'pages';
33
+ return {
34
+ framework: 'astro',
35
+ name: pkg.name || path.basename(projectDir),
36
+ version: pkg.dependencies?.astro || pkg.devDependencies?.astro,
37
+ packageManager: fs.existsSync(path.join(projectDir, 'pnpm-lock.yaml'))
38
+ ? 'pnpm'
39
+ : fs.existsSync(path.join(projectDir, 'yarn.lock'))
40
+ ? 'yarn'
41
+ : 'npm',
42
+ hasTypeScript: fs.existsSync(path.join(projectDir, 'tsconfig.json')),
43
+ hasSitemapConfig: Boolean(this.findSitemapConfig(projectDir)),
44
+ hasRobotsConfig: Boolean(this.findRobotsConfig(projectDir)),
45
+ hasLlmsTxt: Boolean(this.findLlmsTxt(projectDir)),
46
+ rootDir: path.resolve(projectDir),
47
+ routesDir,
48
+ devCommand: 'npm run dev',
49
+ defaultDevPort: 4321
50
+ };
51
+ }
52
+ discoverRoutes(projectDir) {
53
+ const info = this.getProjectInfo(projectDir);
54
+ const fullRoutesDir = path.join(projectDir, info.routesDir || 'src/pages');
55
+ const discovered = [];
56
+ if (!fs.existsSync(fullRoutesDir))
57
+ return discovered;
58
+ const scanDir = (currentDir, routePrefix) => {
59
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true });
60
+ for (const entry of entries) {
61
+ const entryPath = path.join(currentDir, entry.name);
62
+ if (entry.isDirectory()) {
63
+ const nextPrefix = routePrefix === '/' ? `/${entry.name}` : `${routePrefix}/${entry.name}`;
64
+ scanDir(entryPath, nextPrefix);
65
+ }
66
+ else if (entry.isFile() && /\.(astro|md|mdx)$/.test(entry.name)) {
67
+ const baseName = entry.name.replace(/\.(astro|md|mdx)$/, '');
68
+ let routePath = routePrefix;
69
+ if (baseName !== 'index') {
70
+ routePath = routePrefix === '/' ? `/${baseName}` : `${routePrefix}/${baseName}`;
71
+ }
72
+ if (routePath === '')
73
+ routePath = '/';
74
+ const relFile = path.relative(projectDir, entryPath).replace(/\\/g, '/');
75
+ const content = fs.readFileSync(entryPath, 'utf-8');
76
+ const dynamicParams = this.extractDynamicParams(routePath);
77
+ discovered.push({
78
+ routePath,
79
+ sourceFilePath: relFile,
80
+ isDynamic: dynamicParams.length > 0,
81
+ dynamicParams,
82
+ routeType: 'page',
83
+ hasMetadataExport: /title\s*=|description\s*=|astro:head|<title/.test(content),
84
+ hasGenerateMetadata: false,
85
+ hasSchemaMarkup: /application\/ld\+json/.test(content),
86
+ hasHeadComponent: /<head|astro:head|<title/.test(content),
87
+ isClientComponent: false
88
+ });
89
+ }
90
+ }
91
+ };
92
+ scanDir(fullRoutesDir, '/');
93
+ return discovered;
94
+ }
95
+ mapRouteToSource(targetUrl, routes) {
96
+ let urlPath = targetUrl;
97
+ try {
98
+ if (targetUrl.startsWith('http')) {
99
+ urlPath = new URL(targetUrl).pathname;
100
+ }
101
+ }
102
+ catch {
103
+ urlPath = targetUrl;
104
+ }
105
+ urlPath = urlPath.replace(/\/$/, '') || '/';
106
+ for (const r of routes) {
107
+ const clean = r.routePath.replace(/\/$/, '') || '/';
108
+ if (clean === urlPath) {
109
+ return {
110
+ urlPath,
111
+ matchedRoute: r,
112
+ sourceFilePath: r.sourceFilePath,
113
+ confidence: 1.0,
114
+ resolutionMethod: 'exact_match'
115
+ };
116
+ }
117
+ }
118
+ return {
119
+ urlPath,
120
+ confidence: 0.0,
121
+ resolutionMethod: 'unmapped'
122
+ };
123
+ }
124
+ async findMetadataImplementation(projectDir, route) {
125
+ const fullPath = path.join(projectDir, route.sourceFilePath);
126
+ if (!fs.existsSync(fullPath))
127
+ return { hasMetadata: false, type: 'none' };
128
+ const content = fs.readFileSync(fullPath, 'utf-8');
129
+ const hasMeta = /<title\b|<meta\s+name=["']description["']/i.test(content) || /title\s*:/i.test(content);
130
+ return {
131
+ hasMetadata: hasMeta,
132
+ type: hasMeta ? 'jsx_head' : 'none'
133
+ };
134
+ }
135
+ async findCanonicalDeclaration(projectDir, route) {
136
+ const fullPath = path.join(projectDir, route.sourceFilePath);
137
+ if (!fs.existsSync(fullPath))
138
+ return { hasCanonical: false, type: 'none' };
139
+ const content = fs.readFileSync(fullPath, 'utf-8');
140
+ const hasCanonical = /rel=["']canonical["']/i.test(content);
141
+ return {
142
+ hasCanonical,
143
+ type: hasCanonical ? 'link_jsx_tag' : 'none'
144
+ };
145
+ }
146
+ async findSchemaDeclaration(projectDir, route) {
147
+ const fullPath = path.join(projectDir, route.sourceFilePath);
148
+ if (!fs.existsSync(fullPath))
149
+ return { hasSchema: false, typesFound: [] };
150
+ const content = fs.readFileSync(fullPath, 'utf-8');
151
+ const hasSchema = /application\/ld\+json/i.test(content);
152
+ return {
153
+ hasSchema,
154
+ typesFound: hasSchema ? ['JSON-LD'] : []
155
+ };
156
+ }
157
+ findRobotsConfig(projectDir) {
158
+ const paths = ['public/robots.txt', 'robots.txt'];
159
+ for (const p of paths) {
160
+ if (fs.existsSync(path.join(projectDir, p)))
161
+ return p;
162
+ }
163
+ return null;
164
+ }
165
+ findSitemapConfig(projectDir) {
166
+ const paths = ['public/sitemap.xml', 'sitemap.xml', 'src/pages/sitemap.xml.ts'];
167
+ for (const p of paths) {
168
+ if (fs.existsSync(path.join(projectDir, p)))
169
+ return p;
170
+ }
171
+ return null;
172
+ }
173
+ findLlmsTxt(projectDir) {
174
+ const paths = ['public/llms.txt', 'llms.txt'];
175
+ for (const p of paths) {
176
+ if (fs.existsSync(path.join(projectDir, p)))
177
+ return p;
178
+ }
179
+ return null;
180
+ }
181
+ extractDynamicParams(routePath) {
182
+ const params = [];
183
+ const matches = routePath.match(/\[\.{0,3}([a-zA-Z0-9_-]+)\]/g);
184
+ if (matches) {
185
+ for (const m of matches) {
186
+ params.push(m.replace(/[\[\].]/g, ''));
187
+ }
188
+ }
189
+ return params;
190
+ }
191
+ }
@@ -0,0 +1,17 @@
1
+ import { FrameworkAdapter, MetadataLocationInfo, CanonicalLocationInfo, SchemaLocationInfo } from './types.js';
2
+ import { DiscoveredRoute, ProjectFrameworkInfo, RouteSourceMapping } from '../types/findings.js';
3
+ export declare class NextAppAdapter implements FrameworkAdapter {
4
+ id: string;
5
+ name: string;
6
+ detect(projectDir: string): boolean;
7
+ getProjectInfo(projectDir: string): ProjectFrameworkInfo;
8
+ discoverRoutes(projectDir: string): DiscoveredRoute[];
9
+ mapRouteToSource(targetUrl: string, routes: DiscoveredRoute[]): RouteSourceMapping;
10
+ findMetadataImplementation(projectDir: string, route: DiscoveredRoute): Promise<MetadataLocationInfo>;
11
+ findCanonicalDeclaration(projectDir: string, route: DiscoveredRoute): Promise<CanonicalLocationInfo>;
12
+ findSchemaDeclaration(projectDir: string, route: DiscoveredRoute): Promise<SchemaLocationInfo>;
13
+ findRobotsConfig(projectDir: string): string | null;
14
+ findSitemapConfig(projectDir: string): string | null;
15
+ findLlmsTxt(projectDir: string): string | null;
16
+ private extractDynamicParams;
17
+ }