@rivi-software/agentic-seo-check 0.1.1 → 0.3.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 (110) hide show
  1. package/README.md +67 -7
  2. package/dist/cli.js +69 -26
  3. package/dist/cli.js.map +1 -1
  4. package/dist/core/aeo/audit.d.ts +44 -0
  5. package/dist/core/aeo/audit.js +310 -0
  6. package/dist/core/aeo/audit.js.map +1 -0
  7. package/dist/core/aeo/bots.d.ts +30 -0
  8. package/dist/core/aeo/bots.js +299 -0
  9. package/dist/core/aeo/bots.js.map +1 -0
  10. package/dist/core/aeo/llms-txt.d.ts +8 -0
  11. package/dist/core/aeo/llms-txt.js +88 -0
  12. package/dist/core/aeo/llms-txt.js.map +1 -0
  13. package/dist/core/aeo/page.d.ts +43 -0
  14. package/dist/core/aeo/page.js +284 -0
  15. package/dist/core/aeo/page.js.map +1 -0
  16. package/dist/core/aeo/probe.d.ts +10 -0
  17. package/dist/core/aeo/probe.js +53 -0
  18. package/dist/core/aeo/probe.js.map +1 -0
  19. package/dist/core/aeo/site-rules.d.ts +13 -0
  20. package/dist/core/aeo/site-rules.js +178 -0
  21. package/dist/core/aeo/site-rules.js.map +1 -0
  22. package/dist/core/audit.d.ts +23 -2
  23. package/dist/core/audit.js +50 -22
  24. package/dist/core/audit.js.map +1 -1
  25. package/dist/core/crawl.d.ts +7 -1
  26. package/dist/core/crawl.js +85 -9
  27. package/dist/core/crawl.js.map +1 -1
  28. package/dist/core/fetch.d.ts +9 -0
  29. package/dist/core/fetch.js +28 -12
  30. package/dist/core/fetch.js.map +1 -1
  31. package/dist/core/html/answer.d.ts +4 -0
  32. package/dist/core/html/answer.js +198 -0
  33. package/dist/core/html/answer.js.map +1 -0
  34. package/dist/core/html/dom.d.ts +6 -0
  35. package/dist/core/html/dom.js +92 -1
  36. package/dist/core/html/dom.js.map +1 -1
  37. package/dist/core/html/extract.js +21 -72
  38. package/dist/core/html/extract.js.map +1 -1
  39. package/dist/core/html/head.d.ts +10 -0
  40. package/dist/core/html/head.js +206 -0
  41. package/dist/core/html/head.js.map +1 -0
  42. package/dist/core/html/resources.d.ts +17 -0
  43. package/dist/core/html/resources.js +172 -0
  44. package/dist/core/html/resources.js.map +1 -0
  45. package/dist/core/html/structured-data.d.ts +2 -0
  46. package/dist/core/html/structured-data.js +2 -0
  47. package/dist/core/html/structured-data.js.map +1 -1
  48. package/dist/core/report/markdown.d.ts +3 -1
  49. package/dist/core/report/markdown.js +102 -0
  50. package/dist/core/report/markdown.js.map +1 -1
  51. package/dist/core/robots.d.ts +7 -0
  52. package/dist/core/robots.js +13 -1
  53. package/dist/core/robots.js.map +1 -1
  54. package/dist/core/rules/aeo.d.ts +11 -0
  55. package/dist/core/rules/aeo.js +423 -0
  56. package/dist/core/rules/aeo.js.map +1 -0
  57. package/dist/core/rules/canonical.d.ts +3 -0
  58. package/dist/core/rules/canonical.js +54 -2
  59. package/dist/core/rules/canonical.js.map +1 -1
  60. package/dist/core/rules/document.js +4 -2
  61. package/dist/core/rules/document.js.map +1 -1
  62. package/dist/core/rules/head.d.ts +1 -0
  63. package/dist/core/rules/head.js +116 -0
  64. package/dist/core/rules/head.js.map +1 -0
  65. package/dist/core/rules/index.d.ts +4 -0
  66. package/dist/core/rules/index.js +15 -1
  67. package/dist/core/rules/index.js.map +1 -1
  68. package/dist/core/rules/indexing.d.ts +10 -0
  69. package/dist/core/rules/indexing.js +171 -9
  70. package/dist/core/rules/indexing.js.map +1 -1
  71. package/dist/core/rules/loading.d.ts +1 -0
  72. package/dist/core/rules/loading.js +138 -0
  73. package/dist/core/rules/loading.js.map +1 -0
  74. package/dist/core/rules/rule.d.ts +2 -0
  75. package/dist/core/rules/rule.js +2 -0
  76. package/dist/core/rules/rule.js.map +1 -1
  77. package/dist/core/rules/structured-data-values.d.ts +3 -0
  78. package/dist/core/rules/structured-data-values.js +316 -0
  79. package/dist/core/rules/structured-data-values.js.map +1 -0
  80. package/dist/core/rules/structured-data.js +50 -20
  81. package/dist/core/rules/structured-data.js.map +1 -1
  82. package/dist/core/rules/urls.d.ts +1 -0
  83. package/dist/core/rules/urls.js +293 -0
  84. package/dist/core/rules/urls.js.map +1 -0
  85. package/dist/core/score.d.ts +4 -2
  86. package/dist/core/score.js.map +1 -1
  87. package/dist/core/site-probes.d.ts +33 -0
  88. package/dist/core/site-probes.js +144 -0
  89. package/dist/core/site-probes.js.map +1 -0
  90. package/dist/core/site-rules.d.ts +18 -0
  91. package/dist/core/site-rules.js +479 -5
  92. package/dist/core/site-rules.js.map +1 -1
  93. package/dist/core/sitemap.d.ts +38 -1
  94. package/dist/core/sitemap.js +177 -43
  95. package/dist/core/sitemap.js.map +1 -1
  96. package/dist/core/static.d.ts +6 -0
  97. package/dist/core/static.js +122 -12
  98. package/dist/core/static.js.map +1 -1
  99. package/dist/core/types.d.ts +268 -2
  100. package/dist/core/types.js.map +1 -1
  101. package/dist/core/url.d.ts +2 -0
  102. package/dist/core/url.js +8 -0
  103. package/dist/core/url.js.map +1 -1
  104. package/dist/index.d.ts +6 -2
  105. package/dist/index.js +4 -2
  106. package/dist/index.js.map +1 -1
  107. package/dist/mcp.js +129 -3
  108. package/dist/mcp.js.map +1 -1
  109. package/package.json +6 -2
  110. package/skills/seo-audit/SKILL.md +9 -2
@@ -3,8 +3,10 @@ import path from "node:path";
3
3
  import { DEFAULT_USER_AGENT } from "./fetch.js";
4
4
  import { extractPage } from "./html/extract.js";
5
5
  import { buildRobots } from "./robots.js";
6
- import { parseSitemap } from "./sitemap.js";
7
- import { normalizePath, normalizeUrl } from "./url.js";
6
+ import { isLocalHost } from "./rules/canonical.js";
7
+ import { imageSourcesOf } from "./site-probes.js";
8
+ import { emptySitemapProblems, inspectSitemap, parseSitemap, SITEMAP_MAX_BYTES, SITEMAP_READ_BYTES, sitemapText, } from "./sitemap.js";
9
+ import { hostOf, normalizePath, normalizeUrl } from "./url.js";
8
10
  const SKIP_DIRS = new Set([
9
11
  "node_modules",
10
12
  ".git",
@@ -37,6 +39,18 @@ const walk = async (dir) => {
37
39
  }
38
40
  return out;
39
41
  };
42
+ /**
43
+ * Whether `full` lies inside the directory `root`. Paths come from pages, robots.txt and sitemaps,
44
+ * so a decoded "%2e%2e" can climb out; a sibling such as root + "2" is outside too. path.relative
45
+ * also holds when root is a filesystem or drive root ("/", "D:\\"), which ends in a separator.
46
+ */
47
+ export const isInside = (root, full) => {
48
+ const rel = path.relative(root, full);
49
+ return (rel !== "" &&
50
+ rel !== ".." &&
51
+ !rel.startsWith(`..${path.sep}`) &&
52
+ !path.isAbsolute(rel));
53
+ };
40
54
  const fileExists = async (root, pathname) => {
41
55
  let decoded = pathname;
42
56
  try {
@@ -54,7 +68,7 @@ const fileExists = async (root, pathname) => {
54
68
  ];
55
69
  for (const c of candidates) {
56
70
  const full = path.join(root, c);
57
- if (!full.startsWith(root)) {
71
+ if (!isInside(root, full)) {
58
72
  continue;
59
73
  }
60
74
  // oxlint-disable-next-line eslint/no-await-in-loop -- the candidates are tried in order and the first file found ends the search
@@ -125,6 +139,53 @@ const checkLinks = async (root, records, fileByPathKey) => {
125
139
  }
126
140
  return { linkChecks, linkSources };
127
141
  };
142
+ /**
143
+ * Canonical and hreflang targets on the site's own host, checked against the files like links are.
144
+ * With the default base URL (localhost) a production canonical is on another host and is skipped.
145
+ */
146
+ const checkMetadataTargets = async (root, records, base, fileByPathKey, linkChecks) => {
147
+ for (const record of records) {
148
+ for (const url of [
149
+ record.page.canonical,
150
+ ...record.page.hreflang.map((h) => h.url),
151
+ ]) {
152
+ const target = url ? normalizeUrl(url) : null;
153
+ if (!target ||
154
+ linkChecks.has(target) ||
155
+ hostOf(target) !== base.hostname) {
156
+ continue;
157
+ }
158
+ const { pathname } = new URL(target);
159
+ const exists = fileByPathKey.has(normalizePath(pathname)) ||
160
+ // oxlint-disable-next-line eslint/no-await-in-loop -- a target is checked once, so the next page naming it must see this check
161
+ (await fileExists(root, pathname));
162
+ linkChecks.set(target, fileCheck(target, target, exists));
163
+ }
164
+ }
165
+ };
166
+ /**
167
+ * Image URLs a server or CDN makes at request time (next/image, Vercel, Netlify, Cloudflare,
168
+ * Nuxt Image, Astro), which are never files in the build output.
169
+ */
170
+ const IMAGE_OPTIMIZER_PATH = /^\/(?:_next\/image|_vercel\/image|\.netlify\/images|cdn-cgi\/image|_ipx|_image)(?:[/?]|$)/u;
171
+ const isServedImage = (url) => {
172
+ const { pathname, search } = new URL(url);
173
+ return search !== "" || IMAGE_OPTIMIZER_PATH.test(pathname);
174
+ };
175
+ /**
176
+ * Images on the site's own host, looked up as files. Images on other hosts (a CDN) cannot be
177
+ * checked without a request, which a directory audit does not make.
178
+ */
179
+ const checkImageFiles = async (root, records, base) => {
180
+ const imageSources = new Map([...imageSourcesOf(records)].filter(([url]) => hostOf(url) === base.hostname && !isServedImage(url)));
181
+ const imageChecks = new Map();
182
+ for (const url of imageSources.keys()) {
183
+ // oxlint-disable-next-line eslint/no-await-in-loop -- one file at a time, like the links: a build can hold thousands of images
184
+ const exists = await fileExists(root, new URL(url).pathname);
185
+ imageChecks.set(url, fileCheck(url, url, exists));
186
+ }
187
+ return { imageChecks, imageSources };
188
+ };
128
189
  /** Depth via breadth-first search from the root index (if present); returns the start page. */
129
190
  const assignDepths = (records, recordByKey) => {
130
191
  const start = recordByKey.get("/") ?? records[0];
@@ -148,23 +209,26 @@ const assignDepths = (records, recordByKey) => {
148
209
  return start;
149
210
  };
150
211
  /** sitemap.xml, and the sitemaps robots.txt names, read from the output directory. */
151
- const readSitemaps = async (root, base, robots) => {
212
+ const readSitemaps = async (root, base, robots, includeSubdomains) => {
152
213
  const sitemaps = {
153
214
  sources: [],
154
215
  urls: [],
155
216
  urlCount: 0,
156
217
  errors: [],
218
+ problems: emptySitemapProblems(),
157
219
  };
158
220
  const candidates = [
159
221
  ...new Set([...robots.info.sitemaps, new URL("/sitemap.xml", base).href]),
160
- ];
222
+ ].map((url) => ({ url, fromIndex: false }));
161
223
  const seen = new Set();
162
224
  const urls = new Set();
225
+ const now = Date.now();
163
226
  while (seen.size < 25) {
164
- const candidate = candidates.shift();
165
- if (candidate === undefined) {
227
+ const next = candidates.shift();
228
+ if (next === undefined) {
166
229
  break;
167
230
  }
231
+ const { url: candidate, fromIndex } = next;
168
232
  if (seen.has(candidate)) {
169
233
  continue;
170
234
  }
@@ -178,22 +242,63 @@ const readSitemaps = async (root, base, robots) => {
178
242
  continue;
179
243
  }
180
244
  const file = path.join(root, pathname);
245
+ // robots.txt and sitemap indexes come from the site; a decoded "%2e%2e" must not leave the directory.
246
+ if (!isInside(root, file)) {
247
+ sitemaps.errors.push(`${candidate}: points outside the output directory`);
248
+ continue;
249
+ }
181
250
  // oxlint-disable-next-line eslint/no-await-in-loop -- a sitemap index adds the sitemaps it lists to the candidates, so each read decides what comes next
182
- const xml = await fs.readFile(file, "utf-8").catch(() => null);
183
- if (xml === null) {
251
+ const stat = await fs.stat(file).catch(() => null);
252
+ if (stat?.isFile() && stat.size > SITEMAP_READ_BYTES) {
253
+ sitemaps.problems.oversized.push({
254
+ sitemap: candidate,
255
+ urls: null,
256
+ bytes: stat.size,
257
+ overLimit: stat.size > SITEMAP_MAX_BYTES,
258
+ });
259
+ continue;
260
+ }
261
+ const bytes = stat?.isFile()
262
+ ? // oxlint-disable-next-line eslint/no-await-in-loop -- read right after the size check above
263
+ await fs.readFile(file).catch(() => null)
264
+ : null;
265
+ if (bytes === null) {
184
266
  if (robots.info.sitemaps.includes(candidate)) {
185
267
  sitemaps.errors.push(`${candidate}: declared in robots.txt but ${pathname} is not in the output directory`);
186
268
  }
187
269
  continue;
188
270
  }
189
- const parsed = parseSitemap(xml);
271
+ // oxlint-disable-next-line eslint/no-await-in-loop -- one sitemap at a time, as above
272
+ const text = await sitemapText(bytes);
273
+ if ("error" in text) {
274
+ if (text.tooLarge) {
275
+ sitemaps.problems.oversized.push({
276
+ sitemap: candidate,
277
+ urls: null,
278
+ bytes: null,
279
+ overLimit: false,
280
+ });
281
+ }
282
+ else {
283
+ sitemaps.errors.push(`${pathname}: ${text.error}`);
284
+ }
285
+ continue;
286
+ }
287
+ const parsed = parseSitemap(text.text);
190
288
  if (parsed.kind === "unknown") {
191
289
  sitemaps.errors.push(`${pathname}: could not parse as a sitemap`);
192
290
  continue;
193
291
  }
194
292
  sitemaps.sources.push(candidate);
293
+ // With the placeholder localhost base every production URL would count as another host.
294
+ inspectSitemap(sitemaps.problems, candidate, parsed, text.bytes, {
295
+ fromIndex,
296
+ siteHost: isLocalHost(base.href) ? null : base.hostname,
297
+ includeSubdomains,
298
+ now,
299
+ });
195
300
  if (parsed.kind === "sitemapindex") {
196
- candidates.push(...parsed.locs);
301
+ candidates.push(...parsed.locs.map((loc) => ({ url: loc, fromIndex: true })));
197
302
  }
198
303
  else {
199
304
  for (const loc of parsed.locs) {
@@ -241,6 +346,8 @@ export const scanDirectory = async (dir, options) => {
241
346
  }
242
347
  const { records, recordByKey } = await readPages(root, selected, base, options, toUrlPath);
243
348
  const { linkChecks, linkSources } = await checkLinks(root, records, fileByPathKey);
349
+ await checkMetadataTargets(root, records, base, fileByPathKey, linkChecks);
350
+ const images = await checkImageFiles(root, records, base);
244
351
  const start = assignDepths(records, recordByKey);
245
352
  const linkedKeys = new Set([...linkSources.keys()].map((u) => normalizePath(new URL(u).pathname)));
246
353
  const unlinkedPages = records.flatMap((r) => r !== start && !linkedKeys.has(normalizePath(new URL(r.url).pathname))
@@ -251,7 +358,7 @@ export const scanDirectory = async (dir, options) => {
251
358
  .readFile(path.join(root, "robots.txt"), "utf-8")
252
359
  .catch(() => null);
253
360
  const robots = buildRobots(new URL("/robots.txt", base).href, robotsText === null ? 404 : 200, undefined, robotsText, options.userAgent ?? DEFAULT_USER_AGENT);
254
- const sitemaps = await readSitemaps(root, base, robots);
361
+ const sitemaps = await readSitemaps(root, base, robots, options.includeSubdomains);
255
362
  checkSitemapUrls(sitemaps.urls, base, fileByPathKey, linkChecks);
256
363
  return {
257
364
  startUrl: base.href,
@@ -259,6 +366,7 @@ export const scanDirectory = async (dir, options) => {
259
366
  linkChecks,
260
367
  linkSources,
261
368
  robots: robots.info,
369
+ robotsText: robots.text,
262
370
  robotsAllows: robots.info.found ? robots.allows : null,
263
371
  blockedByRobots: robots.info.found
264
372
  ? records.flatMap((r) => (robots.allows(r.url) ? [] : [r.url]))
@@ -276,6 +384,8 @@ export const scanDirectory = async (dir, options) => {
276
384
  respectedRobots: false,
277
385
  },
278
386
  unlinkedPages,
387
+ imageChecks: images.imageChecks,
388
+ imageSources: images.imageSources,
279
389
  };
280
390
  };
281
391
  //# sourceMappingURL=static.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/core/static.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/core/static.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,8 @@
4
4
  */
5
5
  export type Severity = "error" | "warning" | "info";
6
6
  export declare const SEVERITY_RANK: Record<Severity, number>;
7
- export type Category = "title" | "meta" | "headings" | "canonical" | "indexing" | "document" | "social" | "images" | "links" | "international" | "structured-data" | "content" | "keyword" | "response" | "rendering" | "performance" | "site" | "tool";
8
- export type Requirement = "render" | "lighthouse" | "crawl" | "keyword";
7
+ export type Category = "title" | "meta" | "headings" | "canonical" | "indexing" | "document" | "social" | "images" | "links" | "international" | "structured-data" | "content" | "keyword" | "response" | "rendering" | "performance" | "site" | "aeo" | "tool";
8
+ export type Requirement = "render" | "lighthouse" | "crawl" | "keyword" | "ai-bots";
9
9
  /** Static description of a rule, exposed through `seo_list_rules` / `agentic-seo-check rules`. */
10
10
  export interface RuleMeta {
11
11
  id: string;
@@ -50,6 +50,15 @@ export interface ImageInfo {
50
50
  width: string | null;
51
51
  height: string | null;
52
52
  loading: string | null;
53
+ srcset: string | null;
54
+ /** The image sits in a <picture>, whose <source> elements offer other sizes or formats. */
55
+ inPicture: boolean;
56
+ fetchpriority: string | null;
57
+ /**
58
+ * Words of visible text before the image, a rough measure of how far down the page it is; null
59
+ * for an image that does not render where it is written (inside <template>, <noscript>, <svg>).
60
+ */
61
+ wordsBefore: number | null;
53
62
  }
54
63
  export interface LinkInfo {
55
64
  href: string;
@@ -78,6 +87,86 @@ export interface StructuredDataError {
78
87
  message: string;
79
88
  snippet: string;
80
89
  }
90
+ /** A heading (or FAQ `<summary>`/`<dt>`) phrased as a question, and the text that follows it. */
91
+ export interface QuestionHeading {
92
+ /** 1-6 for h1-h6, 0 for `<summary>` and `<dt>`. */
93
+ level: number;
94
+ text: string;
95
+ /** Words between the question and the next heading or question. */
96
+ sectionWords: number;
97
+ /** Words in the first paragraph, list item or definition after the question, or null when there is none. */
98
+ firstBlockWords: number | null;
99
+ }
100
+ /** What an answer engine needs from a page beyond classic SEO, read once by the extractor. */
101
+ export interface AnswerSignals {
102
+ /** Content of each robots meta tag by name (robots, googlebot, bingbot, ...), lower-cased. */
103
+ robotsMeta: {
104
+ name: string;
105
+ content: string;
106
+ }[];
107
+ questions: QuestionHeading[];
108
+ /** Lists with two or more items outside navigation, header, footer and aside. */
109
+ lists: number;
110
+ /** Tables with two or more rows outside navigation, header, footer and aside. */
111
+ tables: number;
112
+ /** Elements with `data-nosnippet`, the outermost ones only. */
113
+ nosnippetElements: number;
114
+ nosnippetWords: number;
115
+ nosnippetSelectors: string[];
116
+ /** Selector of an empty JavaScript app root (`#root`, `#__next`, ...), when the page has one. */
117
+ emptyAppRoot: string | null;
118
+ /** A `<noscript>` element mentions JavaScript ("please enable JavaScript"). */
119
+ noscriptAsksForJavaScript: boolean;
120
+ /** `<time>` elements in the body. */
121
+ timeElements: number;
122
+ /** The visible text contains a written date (2026-03-14, 14/03/2026, March 14, 2026, 14 March 2026). */
123
+ mentionsDate: boolean;
124
+ }
125
+ /** A subresource the page requests: a script, stylesheet, frame, image or media file. */
126
+ export interface ResourceInfo {
127
+ /**
128
+ * What browsers do with it on an https page: they upgrade `image` and `media` (audio, video) to
129
+ * https and block the rest, including a `responsive-image` (an image with srcset or in a
130
+ * <picture>) and a `track` (subtitles).
131
+ */
132
+ kind: "script" | "stylesheet" | "frame" | "object" | "image" | "responsive-image" | "media" | "track";
133
+ /** Absolute http(s) URL. */
134
+ url: string;
135
+ }
136
+ /** A `<meta http-equiv="refresh">`: reload or redirect after a number of seconds. */
137
+ export interface MetaRefresh {
138
+ /** Seconds before it acts, or null when the content does not start with a number. */
139
+ seconds: number | null;
140
+ /** Where it redirects to as written, or null when it only reloads the page. */
141
+ url: string | null;
142
+ }
143
+ /** How <head> reads to a parser, and the metadata that sits outside it. */
144
+ export interface HeadSignals {
145
+ /**
146
+ * The element or text that ended <head> before the author's `</head>` or `<body>`, quoted from
147
+ * the source (`<img src="/pixel.gif">`, `text "Loading"`), or null when <head> holds only
148
+ * elements that belong there.
149
+ */
150
+ closedBy: string | null;
151
+ /** `closedBy` sits in a `<noscript>`, which only parsers that do not run JavaScript read as markup. */
152
+ closedInNoscript: boolean;
153
+ /** Metadata written after `closedBy`, which a parser then puts in <body>: `<link rel="canonical">`. */
154
+ afterClose: string[];
155
+ /** Metadata written in <body> itself (after `</head>` or `<body>`). */
156
+ inBody: string[];
157
+ /**
158
+ * Metadata in <body> inside a hidden element: how React streams tags (Next.js streaming metadata)
159
+ * that its JavaScript then moves into <head>.
160
+ */
161
+ streamedInBody: string[];
162
+ refresh: MetaRefresh[];
163
+ /** Byte offset where the element declaring the character encoding ends, or null when none does. */
164
+ charsetEndByte: number | null;
165
+ /** `src` of scripts in <head> without async, defer or type="module", which stop the parser. */
166
+ blockingScripts: string[];
167
+ /** `href` of icon links: rel icon, shortcut icon, apple-touch-icon(-precomposed). */
168
+ icons: string[];
169
+ }
81
170
  /** Everything the extractor pulls out of one HTML document. Rules read only this. */
82
171
  export interface ExtractedPage {
83
172
  /** URL used to resolve relative links (the final URL after redirects, or the base URL for files/inline HTML). */
@@ -101,6 +190,12 @@ export interface ExtractedPage {
101
190
  images: ImageInfo[];
102
191
  links: LinkInfo[];
103
192
  hreflang: HreflangInfo[];
193
+ /** Scripts, stylesheets, frames, images and media the page requests. */
194
+ resources: ResourceInfo[];
195
+ /** A Content-Security-Policy meta tag tells browsers to upgrade the page's http:// requests to https. */
196
+ upgradesInsecureRequests: boolean;
197
+ /** `href="#name"` values with no element on the page whose id (or `<a name>`) is that name. */
198
+ missingFragments: string[];
104
199
  structuredData: StructuredDataItem[];
105
200
  structuredDataErrors: StructuredDataError[];
106
201
  /** Visible text of <body> with scripts/styles removed and whitespace collapsed. */
@@ -108,6 +203,9 @@ export interface ExtractedPage {
108
203
  wordCount: number;
109
204
  htmlBytes: number;
110
205
  hasBaseHref: boolean;
206
+ head: HeadSignals;
207
+ /** Signals the AEO audit reads; the SEO rules do not use them. */
208
+ answer: AnswerSignals;
111
209
  }
112
210
  export interface RedirectHop {
113
211
  url: string;
@@ -232,8 +330,37 @@ export interface RobotsTxtInfo {
232
330
  sitemaps: string[];
233
331
  /** Raw text, capped. */
234
332
  text: string | null;
333
+ /** Size of the file in bytes, or null when there is none. */
334
+ bytes: number | null;
235
335
  error?: string;
236
336
  }
337
+ /** A count of sitemap entries with one problem, and the first few of them. */
338
+ export interface SitemapExamples {
339
+ count: number;
340
+ /** "URL (value)" for the first 10. */
341
+ examples: string[];
342
+ }
343
+ /** Where the sitemaps break the sitemap protocol or what Google reads of it. */
344
+ export interface SitemapProblems {
345
+ /**
346
+ * Sitemaps over 50,000 URLs or 50 MB uncompressed (`overLimit`), or larger than the 15 MB this
347
+ * audit reads, which it could not check.
348
+ */
349
+ oversized: {
350
+ sitemap: string;
351
+ urls: number | null;
352
+ bytes: number | null;
353
+ overLimit: boolean;
354
+ }[];
355
+ /** Sitemap indexes that another sitemap index lists, which Google does not read. */
356
+ nestedIndexes: string[];
357
+ /** URLs whose <lastmod> is not a W3C Datetime such as 2026-11-09 or 2026-11-09T10:00:00+01:00. */
358
+ invalidLastmod: SitemapExamples;
359
+ /** URLs whose <lastmod> is later than the time of the audit. */
360
+ futureLastmod: SitemapExamples;
361
+ /** URLs on another host than the audited site. */
362
+ otherHost: SitemapExamples;
363
+ }
237
364
  export interface SitemapInfo {
238
365
  /** Sitemap (and sitemap index) URLs that were fetched. */
239
366
  sources: string[];
@@ -241,6 +368,7 @@ export interface SitemapInfo {
241
368
  urls: string[];
242
369
  urlCount: number;
243
370
  errors: string[];
371
+ problems: SitemapProblems;
244
372
  }
245
373
  export interface CrawlStats {
246
374
  pagesCrawled: number;
@@ -280,6 +408,144 @@ export interface SiteAudit {
280
408
  score: number;
281
409
  }
282
410
  export type Audit = PageAudit | SiteAudit;
411
+ /**
412
+ * What an AI crawler fetches pages for, which decides what blocking it costs: `search` crawlers
413
+ * feed a search index that AI answers draw on (Google AI Overviews, Copilot), `answer` bots fetch
414
+ * pages for an AI answer or an AI search index, `training` bots collect text to train models.
415
+ */
416
+ export type AiBotPurpose = "search" | "answer" | "training";
417
+ /** What the server answered a request with an AI bot's User-Agent (`aiBots` only). */
418
+ export interface BotProbe {
419
+ status: number | null;
420
+ /** The server refused or challenged this User-Agent while the audit's own request got the page. */
421
+ blocked: boolean;
422
+ /** Why it counts as blocked: "HTTP 403", "challenge page", "connection failed: ...". */
423
+ reason: string | null;
424
+ }
425
+ export interface AiBotAccess {
426
+ /** The bot's robots.txt token, e.g. "OAI-SearchBot". */
427
+ name: string;
428
+ operator: string;
429
+ purpose: AiBotPurpose;
430
+ usedFor: string;
431
+ /**
432
+ * The robots.txt group the bot follows: "named" when a group names it, "googlebot" for Applebot
433
+ * following the Googlebot group (Apple's documented fallback), "wildcard" when only
434
+ * `User-agent: *` applies, "none" when nothing does.
435
+ */
436
+ robotsGroup: "named" | "googlebot" | "wildcard" | "none";
437
+ /** robots.txt lets the bot fetch the audited page (the start page of a crawl or directory). */
438
+ allowed: boolean;
439
+ /**
440
+ * Audited pages robots.txt keeps this bot from while `User-agent: *` lets crawlers fetch them.
441
+ * Paths disallowed for every crawler are left to the SEO audit's `site.robots-blocked-pages`.
442
+ */
443
+ blockedPages: number;
444
+ probe?: BotProbe;
445
+ }
446
+ /** One `Content-Signal` line of robots.txt (contentsignals.org). */
447
+ export interface ContentSignal {
448
+ /** User agents of the robots.txt group the line sits in. */
449
+ userAgents: string[];
450
+ /** The path the line is limited to, or null for the whole site. */
451
+ path: string | null;
452
+ /** Each signal and its value as written, lower-cased: { search: "yes", "ai-input": "no" }. */
453
+ signals: Record<string, string>;
454
+ }
455
+ export interface AiCrawlerReport {
456
+ robotsTxt: string;
457
+ status: "found" | "missing" | "unreachable";
458
+ httpStatus: number | null;
459
+ /**
460
+ * The shared AI training preference (`User-Agent: __usage_ai-training`) for the audited page:
461
+ * "disallowed" opts out of training, "none" when robots.txt names no such group.
462
+ */
463
+ trainingPreference: "allowed" | "disallowed" | "none";
464
+ contentSignals: ContentSignal[];
465
+ bots: AiBotAccess[];
466
+ /** With `aiBots`: the User-Agent and status of the audit's own request, which each probe is compared with. */
467
+ probeBaseline?: {
468
+ userAgent: string;
469
+ status: number | null;
470
+ };
471
+ }
472
+ export interface LlmsTxtInfo {
473
+ url: string;
474
+ status: "found" | "missing" | "invalid";
475
+ httpStatus: number | null;
476
+ /** The H1 line, the one part the llms.txt format requires. */
477
+ title: string | null;
478
+ /** The blockquote after the title. */
479
+ summary: string | null;
480
+ /** H2 section names (capped). */
481
+ sections: string[];
482
+ /** Markdown links in the file. */
483
+ links: number;
484
+ bytes: number;
485
+ /** Why the file does not follow the format, when it does not. */
486
+ problems: string[];
487
+ }
488
+ export interface AeoPageSummary {
489
+ indexable: boolean;
490
+ /** "blocked" by nosnippet or max-snippet:0, "limited" by a short max-snippet or data-nosnippet. */
491
+ googleSnippets: "allowed" | "limited" | "blocked";
492
+ /** "excluded" by noarchive or noindex, "snippet-only" by nocache (Bing's rules for Copilot). */
493
+ copilotAnswers: "allowed" | "snippet-only" | "excluded";
494
+ wordCount: number;
495
+ questions: number;
496
+ structuredDataTypes: string[];
497
+ author: string | null;
498
+ datePublished: string | null;
499
+ dateModified: string | null;
500
+ }
501
+ export interface AeoPage {
502
+ url: string;
503
+ depth?: number;
504
+ score: number;
505
+ counts: SeverityCounts;
506
+ summary: AeoPageSummary;
507
+ }
508
+ export interface AeoSummary {
509
+ pages: number;
510
+ /** null when the target has no site to read robots.txt from (an HTML string or a single file). */
511
+ robotsTxt: "found" | "missing" | "unreachable" | null;
512
+ searchCrawlersBlocked: string[];
513
+ answerBotsBlocked: string[];
514
+ trainingBotsBlocked: string[];
515
+ trainingPreference: "allowed" | "disallowed" | "none" | null;
516
+ /** Bots the server refused or challenged, with `aiBots`; null without it. */
517
+ blockedByServer: string[] | null;
518
+ llmsTxt: "found" | "missing" | "invalid" | null;
519
+ /** The audited page, or the start page of a crawl or directory. */
520
+ page: AeoPageSummary | null;
521
+ }
522
+ /**
523
+ * An answer engine optimization audit: can AI crawlers reach the site, may answer engines quote
524
+ * it, and is the content easy to lift into an answer. Its score counts AEO findings only.
525
+ */
526
+ export interface AeoAudit {
527
+ schemaVersion: 1;
528
+ kind: "aeo";
529
+ target: string;
530
+ url: string;
531
+ source: PageSource | "crawl" | "directory";
532
+ /** 0-100. Indicative only: the average page score minus weighted site-wide findings. */
533
+ score: number;
534
+ counts: SeverityCounts;
535
+ auditedAt: string;
536
+ summary: AeoSummary;
537
+ /**
538
+ * Site-wide findings (robots.txt, llms.txt, bot probes), then the page findings: all of them for
539
+ * one page or with `pageDetail: "full"`, none for a site with `pageDetail: "summary"` (see `issues`).
540
+ */
541
+ findings: Finding[];
542
+ crawlers: AiCrawlerReport | null;
543
+ llmsTxt: LlmsTxtInfo | null;
544
+ /** Crawl and directory audits: each page's score and summary. */
545
+ pages?: AeoPage[];
546
+ /** Crawl and directory audits: page findings rolled up by rule. */
547
+ issues?: IssueRollup[];
548
+ }
283
549
  export interface Thresholds {
284
550
  titleMinChars: number;
285
551
  titleMaxChars: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,MAAM,aAAa,GAA6B;IACrD,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;CACR,CAAC;AA4UF,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,EAAE;IACjB,mBAAmB,EAAE,EAAE;IACvB,mBAAmB,EAAE,GAAG;IACxB,UAAU,EAAE,EAAE;IACd,gBAAgB,EAAE,GAAG;IACrB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,CAAC;IAChB,wBAAwB,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,GAAmB,EAAE,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;CACR,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAmB,EAAkB,EAAE;IACnE,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,MAAM,aAAa,GAA6B;IACrD,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;CACR,CAAC;AA+mBF,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,EAAE;IACjB,mBAAmB,EAAE,EAAE;IACvB,mBAAmB,EAAE,GAAG;IACxB,UAAU,EAAE,EAAE;IACd,gBAAgB,EAAE,GAAG;IACrB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,CAAC;IAChB,wBAAwB,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,GAAmB,EAAE,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;CACR,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAmB,EAAkB,EAAE;IACnE,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
@@ -14,6 +14,8 @@ export declare const isSameSite: (candidate: string, startHost: string, includeS
14
14
  /** Heuristic: does the path look like it points at an HTML document (not an asset)? */
15
15
  export declare const looksLikeHtml: (url: string) => boolean;
16
16
  /** `/dir/index.html` -> `/dir/`, `/page.html` -> `/page`, trailing slash dropped except root. */
17
+ /** The string without its trailing slashes. A loop, not /\/+$/, which backtracks on a long run. */
18
+ export declare const trimTrailingSlashes: (value: string) => string;
17
19
  export declare const normalizePath: (pathname: string) => string;
18
20
  /** Compare two URLs by path only (used for static-directory audits where the host is synthetic). */
19
21
  export declare const samePath: (a: string, b: string) => boolean;
package/dist/core/url.js CHANGED
@@ -163,6 +163,14 @@ export const looksLikeHtml = (url) => {
163
163
  }
164
164
  };
165
165
  /** `/dir/index.html` -> `/dir/`, `/page.html` -> `/page`, trailing slash dropped except root. */
166
+ /** The string without its trailing slashes. A loop, not /\/+$/, which backtracks on a long run. */
167
+ export const trimTrailingSlashes = (value) => {
168
+ let end = value.length;
169
+ while (end > 0 && value[end - 1] === "/") {
170
+ end -= 1;
171
+ }
172
+ return value.slice(0, end);
173
+ };
166
174
  export const normalizePath = (pathname) => {
167
175
  let p = pathname;
168
176
  try {