@softspark/ai-toolkit 4.20.0 → 4.22.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.
@@ -0,0 +1,304 @@
1
+ # SEO Scanner Categories
2
+
3
+ ### Category 1: HTML Semantics & W3C
4
+
5
+ Scan HTML/JSX/Vue/Svelte/Astro templates for W3C HTML5 compliance.
6
+
7
+ | Pattern | Severity | Confidence | Description |
8
+ |---------|----------|------------|-------------|
9
+ | `<html>` without `lang` attribute | HIGH | definitive | HTML5 §3.2.6 — `lang` required for SEO + a11y |
10
+ | Missing `<meta charset="utf-8">` in `<head>` | HIGH | definitive | HTML5 §4.2.5.5 — required first |
11
+ | Missing `<meta name="viewport">` | HIGH | definitive | Mobile-first indexing requires viewport |
12
+ | Multiple `<h1>` per page/route component | WARN | heuristic | One H1 per document is standard SEO practice |
13
+ | No `<h1>` in page component | WARN | heuristic | Every indexable page should have H1 |
14
+ | Heading level skip (h1 → h3) | WARN | heuristic | Document outline breaks assistive tech + crawlers |
15
+ | Missing landmarks (`<main>`, `<nav>`, `<header>`, `<footer>`) | WARN | heuristic | Semantic HTML aids both a11y and crawlers |
16
+ | Missing `<!DOCTYPE html>` | HIGH | definitive | Triggers quirks mode in older browsers |
17
+
18
+ See: [w3c-guidelines.md](w3c-guidelines.md)
19
+
20
+ ---
21
+
22
+ ### Category 2: Meta & Open Graph
23
+
24
+ Check `<head>` composition in entry HTML, framework metadata exports, and route-level metadata.
25
+
26
+ | Pattern | Severity | Confidence | Description |
27
+ |---------|----------|------------|-------------|
28
+ | Missing `<title>` / framework title | HIGH | definitive | Required for SERP display |
29
+ | `<title>` >60 chars OR <10 chars | WARN | definitive | Recommended 50–60 char range |
30
+ | Missing `<meta name="description">` | HIGH | definitive | Required for SERP snippets |
31
+ | Description >160 chars OR <50 chars | WARN | definitive | Recommended 150–160 char range |
32
+ | Missing `<link rel="canonical">` on indexable pages | HIGH | definitive | Prevents duplicate-content dilution |
33
+ | `<meta name="robots" content="noindex">` on production route | WARN | heuristic | Confirm intentional — blocks indexing |
34
+ | Missing OG tags: `og:title`, `og:description`, `og:image`, `og:url`, `og:type` | WARN | definitive | Required for rich social cards |
35
+ | Missing Twitter Card (`twitter:card`) | WARN | definitive | Required for Twitter/X rich previews |
36
+ | OG image without absolute URL | WARN | definitive | OG spec requires absolute URLs |
37
+
38
+ **Framework adapters**:
39
+ - **Next.js App Router**: look for `export const metadata = { ... }` or `generateMetadata()` in `layout.tsx`/`page.tsx`.
40
+ - **Next.js Pages Router**: look for `<Head>` from `next/head`.
41
+ - **Nuxt**: look for `useHead()` / `definePageMeta({ title, ... })`.
42
+ - **Astro**: look for `<BaseHead>` component or direct `<meta>` in layout.
43
+ - **Gatsby**: look for `<Helmet>` from `react-helmet`.
44
+ - **SvelteKit**: look for `<svelte:head>` blocks.
45
+ - **SPAs (Vue/Vite/CRA/Angular)**: look for `react-helmet-async`, `vue-meta`, `@angular/platform-browser`'s `Meta`/`Title` services. Flag runtime-only meta as a rendering-crawlability issue (Category 7).
46
+
47
+ ---
48
+
49
+ ### Category 3: Structured Data / Schema.org
50
+
51
+ Scan for JSON-LD (`<script type="application/ld+json">`) presence and correctness on key page types.
52
+
53
+ | Pattern | Severity | Confidence | Description |
54
+ |---------|----------|------------|-------------|
55
+ | No JSON-LD on article/blog route | WARN | heuristic | `Article` schema improves rich results |
56
+ | JSON-LD missing `@context` | HIGH | definitive | Must be `https://schema.org` |
57
+ | JSON-LD missing `@type` | HIGH | definitive | Type declaration is required |
58
+ | `Article` missing `headline` / `author` / `datePublished` | WARN | definitive | Required properties per schema.org |
59
+ | `FAQPage` missing `mainEntity` array | WARN | definitive | FAQ rich result needs Q&A pairs |
60
+ | `BreadcrumbList` missing `itemListElement` | WARN | definitive | Breadcrumb rich result needs list |
61
+ | `Organization` missing `name` / `url` / `logo` | WARN | definitive | Knowledge Graph signals |
62
+ | `Product` missing `name` / `offers` / `aggregateRating` | WARN | definitive | Product rich results |
63
+ | `LocalBusiness` missing `address` / `telephone` / `openingHours` | WARN | definitive | Local SEO signals |
64
+
65
+ See: [schema-types.md](schema-types.md) for required-property matrix.
66
+
67
+ ---
68
+
69
+ ### Category 4: Hreflang & i18n
70
+
71
+ Scan all locale variants for hreflang correctness.
72
+
73
+ | Pattern | Severity | Confidence | Description |
74
+ |---------|----------|------------|-------------|
75
+ | Hreflang pair not bidirectional (A→B but not B→A) | HIGH | definitive | Google ignores unidirectional hreflang |
76
+ | Missing `hreflang="x-default"` | WARN | definitive | Fallback required for unmatched locales |
77
+ | Missing self-referencing hreflang tag | WARN | definitive | Each version must reference itself |
78
+ | Invalid BCP 47 code (e.g., `en_US` instead of `en-US`) | HIGH | definitive | RFC 5646 requires hyphen-separated subtags |
79
+ | Unknown language code (not ISO 639-1) | HIGH | definitive | Invalid language subtag |
80
+ | Unknown region code (not ISO 3166-1 alpha-2) | HIGH | definitive | Invalid region subtag |
81
+ | Hreflang points to URL returning canonical to different URL | WARN | heuristic | Canonical must match hreflang target |
82
+
83
+ ---
84
+
85
+ ### Category 5: Core Web Vitals (Static Signals)
86
+
87
+ Detect code patterns that cause CWV regressions. Covers LCP, INP, CLS, resource hints, and above-the-fold optimization.
88
+
89
+ #### 5a. LCP (Largest Contentful Paint, target <2.5s)
90
+
91
+ | Pattern | Severity | Confidence | Description |
92
+ |---------|----------|------------|-------------|
93
+ | `<img>` without `width`/`height` attributes | HIGH | definitive | Causes CLS + delays LCP |
94
+ | Above-the-fold `<img>` without `fetchpriority="high"` (or framework equivalent) | HIGH | heuristic | LCP image must be prioritized |
95
+ | Above-the-fold `<img loading="lazy">` | HIGH | definitive | Actively harmful — delays LCP |
96
+ | `@font-face` without `font-display` | HIGH | definitive | Blocks text paint |
97
+ | Missing `<link rel="preload" as="image">` for known hero image | WARN | heuristic | Preload accelerates LCP |
98
+ | Missing `<link rel="preload" as="font" crossorigin>` for self-hosted webfonts | WARN | heuristic | Fonts are a common LCP blocker |
99
+ | Missing `<link rel="preconnect">` for 3rd-party font/image/CDN origins on critical path | WARN | heuristic | Saves ~100–300ms per origin |
100
+ | Render-blocking `<link rel="stylesheet">` without `media` split or critical-inline | WARN | heuristic | Blocks first paint |
101
+ | Responsive image: `<img>` >600px without `srcset`+`sizes` or `<picture>` | WARN | heuristic | Over-fetches on mobile |
102
+ | **Next.js**: `<img>` used instead of `next/image` in route component | WARN | definitive | Misses automatic optimization |
103
+ | **Next.js**: `next/image` without `priority` on detected LCP element | HIGH | heuristic | LCP will under-perform |
104
+ | **Nuxt**: `<img>` instead of `<NuxtImg>`/`<NuxtPicture>` | WARN | definitive | Misses auto-optimization |
105
+ | **Astro**: `<img>` instead of `<Image>` from `astro:assets` | WARN | definitive | Misses auto-optimization |
106
+ | **Gatsby**: `<img>` instead of `GatsbyImage` | WARN | definitive | Misses auto-optimization |
107
+
108
+ #### 5b. INP (Interaction to Next Paint, target <200ms)
109
+
110
+ | Pattern | Severity | Confidence | Description |
111
+ |---------|----------|------------|-------------|
112
+ | `<script>` in `<head>` without `async`/`defer` | HIGH | definitive | Render-blocking |
113
+ | Third-party analytics/chat/ads without `async`/`defer` or framework lazy strategy | WARN | definitive | Blocks main thread |
114
+ | `document.write` usage | HIGH | definitive | Blocks parser; disabled by modern browsers |
115
+ | Heavy top-level `useEffect(() => {...}, [])` (many sync calls) | WARN | heuristic | Long tasks delay INP |
116
+ | Client bundle estimated >300KB gzipped gating interaction | WARN | heuristic | Excessive JS delays hydration + INP |
117
+ | **Next.js**: `<Script>` without `strategy` prop on non-critical scripts | WARN | definitive | Defaults to `afterInteractive` — often not optimal |
118
+ | Missing `fetchpriority="low"` on deferrable below-the-fold resources | INFO | heuristic | Helps browser prioritize LCP |
119
+
120
+ #### 5c. CLS (Cumulative Layout Shift, target <0.1)
121
+
122
+ | Pattern | Severity | Confidence | Description |
123
+ |---------|----------|------------|-------------|
124
+ | Images without `width`/`height` or `aspect-ratio` CSS | HIGH | definitive | Primary CLS cause |
125
+ | Iframes (YouTube/maps/ads) without dimensions or aspect-ratio | HIGH | definitive | Embeds shift layout |
126
+ | Dynamically injected ads/embeds without reserved placeholder space | WARN | heuristic | Shifts layout on load |
127
+ | `@font-face` without `font-display: swap`/`optional` | WARN | definitive | FOIT/FOUT shifts |
128
+ | SSR hydration mismatch: `typeof window` branches rendering different content | WARN | heuristic | Hydration-triggered shift |
129
+ | Skeleton → content of different height | WARN | heuristic | Load-state shift |
130
+
131
+ #### 5d. Resource Hints & Route Prefetching
132
+
133
+ | Pattern | Severity | Confidence | Description |
134
+ |---------|----------|------------|-------------|
135
+ | `<link rel="preload">` for non-critical resource | WARN | heuristic | Wastes bandwidth + contention |
136
+ | Next-route not prefetched when framework supports it (Next `<Link>`, Nuxt `<NuxtLink>`, SvelteKit `data-sveltekit-preload-data`) | INFO | heuristic | Hurts soft-navigation UX |
137
+ | External origin referenced in critical path without `<link rel="preconnect">` | WARN | definitive | Adds 100–300ms per origin |
138
+ | Less-critical external origin without `<link rel="dns-prefetch">` | INFO | heuristic | Lightweight fallback |
139
+ | ESM chunks on critical path without `<link rel="modulepreload">` | INFO | heuristic | Helps browser parse ahead |
140
+ | `<link rel="preload">` appears AFTER resource that uses it in document order | WARN | heuristic | Preload must come first to help |
141
+ | >6 `<link rel="preload">` directives on one page | WARN | heuristic | Over-hinting — browsers throttle |
142
+
143
+ #### 5e. Above-the-Fold Heuristic
144
+
145
+ "Above-the-fold" candidates (confidence: heuristic):
146
+ - First `<img>` / `<Image>` / `<NuxtImg>` / `<Image from 'astro:assets'>` / `GatsbyImage` inside a page/route component.
147
+ - First child of `<main>` or `<section>`.
148
+ - Components named `Hero`, `Banner`, `Masthead`, `Jumbotron`, `HeroSection`, `CoverImage`.
149
+ - Images inside `<header>` that appear before any scroll-margin content.
150
+
151
+ Rules for ATF elements:
152
+ - MUST have explicit `width` + `height`.
153
+ - MUST have high priority (`fetchpriority="high"` or `priority` prop).
154
+ - MUST NOT have `loading="lazy"`.
155
+ - SHOULD have a matching `<link rel="preload">` entry.
156
+
157
+ Rules for below-the-fold:
158
+ - SHOULD have `loading="lazy"` + `decoding="async"`.
159
+ - MAY have `fetchpriority="low"`.
160
+
161
+ See: [core-web-vitals.md](core-web-vitals.md)
162
+
163
+ ---
164
+
165
+ ### Category 6: GEO (Generative Engine Optimization)
166
+
167
+ Content structure for AI answer engines (ChatGPT, Perplexity, Google AI Overviews, Bing Copilot, Google AI Mode). **Most findings here are severity `INFO` or `WARN`** — guidance based on measured citation patterns, not penalty-causing.
168
+
169
+ Google's retrieval stage splits content into chunks of ≤500 tokens (~375 words). Each section must be a self-contained answer unit. See [ai-pipeline.md](ai-pipeline.md) for the full 4-stage pipeline and 7 ranking signals. See [content-citability.md](content-citability.md) for chunk anatomy, semantic triples, and hedging patterns.
170
+
171
+ | Pattern | Severity | Confidence | Description |
172
+ |---------|----------|------------|-------------|
173
+ | No `FAQPage` schema on FAQ-style content | INFO | heuristic | Highly extractable by LLMs |
174
+ | No `speakable` schema on summary content | INFO | heuristic | Voice/audio answer engines |
175
+ | H2 section body exceeds ~375 words without an H3 sub-heading | WARN | heuristic | Exceeds single chunk boundary (~500 tokens); AI cannot extract cleanly — split with H3 |
176
+ | First paragraph under a heading exceeds 60 words before a concrete fact, number, or direct recommendation | INFO | heuristic | AI extracts first 2–3 sentences as the answer; preamble displaces the answer |
177
+ | Hedging language in recommendation or product context: "may be", "might be", "could be", "worth considering", "for many", "for most people" | INFO | heuristic | AI skips hedged claims; Jetstream signal rewards declarative recommendations (see [content-citability.md](content-citability.md)) |
178
+ | No decision framework ("if X → choose Y" / "for X, use Y") in guide or category content | INFO | heuristic | Decision frameworks are the most-cited AI construction; covers Jetstream cross-attention signal |
179
+ | No contrast or comparison ("X vs Y", "unlike X", "in contrast to X") in content with comparative headings | INFO | heuristic | Jetstream directly rewards explicit contrasts; absence reduces AI citation probability |
180
+ | No negative definition ("not recommended for", "not suitable for", "avoid if") on product or category pages | INFO | heuristic | Covers AI exclusion sub-queries ("which product is not for stomach sleepers?") |
181
+ | Author name uses generic placeholder: "Admin", "Team", "Staff", "Editor", or no author at all | WARN | heuristic | E-E-A-T Experience signal requires a real named author; generic names suppressed by Google Bury Rules |
182
+ | Author block contains fewer than 30 words of bio text near the author name | INFO | heuristic | LLM answer engines use author credentials as an authority signal; stub bios do not qualify |
183
+ | Article `dateModified` (JSON-LD or `<time>`) is older than 13 weeks with no visible update notice | WARN | heuristic | 50% of top AI-cited content updated within 13 weeks (Blyskall, 40M AI Overviews study); stale content drops from citation pools |
184
+ | Missing explicit citation/source markup (`<cite>`, author bylines) | INFO | heuristic | LLM answer engines prefer attributable sources |
185
+ | No `<q>` or quote schema on quoted content | INFO | heuristic | Aids AI extraction |
186
+ | No Q&A structure on how-to content | INFO | heuristic | LLMs favor structured Q&A |
187
+ | Heavy reliance on `<div>` over semantic HTML | INFO | heuristic | Semantic HTML improves AI parsing |
188
+ | Key facts hidden behind JS interactions (tabs, accordions) | INFO | heuristic | LLMs see initial DOM only |
189
+
190
+ See: [geo-guidelines.md](geo-guidelines.md), [content-citability.md](content-citability.md), [ai-pipeline.md](ai-pipeline.md)
191
+
192
+ ---
193
+
194
+ ### Category 7: Rendering Mode & SPA/CSR/SSG Crawlability ⭐
195
+
196
+ **The most critical category for JS apps.** A CSR-only app with no prerendering is effectively invisible to most crawlers.
197
+
198
+ | Pattern | Severity | Confidence | Description |
199
+ |---------|----------|------------|-------------|
200
+ | Entry HTML contains only mount point (`<div id="root">` or `<div id="app">`) with no prerendered content, and no SSR/SSG configured | HIGH | definitive | Crawlers see empty page |
201
+ | Meta/title set only in JS runtime (react-helmet-async, vue-meta, `document.title = ...`) with no SSR/SSG fallback | HIGH | definitive | Public routes won't have crawlable meta |
202
+ | `HashRouter` / hash-based routing (`/#/about`) on public routes | HIGH | definitive | Google ignores fragments for indexing |
203
+ | CSR app without `<noscript>` fallback containing meaningful content | WARN | heuristic | Minimum no-JS signal for crawlers |
204
+ | **Next.js**: `'use client'` at top of every page/layout forcing CSR | WARN | heuristic | Defeats SSR/SSG benefits |
205
+ | **Next.js**: Content page missing `generateMetadata` / static `metadata` export | WARN | heuristic | No crawlable metadata |
206
+ | **Next.js**: `dynamic(..., { ssr: false })` wrapping LCP / above-the-fold content | HIGH | definitive | Blocks both SSR and LCP |
207
+ | **Nuxt**: `ssr: false` in config or route with public content | WARN | heuristic | Disables SSR intentionally |
208
+ | **Astro**: `client:only` on hero/content components | WARN | heuristic | Component not prerendered |
209
+ | **SvelteKit**: `export const ssr = false` on public route | WARN | heuristic | Disables SSR |
210
+ | **Gatsby**: route excluded from prerender (`gatsby-plugin-exclude`) | WARN | heuristic | Verify intent |
211
+ | **Angular SPA**: project uses `@angular/core` without `@angular/ssr` or `@nguniversal/*` | HIGH | definitive | Default Angular is CSR-only |
212
+ | **Vue SPA / React SPA / CRA / Vite-SPA**: no prerender plugin detected (no `vite-plugin-ssr`, `react-snap`, `prerender-spa-plugin`, `vite-plugin-prerender`) | HIGH | definitive | Content invisible to crawlers |
213
+ | `suppressHydrationWarning` overuse (>3 occurrences) | WARN | heuristic | Masks real hydration mismatches |
214
+ | `typeof window !== 'undefined'` / `isBrowser` checks in render paths | WARN | heuristic | Often signals hydration mismatch |
215
+ | Static `robots.txt` references dynamic routes that aren't prerendered | WARN | heuristic | Crawlers hit empty pages |
216
+ | `prerender.io` / `rendertron` / dynamic-rendering middleware detected | INFO | definitive | Legacy pattern — Google now prefers SSR/SSG |
217
+
218
+ See: [spa-ssg-patterns.md](spa-ssg-patterns.md)
219
+
220
+ ---
221
+
222
+ ### Category 8: Technical SEO
223
+
224
+ | Pattern | Severity | Confidence | Description |
225
+ |---------|----------|------------|-------------|
226
+ | Missing `robots.txt` | HIGH | definitive | Blocks crawler directives + sitemap reference |
227
+ | `robots.txt` contains `Disallow: /` in production build | HIGH | definitive | Blocks entire site |
228
+ | Missing `sitemap.xml` / framework sitemap generator | HIGH | definitive | Slows discovery |
229
+ | `robots.txt` missing `Sitemap:` directive | WARN | definitive | Crawlers may not find sitemap |
230
+ | Canonical URLs inconsistent with actual deployed URLs | WARN | heuristic | Dilutes link equity |
231
+ | Canonical URL includes query params on parametrized pages (e.g., `?q=`, `?page=`, `?sort=`) | HIGH | heuristic | Canonical must point to clean base URL, not parametrized variant — else each query variant is a duplicate |
232
+ | Site has search feature (detected: `<input type="search">`, `<form action="/search">`, route `/search`, `?q=` / `?query=` / `?s=` / `?search=`) but `robots.txt` does NOT `Disallow` the search URL pattern | HIGH | heuristic | Parametrized search URLs create unlimited duplicate-content pages — crawl budget waste + index bloat |
233
+ | Site has faceted navigation (filters, sort params, pagination like `?filter=`, `?sort=`, `?page=`, `?color=`) without `robots.txt` Disallow rules OR parameter-handling via canonical | WARN | heuristic | Faceted URLs multiply indexable variants exponentially |
234
+ | Search result page (SRP) missing `<meta name="robots" content="noindex, follow">` | HIGH | heuristic | SRPs are thin/duplicate content per Google Search Essentials; indexing wastes crawl budget |
235
+ | Search result page missing self-referencing canonical OR canonical with dynamic query in it | WARN | heuristic | SRP should either canonical to clean `/search` or be noindexed entirely |
236
+ | Parametrized URLs (tracking: `utm_*`, `gclid`, `fbclid`, `ref=`) served without canonical to clean URL | HIGH | heuristic | Tracking params create duplicate URLs — canonical must strip them |
237
+ | Trailing-slash inconsistency (some pages `/about/`, some `/about`) | WARN | heuristic | Duplicate-content risk |
238
+ | HTTPS not enforced (hardcoded `http://` internal links) | WARN | definitive | Mixed-content + security |
239
+ | No 404 page / no custom `not-found` route | WARN | heuristic | Default 404s hurt UX |
240
+ | Meta `robots: noindex,nofollow` on indexable production routes | HIGH | heuristic | Blocks indexing — verify intent |
241
+
242
+ **Parameter-handling guidance**: Google deprecated the Search Console URL Parameters tool in April 2022. Today the only signals are:
243
+ 1. **Canonical tags** — every parametrized variant must `<link rel="canonical">` to the clean base URL.
244
+ 2. **`robots.txt` Disallow rules** — block crawlers from following parameter patterns entirely (`Disallow: /*?q=*`, `Disallow: /search?*`).
245
+ 3. **`noindex` meta** — allow crawl (for link discovery) but prevent indexing on SRPs and thin faceted pages.
246
+
247
+ Choose ONE strategy per parameter type — mixing `Disallow` + `noindex` is contradictory (Disallow prevents crawler from ever seeing the noindex directive).
248
+
249
+ **Example `robots.txt` for a site with search**:
250
+ ```
251
+ User-agent: *
252
+ Disallow: /search?*
253
+ Disallow: /*?q=*
254
+ Disallow: /*?query=*
255
+ Disallow: /*?s=*
256
+ Disallow: /*?utm_*
257
+ Disallow: /*?gclid=*
258
+ Disallow: /*?fbclid=*
259
+ Allow: /
260
+
261
+ Sitemap: https://example.com/sitemap.xml
262
+ ```
263
+
264
+ **Example canonical on a parametrized page** (`/products?category=shoes&color=red&sort=price`):
265
+ ```html
266
+ <link rel="canonical" href="https://example.com/products">
267
+ ```
268
+
269
+ The canonical points to the clean page; the specific filter combination is a view, not a distinct URL.
270
+
271
+ ---
272
+
273
+ ### Category 9: Accessibility for SEO
274
+
275
+ Accessibility ↔ SEO overlap. WCAG compliance improves ranking signals.
276
+
277
+ | Pattern | Severity | Confidence | Description |
278
+ |---------|----------|------------|-------------|
279
+ | `<img>` missing `alt` attribute | WARN | definitive | WCAG 1.1.1 + image SEO |
280
+ | `<img alt="">` on informational image | WARN | heuristic | Empty alt only for decorative |
281
+ | Icon-only `<button>` without `aria-label` | WARN | definitive | Screen readers + semantic crawlers |
282
+ | Form `<input>` without associated `<label>` | WARN | definitive | WCAG 3.3.2 |
283
+ | `<div>` used for interactive element (click handler on `<div>`) | WARN | heuristic | Should be `<button>` or `<a>` |
284
+ | Link text is "click here" / "read more" | WARN | heuristic | Anchor text is a ranking signal |
285
+ | `<a>` without `href` (fake link) | WARN | definitive | Not crawlable |
286
+
287
+ ---
288
+
289
+ ### Category 10: Topical Authority & Cluster Architecture
290
+
291
+ Topical authority is the degree to which a domain is recognised as an expert source across an entire topic, not just individual pages. AI retrieval (Gecko Score / semantic embedding) rewards domains with deep, interlinked coverage. Classical SEO also benefits — Senuto's study of 212K phrases across 7,200 semantic groups showed topical coverage dominates top-10 rankings independently of individual technical metrics.
292
+
293
+ | Pattern | Severity | Confidence | Description |
294
+ |---------|----------|------------|-------------|
295
+ | Long-form page (>800 words) has internal link density below 1 link per 800 characters of body text | WARN | heuristic | Google's internal linking guideline: ~1 contextual internal link per 800 chars; low density = weak cluster signal |
296
+ | Internal link uses generic anchor text: "click here", "read more", "here", "this page", "learn more" | WARN | definitive | Anchor text is a topical signal; descriptive claim-based anchors transfer semantic context to the linked page |
297
+ | Page >2,000 words with no outbound internal links to topically related pages | INFO | heuristic | Pillar pages must link out to cluster articles; absence breaks the pillar→cluster signal and reduces Gecko relevance |
298
+ | Page has >500 words of indexable content with zero detected inbound internal links (orphan page) | WARN | heuristic | Orphan pages receive minimal crawl budget and no authority pass-through; every content page needs at least one inbound link |
299
+ | Content page URL slug contains numeric IDs, UUIDs, or is purely numeric (e.g., `/post/12345`, `/p/abc-uuid`) | WARN | heuristic | Natural-language slugs (5–7 descriptive words) show +11.4% AI citation rate vs. ID-based URLs (Blyskall study) |
300
+ | Two or more pages on the same domain target the same primary keyword in H1 and title | WARN | heuristic | Keyword cannibalization: pages compete against each other, diluting authority; consolidate into pillar + cluster |
301
+
302
+ **Topical authority strategy note:** Query Fan Out means AI generates 50+ sub-queries per user question, 95% of which have zero Monthly Search Volume in any keyword tool. Covering a topic with a pillar + cluster architecture answers the full sub-query space that keyword tools cannot see. See [ai-pipeline.md](ai-pipeline.md).
303
+
304
+ ---
@@ -0,0 +1,296 @@
1
+ {
2
+ "_comment": "Public surface snapshot. Removing an entry is a breaking change: see BACKWARD_COMPATIBILITY.md, and record it in DECISIONS.md. Regenerate deliberately with `python3 scripts/surface_manifest.py --update` and read the diff — never as a reflex to green a red build.",
3
+ "skills": [
4
+ "a11y-validate",
5
+ "agent-creator",
6
+ "analyze",
7
+ "api-patterns",
8
+ "app-builder",
9
+ "architecture-audit",
10
+ "architecture-decision",
11
+ "biz-scan",
12
+ "brainstorm",
13
+ "brand-voice",
14
+ "briefing",
15
+ "build",
16
+ "chaos",
17
+ "ci",
18
+ "ci-cd-patterns",
19
+ "clean-code",
20
+ "command-creator",
21
+ "commit",
22
+ "content-moderation-patterns",
23
+ "council",
24
+ "cpp-rules",
25
+ "csharp-patterns",
26
+ "csharp-rules",
27
+ "cve-scan",
28
+ "dart-rules",
29
+ "database-patterns",
30
+ "debug",
31
+ "deep-research",
32
+ "deploy",
33
+ "design-an-interface",
34
+ "design-engineering",
35
+ "docker-devops",
36
+ "docs",
37
+ "documentation-standards",
38
+ "ecommerce-patterns",
39
+ "evaluate",
40
+ "evolve",
41
+ "explain",
42
+ "explore",
43
+ "fix",
44
+ "flutter-patterns",
45
+ "git-mastery",
46
+ "golang-rules",
47
+ "grill-me",
48
+ "health",
49
+ "hipaa-validate",
50
+ "hook-creator",
51
+ "index",
52
+ "instinct-review",
53
+ "introspect",
54
+ "java-patterns",
55
+ "java-rules",
56
+ "json-mode-patterns",
57
+ "kotlin-patterns",
58
+ "kotlin-rules",
59
+ "lint",
60
+ "mcp-builder",
61
+ "mcp-patterns",
62
+ "medplum-rules",
63
+ "mem-search",
64
+ "migrate",
65
+ "migration-patterns",
66
+ "model-routing-patterns",
67
+ "night-watch",
68
+ "observability-patterns",
69
+ "onboard",
70
+ "orchestrate",
71
+ "panic",
72
+ "performance-profiling",
73
+ "persona",
74
+ "php-rules",
75
+ "plan",
76
+ "plugin-creator",
77
+ "pr",
78
+ "prd-to-issues",
79
+ "prd-to-plan",
80
+ "predict",
81
+ "prompt-caching-patterns",
82
+ "python-rules",
83
+ "qa-session",
84
+ "rag-patterns",
85
+ "refactor",
86
+ "refactor-plan",
87
+ "repeat",
88
+ "research-mastery",
89
+ "review",
90
+ "rollback",
91
+ "ruby-patterns",
92
+ "ruby-rules",
93
+ "rust-patterns",
94
+ "rust-rules",
95
+ "security-patterns",
96
+ "seo-validate",
97
+ "skill-audit",
98
+ "skill-creator",
99
+ "subagent-development",
100
+ "swarm",
101
+ "swift-patterns",
102
+ "swift-rules",
103
+ "tdd",
104
+ "test",
105
+ "testing-patterns",
106
+ "triage-issue",
107
+ "typescript-patterns",
108
+ "typescript-rules",
109
+ "ubiquitous-language",
110
+ "verification-before-completion",
111
+ "workflow",
112
+ "write-a-prd"
113
+ ],
114
+ "agents": [
115
+ "ai-engineer",
116
+ "backend-specialist",
117
+ "business-intelligence",
118
+ "chaos-monkey",
119
+ "chief-of-staff",
120
+ "code-archaeologist",
121
+ "code-reviewer",
122
+ "command-expert",
123
+ "data-analyst",
124
+ "data-scientist",
125
+ "database-architect",
126
+ "debugger",
127
+ "devops-implementer",
128
+ "documenter",
129
+ "explorer-agent",
130
+ "fact-checker",
131
+ "frontend-specialist",
132
+ "game-developer",
133
+ "incident-responder",
134
+ "infrastructure-architect",
135
+ "infrastructure-validator",
136
+ "llm-ops-engineer",
137
+ "mcp-specialist",
138
+ "mcp-testing-engineer",
139
+ "meta-architect",
140
+ "ml-engineer",
141
+ "mobile-developer",
142
+ "night-watchman",
143
+ "nlp-engineer",
144
+ "orchestrator",
145
+ "performance-optimizer",
146
+ "predictive-analyst",
147
+ "product-manager",
148
+ "project-planner",
149
+ "prompt-engineer",
150
+ "qa-automation-engineer",
151
+ "search-specialist",
152
+ "security-architect",
153
+ "security-auditor",
154
+ "seo-specialist",
155
+ "system-governor",
156
+ "tech-lead",
157
+ "technical-researcher",
158
+ "test-engineer"
159
+ ],
160
+ "skill_frontmatter_fields": [
161
+ "agent",
162
+ "allowed-tools",
163
+ "argument-hint",
164
+ "context",
165
+ "description",
166
+ "disable-model-invocation",
167
+ "effort",
168
+ "hooks",
169
+ "model",
170
+ "name",
171
+ "scripts",
172
+ "user-invocable"
173
+ ],
174
+ "agent_frontmatter_fields": [
175
+ "color",
176
+ "description",
177
+ "model",
178
+ "name",
179
+ "skills",
180
+ "tools"
181
+ ],
182
+ "hook_scripts": [
183
+ "ai-toolkit-statusline.sh",
184
+ "commit-quality.sh",
185
+ "config-desync-guard.sh",
186
+ "governance-capture.sh",
187
+ "guard-config.sh",
188
+ "guard-destructive.sh",
189
+ "guard-path.sh",
190
+ "instructions-audit.sh",
191
+ "loop-guard.sh",
192
+ "mcp-health.sh",
193
+ "notify-waiting.sh",
194
+ "post-tool-use.sh",
195
+ "pre-compact-save.sh",
196
+ "pre-compact.sh",
197
+ "quality-check.sh",
198
+ "quality-gate.sh",
199
+ "revert-guard.sh",
200
+ "save-session.sh",
201
+ "search-tracker.sh",
202
+ "session-end.sh",
203
+ "session-start.sh",
204
+ "stop-search-check.sh",
205
+ "subagent-start.sh",
206
+ "subagent-stop.sh",
207
+ "test-cohesion.sh",
208
+ "track-usage.sh",
209
+ "user-prompt-submit.sh"
210
+ ],
211
+ "hook_events": [
212
+ "ConfigChange",
213
+ "InstructionsLoaded",
214
+ "Notification",
215
+ "PostToolUse",
216
+ "PreCompact",
217
+ "PreToolUse",
218
+ "SessionEnd",
219
+ "SessionStart",
220
+ "Stop",
221
+ "SubagentStart",
222
+ "SubagentStop",
223
+ "TaskCompleted",
224
+ "TeammateIdle",
225
+ "UserPromptSubmit"
226
+ ],
227
+ "plugin_packs": [
228
+ "enterprise-pack",
229
+ "memory-pack"
230
+ ],
231
+ "kb_categories": [
232
+ "best-practices",
233
+ "decisions",
234
+ "howto",
235
+ "planning",
236
+ "procedures",
237
+ "reference",
238
+ "runbooks",
239
+ "troubleshooting"
240
+ ],
241
+ "cli_commands": [
242
+ "add-rule",
243
+ "agents-md",
244
+ "aider-conf",
245
+ "antigravity-rules",
246
+ "augment-dir-rules",
247
+ "augment-rules",
248
+ "benchmark",
249
+ "benchmark-ecosystem",
250
+ "claude-app",
251
+ "cline-dir-rules",
252
+ "cline-rules",
253
+ "codex-hooks",
254
+ "codex-md",
255
+ "compile-slm",
256
+ "config",
257
+ "conventions-md",
258
+ "copilot-instructions",
259
+ "create",
260
+ "cursor-mdc",
261
+ "cursor-rules",
262
+ "doctor",
263
+ "eject",
264
+ "evaluate",
265
+ "gemini-md",
266
+ "generate-all",
267
+ "help",
268
+ "inject-hook",
269
+ "inject-mcp",
270
+ "install",
271
+ "llms-txt",
272
+ "mcp",
273
+ "opencode-agents",
274
+ "opencode-commands",
275
+ "opencode-json",
276
+ "opencode-md",
277
+ "opencode-plugin",
278
+ "pack-codebase",
279
+ "plugin",
280
+ "projects",
281
+ "remove-hook",
282
+ "remove-mcp",
283
+ "remove-rule",
284
+ "reset",
285
+ "roo-dir-rules",
286
+ "roo-modes",
287
+ "stats",
288
+ "status",
289
+ "sync",
290
+ "uninstall",
291
+ "update",
292
+ "validate",
293
+ "windsurf-dir-rules",
294
+ "windsurf-rules"
295
+ ]
296
+ }