seo-crawl-audit 0.1.2 → 0.7.1

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.
package/README.md CHANGED
@@ -1,48 +1,74 @@
1
1
  # SEO Crawl Audit
2
2
 
3
- `seo-audit` is a local-first command-line crawler that finds current on-page SEO
4
- problems and detects accidental SEO regressions after a site changes.
5
-
6
- It is free and open-source software released under the MIT License. It needs no
7
- account, API key, browser extension, or hosted dashboard. Scan results stay on
8
- your computer in readable JSON and self-contained HTML files.
9
-
10
- ## What you get
11
-
12
- - automatic sitemap and sitemap-index discovery;
13
- - a simple terminal menu for 100 pages, the whole sitemap, batches, or a custom
14
- limit;
15
- - a live progress indicator;
16
- - automatic recovery after an interrupted scan without requesting completed
17
- pages again;
18
- - configurable spacing between request starts to reduce load on the site;
19
- - a partial HTML report that remains useful even if the process is stopped;
20
- - a saved baseline for later regression checks;
21
- - exit codes suitable for CI and pull-request checks.
3
+ Free, open-source, local-first SEO crawler and regression audit tool.
4
+
5
+ `seo-audit` crawls server-rendered pages, saves a versioned JSON snapshot,
6
+ finds concrete SEO problems, and detects regressions after a deployment. It
7
+ needs no account or API key. Page HTML is processed in memory; normalized
8
+ results stay in local JSON, checkpoint, CSV, and self-contained HTML files.
9
+
10
+ [Open the interactive example report](https://melnixdev.github.io/seo-crawl-audit/)
11
+ or [view its source file](examples/quotes-toscrape-report.html).
12
+
13
+ ## Highlights
14
+
15
+ - automatic `robots.txt`, sitemap, sitemap-index, and gzip sitemap support;
16
+ - bounded concurrency with a per-origin request delay;
17
+ - retries for timeouts, `429`, and temporary `5xx`, including `Retry-After`;
18
+ - redirect-chain and redirect-loop detection;
19
+ - 40+ explicit audit and regression rules with stable fingerprints;
20
+ - SnapshotV2 with automatic baseline v1 migration;
21
+ - `new`, `ongoing`, `resolved`, and `unchanged` issue lifecycle;
22
+ - resumable scans and a useful report even after interruption;
23
+ - local SnapshotV2 history with issue, page-count, sitemap, and crawl-depth
24
+ trends—without a hosted account;
25
+ - English/Ukrainian report localization, filters, CSV export, print layout,
26
+ and local report branding;
27
+ - interactive issue statistics for severity, frequent checks, ownership, and
28
+ regression lifecycle, with chart-to-table filtering;
29
+ - a production-versus-preview release guard with safe environment-based
30
+ authentication for private deployments;
31
+ - configuration, suppressions with expiry, severity overrides, and budgets;
32
+ - a self-contained GitHub Action that runs inside the GitHub runner;
33
+ - typed engine API with injectable `fetch`, checkpoints, events, logger, and
34
+ `AbortSignal`.
35
+
36
+ The project intentionally does not calculate an opaque overall SEO score.
37
+ Every finding names the affected URL, rule, risk, evidence, owner, and suggested
38
+ remediation.
22
39
 
23
40
  ## Requirements and installation
24
41
 
25
42
  Node.js 20.19 or newer is required.
26
43
 
44
+ Run without installing:
45
+
27
46
  ```bash
28
- git clone https://github.com/MelnixDev/seo-crawl-audit.git
29
- cd seo-crawl-audit
30
- npm install
31
- npm link
47
+ npx seo-crawl-audit https://example.com/
32
48
  ```
33
49
 
34
- After linking, `seo-audit` can be run from any directory:
50
+ Or install the CLI globally:
35
51
 
36
52
  ```bash
53
+ npm install --global seo-crawl-audit
37
54
  seo-audit --version
38
- seo-audit --help
39
55
  ```
40
56
 
41
- ## Five-minute demo
57
+ For repository development:
58
+
59
+ ```bash
60
+ git clone https://github.com/MelnixDev/seo-crawl-audit.git
61
+ cd seo-crawl-audit
62
+ npm install
63
+ npm run build
64
+ npm link --workspace seo-crawl-audit
65
+ ```
66
+
67
+ ## Five-minute example
42
68
 
43
69
  [Quotes to Scrape](https://quotes.toscrape.com/) is a public educational site
44
- made for crawler practice. It is unrelated to this project and keeps the demo
45
- small and reproducible.
70
+ made for crawler practice. It is unrelated to this project and keeps the
71
+ example small.
46
72
 
47
73
  ```bash
48
74
  seo-audit scan https://quotes.toscrape.com/ \
@@ -52,15 +78,7 @@ seo-audit scan https://quotes.toscrape.com/ \
52
78
  --report quotes-report.html
53
79
  ```
54
80
 
55
- This scans ten internal pages, writes a JSON baseline, and creates a filterable
56
- HTML report. In the current demo scan, the tool finds missing descriptions and
57
- canonical URLs while the pages themselves remain reachable.
58
-
59
- [View the included example report](examples/quotes-toscrape-report.html). GitHub
60
- may show the HTML source; download the file and open it in any browser to use
61
- the filters.
62
-
63
- Run a fresh comparison later:
81
+ Run a comparison later:
64
82
 
65
83
  ```bash
66
84
  seo-audit check https://quotes.toscrape.com/ \
@@ -73,7 +91,7 @@ seo-audit check https://quotes.toscrape.com/ \
73
91
 
74
92
  ### `seo-audit <url>`
75
93
 
76
- A shortcut for `seo-audit scan <url>`.
94
+ Shortcut for `seo-audit scan <url>`.
77
95
 
78
96
  ```bash
79
97
  seo-audit https://example.com/
@@ -81,7 +99,8 @@ seo-audit https://example.com/
81
99
 
82
100
  ### `seo-audit scan <url>`
83
101
 
84
- Crawls a site, audits its current SEO state, and saves a baseline.
102
+ Crawls a site, audits its current state, saves SnapshotV2, and optionally writes
103
+ an HTML report.
85
104
 
86
105
  ```bash
87
106
  seo-audit scan https://example.com/
@@ -89,25 +108,14 @@ seo-audit scan https://example.com/ --pages 250
89
108
  seo-audit scan https://example.com/ --all
90
109
  ```
91
110
 
92
- By default, the command:
93
-
94
- 1. reads `robots.txt`;
95
- 2. looks for a declared sitemap;
96
- 3. tries `/sitemap.xml` and `/sitemap_index.xml` when needed;
97
- 4. shows an interactive scan-size menu when a sitemap is found;
98
- 5. saves the baseline to `.seo-audit.json`;
99
- 6. creates `seo-audit-report.html` in an interactive terminal.
100
-
101
- The menu offers the first 100 pages, the whole sitemap, batches of 100 with
102
- confirmation, or any positive number entered by the user. `--pages` and `--all`
103
- skip that menu.
104
-
105
- If no sitemap is found, the interactive command asks for its full URL. Pressing
106
- Enter instead starts a same-origin internal-link crawl.
111
+ When a sitemap is found in an interactive terminal, the menu offers the first
112
+ 100 pages, every sitemap URL, groups of 100 with confirmation, or a custom
113
+ number. `--pages` and `--all` skip the menu. If no sitemap is found, press Enter
114
+ to continue through same-origin internal links, or enter the full sitemap URL.
107
115
 
108
116
  ### `seo-audit check [url]`
109
117
 
110
- Crawls the site again and compares it with a saved baseline.
118
+ Crawls again and compares the result with a saved baseline.
111
119
 
112
120
  ```bash
113
121
  seo-audit check
@@ -115,258 +123,325 @@ seo-audit check https://preview.example.com/
115
123
  seo-audit check --baseline production-seo.json --strict
116
124
  ```
117
125
 
118
- When `url` is omitted, the source URL stored in the baseline is used. Supplying
119
- a different origin is useful for comparing a production baseline with a preview
120
- deployment; same-path page and canonical URLs are mapped between the origins.
126
+ Without `url`, the saved site URL is used. A different origin supports
127
+ production-to-preview comparison while keeping paths comparable. New
128
+ error-level findings return exit code `1`; `--strict` also blocks on warnings.
129
+ If `scan` receives SIGINT or SIGTERM, it flushes completed pages, writes the
130
+ partial snapshot/report, keeps the checkpoint, and exits with code `130`.
121
131
 
122
- An error-level regression returns exit code `1`. Warnings also return `1` when
123
- `--strict` is enabled.
132
+ ### `seo-audit compare`
124
133
 
125
- ### `seo-audit report [baseline]`
126
-
127
- Builds a new HTML audit report from an existing baseline without crawling or
128
- making network requests.
134
+ Scans production, requests the same paths from a preview deployment, and
135
+ reports only SEO regressions introduced by the preview:
129
136
 
130
137
  ```bash
131
- seo-audit report
132
- seo-audit report quotes-baseline.json
133
- seo-audit report quotes-baseline.json --report quotes-report.html
138
+ seo-audit compare \
139
+ --production https://example.com/ \
140
+ --preview https://preview-123.example.dev/ \
141
+ --pages 100 \
142
+ --report preview-seo-report.html
134
143
  ```
135
144
 
136
- The default input is `.seo-audit.json`, and the default output is
137
- `seo-audit-report.html`.
138
-
139
- ## HTML report
140
-
141
- The report is one portable HTML file with no external scripts, fonts, tracking,
142
- or uploaded data. It contains:
143
-
144
- - summary cards for checked and affected pages;
145
- - error, warning, and informational issue counts;
146
- - free-text search across URL, rule, message, before, and after values;
147
- - severity and rule filters;
148
- - paginated results with 100, 250, or 500 rows per page;
149
- - direct links to affected pages;
150
- - before/after values for regression checks.
151
-
152
- During an interactive `scan`, the report is created immediately and refreshed
153
- after the first completed request batch, then periodically as the scan grows.
154
- Writes are atomic, so interruption should not leave a half-written HTML file.
155
- A partial report clearly says that it contains saved results and shows
156
- `checked / target` page counts.
157
-
158
- Interactive `scan` and `check` commands create the default report automatically.
159
- For scripts or CI, request one explicitly:
145
+ For a protected deployment, put request headers in an environment variable as
146
+ a JSON object and pass only its name on the command line:
160
147
 
161
148
  ```bash
162
- seo-audit scan https://example.com/ --report audit.html
163
- seo-audit check --report regressions.html
149
+ export SEO_AUDIT_PREVIEW_HEADERS='{"Authorization":"Bearer …"}'
150
+ seo-audit compare \
151
+ --production https://example.com/ \
152
+ --preview https://preview-123.example.dev/ \
153
+ --preview-headers-env SEO_AUDIT_PREVIEW_HEADERS
164
154
  ```
165
155
 
166
- Use `--no-report` when an HTML file is not needed.
156
+ Header values are used only by the injected request adapter. They are never
157
+ written to snapshots, reports, checkpoints, or JSON output. Errors block the
158
+ release with exit code `1`; `--strict` also blocks on warnings.
167
159
 
168
- ## Resume cache and interrupted scans
169
-
170
- `scan` stores completed page results in an append-only checkpoint beside the
171
- baseline. For the default `.seo-audit.json` output, its name is:
172
-
173
- ```text
174
- .seo-audit.checkpoint.ndjson
175
- ```
160
+ ### `seo-audit report [baseline]`
176
161
 
177
- The checkpoint contains extracted SEO results and discovered links, not full
178
- page HTML. Each completed request batch is appended immediately. If the process
179
- is stopped, run the same compatible scan command again:
162
+ Regenerates HTML from a saved snapshot without network requests.
180
163
 
181
164
  ```bash
182
- seo-audit https://example.com/ --all
165
+ seo-audit report
166
+ seo-audit report quotes-baseline.json --report quotes-report.html
183
167
  ```
184
168
 
185
- The command reports how many pages were recovered and skips those URLs. A cache
186
- is reused only when the start URL, sitemap, query-string policy, and robots
187
- policy match. An incompatible checkpoint is replaced automatically.
188
-
189
- The checkpoint is removed after the requested scan target finishes. It remains
190
- when a stepped scan is stopped before its target or when the process is
191
- interrupted. Checkpoint files are excluded by the included `.gitignore`.
169
+ ### `seo-audit history [url]`
192
170
 
193
- To deliberately make every request without reading or writing a checkpoint:
171
+ Lists locally saved runs and creates an HTML report with issue trends:
194
172
 
195
173
  ```bash
196
- seo-audit https://example.com/ --pages 100 --no-cache
174
+ seo-audit history https://example.com/
175
+ seo-audit history --history-dir ./audit-history --report history.html
197
176
  ```
198
177
 
199
- `check` never reuses the scan checkpoint because regression detection must
200
- observe the current response from every baseline URL.
178
+ Compare any two saved runs without crawling:
201
179
 
202
- ## What is checked
203
-
204
- The baseline audit reports:
205
-
206
- - unreachable pages and request failures;
207
- - HTTP 4xx and 5xx responses;
208
- - pages blocked by `robots.txt`;
209
- - missing titles;
210
- - missing meta descriptions;
211
- - missing canonical URLs;
212
- - missing or multiple H1 headings;
213
- - `noindex` directives.
214
-
215
- The regression check detects:
216
-
217
- - a previously working page becoming unavailable;
218
- - a new `noindex` directive;
219
- - a page becoming blocked by `robots.txt`;
220
- - a removed or changed title;
221
- - a removed meta description;
222
- - a removed or changed canonical URL;
223
- - a removed H1 heading;
224
- - a changed redirect destination;
225
- - a changed `robots.txt`.
226
-
227
- Errors represent changes or conditions likely to block indexing or make a page
228
- unusable. Warnings identify important metadata problems. Informational findings
229
- are worth reviewing but do not fail a normal check.
180
+ ```bash
181
+ seo-audit history \
182
+ --from .seo-audit/history/older.snapshot.json \
183
+ --to .seo-audit/history/newer.snapshot.json \
184
+ --report selected-runs.html
185
+ ```
230
186
 
231
187
  ## Options
232
188
 
233
189
  ```text
234
190
  --baseline <file> Baseline input for check (default: .seo-audit.json)
235
- --output <file> Baseline output for scan (default: .seo-audit.json)
191
+ --config <file> Config file (default: seo-audit.config.json)
192
+ --output <file> Snapshot output for scan (default: .seo-audit.json)
236
193
  --report <file> HTML report output (default: seo-audit-report.html)
237
194
  --no-report Disable automatic HTML report generation
238
- --no-cache Disable scan checkpoint caching and resume
195
+ --no-cache Disable checkpoint caching and resume
239
196
  --pages <number> Scan an exact number of pages
240
197
  --all Scan every URL found in the sitemap
241
198
  --max-pages <number> Deprecated alias for --pages
242
199
  --concurrency <number> Concurrent requests (default: 5)
243
- --delay <ms> Delay between request starts (default: 100)
200
+ --delay <ms> Delay between starts per origin (default: 100)
244
201
  --timeout <ms> Per-request timeout (default: 10000)
245
202
  --sitemap <url> Use a specific sitemap or sitemap index
246
203
  --no-sitemap Skip sitemap discovery and crawl internal links
247
204
  --include-query Treat query-string URLs as separate pages
248
205
  --ignore-robots Ignore robots.txt disallow rules
249
206
  --strict Fail check on warnings as well as errors
250
- --json Print machine-readable command output
251
- --help Show command help
207
+ --production <url> Production URL for compare
208
+ --preview <url> Preview deployment URL for compare
209
+ --production-headers-env <name>
210
+ Read production headers from a JSON environment variable
211
+ --preview-headers-env <name>
212
+ Read preview headers from a JSON environment variable
213
+ --history-dir <path> Local snapshot history directory
214
+ --no-history Do not save this scan to local history
215
+ --from <snapshot> Older snapshot for an explicit history comparison
216
+ --to <snapshot> Newer snapshot for an explicit history comparison
217
+ --json Print machine-readable output
218
+ --help Show help
252
219
  --version Show the installed version
253
220
  ```
254
221
 
255
- `--sitemap` and `--no-sitemap` cannot be used together. `--all` requires a
256
- sitemap because an internal-link crawl cannot know the site's complete URL set
257
- in advance.
258
-
259
- ## Files
260
-
261
- ### Baseline JSON
262
-
263
- The baseline records the source configuration, including the request delay,
264
- sitemap and robots metadata, and the extracted SEO state of every scanned page.
265
- `check` reuses that delay unless `--delay` overrides it. The file is
266
- deterministic enough to review and commit when a team wants versioned regression
267
- protection.
268
-
269
- ### Checkpoint NDJSON
270
-
271
- The checkpoint is temporary recovery state. It is append-only for efficient
272
- large scans and should not be committed.
273
-
274
- ### HTML report
275
-
276
- The report is a self-contained human-readable artifact. It can be opened
277
- locally, attached to a CI run, or shared as a file without exposing data to a
278
- third-party service.
279
-
280
- ## JSON output and exit codes
281
-
282
- Use `--json` for automation:
283
-
284
- ```bash
285
- seo-audit check --json
286
- ```
287
-
288
- Exit codes:
289
-
290
- ```text
291
- 0 Scan completed, or no blocking regressions were found
292
- 1 SEO regressions were found
293
- 2 Invalid input, invalid baseline, or crawler failure
222
+ ## Configuration
223
+
224
+ The repository includes [`seo-audit.config.json`](seo-audit.config.json) and a
225
+ [JSON Schema](packages/core/config.schema.json). CLI flags take precedence over
226
+ the config file, which takes precedence over the saved baseline, followed by
227
+ safe defaults.
228
+
229
+ ```json
230
+ {
231
+ "$schema": "./packages/core/config.schema.json",
232
+ "url": "https://example.com/",
233
+ "sitemap": "auto",
234
+ "maxPages": 100,
235
+ "concurrency": 5,
236
+ "delay": 100,
237
+ "timeout": 10000,
238
+ "respectRobots": true,
239
+ "includeQuery": false,
240
+ "enabledRules": null,
241
+ "severityOverrides": {
242
+ "low-word-count": "info"
243
+ },
244
+ "suppressions": [
245
+ {
246
+ "rule": "missing-description",
247
+ "urlPattern": "/legal/**",
248
+ "reason": "Description intentionally omitted",
249
+ "expiresAt": "2027-01-01"
250
+ }
251
+ ],
252
+ "regressionBudgets": {
253
+ "error": 0,
254
+ "warning": 3
255
+ },
256
+ "report": {
257
+ "agencyName": "Example Agency",
258
+ "logo": "https://example.com/logo.png",
259
+ "primaryColor": "#3157d5"
260
+ }
261
+ }
294
262
  ```
295
263
 
296
- With `--strict`, warnings count as blocking regressions for exit code `1`.
264
+ Expired suppressions stop matching automatically, so the issue appears again.
265
+ `urlPattern` accepts `*` within one path segment and `**` across segments.
297
266
 
298
- ## GitHub Actions example
267
+ ## What is checked
299
268
 
300
- Create and commit a production baseline first. Then compare a deployed preview
301
- in pull requests:
269
+ The rule registry covers access and HTTP failures, meta and header `noindex`,
270
+ robots blocking, canonical validity and targets, redirects, sitemap consistency,
271
+ titles, descriptions, headings, internal links, orphan pages, hreflang,
272
+ structured data syntax, language declarations, exact duplicate content, social
273
+ metadata, image alt attributes, and low word count.
274
+
275
+ Regression-only checks cover newly introduced indexing blocks, status changes,
276
+ metadata removal or edits, redirect changes, robots changes, and sharp sitemap
277
+ URL loss.
278
+
279
+ [Read the rule-by-rule documentation](https://github.com/MelnixDev/seo-crawl-audit/blob/main/docs/rules.md) ·
280
+ [Українська версія довідника правил](https://github.com/MelnixDev/seo-crawl-audit/blob/main/docs/rules.uk.md).
281
+
282
+ ## Snapshots, lifecycle, and checkpoints
283
+
284
+ SnapshotV2 records schema, engine and rule-set versions, generated time, config
285
+ hash, robots and sitemap state, normalized page data, link-graph summary, and
286
+ crawl statistics. Baseline schema v1 is upgraded automatically when read.
287
+
288
+ Issues use a stable 24-character fingerprint. A comparison separates:
289
+
290
+ - `newIssues` — absent from the previous snapshot;
291
+ - `ongoingIssues` — same issue identity with changed evidence;
292
+ - `resolvedIssues` — present before but absent now;
293
+ - `unchangedIssues` — same identity and evidence.
294
+
295
+ `DiffResult.complete` is `false` for partial or truncated comparisons. Findings
296
+ on checked pages are still reported, while unchecked pages are not falsely
297
+ classified as missing or resolved.
298
+
299
+ During `scan`, completed normalized page results are appended to
300
+ `.seo-audit.checkpoint.ndjson`. Full HTML is not cached. Running the same
301
+ compatible command resumes without requesting saved pages again. The checkpoint
302
+ is removed after completion and retained after interruption. Successful pages
303
+ are reused; transient failures and HTTP 5xx results are refreshed. Only an
304
+ unfinished final NDJSON record is recoverable—earlier corruption is reported.
305
+
306
+ Every completed scan and check also saves a full SnapshotV2 beside the selected
307
+ baseline under `.seo-audit/history/`. Use `--history-dir` to move it or
308
+ `--no-history` for an ephemeral run. History is read directly from disk; no URL,
309
+ snapshot, or metric is uploaded. The HTML trend view shows errors, warnings,
310
+ informational findings, new/resolved issues, page count, sitemap count, and
311
+ maximum crawl depth.
312
+
313
+ ## HTML and CSV report
314
+
315
+ The portable HTML file contains no external script, font, or tracking request.
316
+ It includes:
317
+
318
+ - an `English / Українська` language selector that translates the complete
319
+ interface, rule names, findings, remediation, lifecycle labels, and CSV;
320
+ - dependency-free interactive charts for severity, most frequent checks,
321
+ inferred page templates, and owner or regression-lifecycle distribution;
322
+ selecting a chart item filters
323
+ the issue table and selecting it again clears that filter;
324
+ - summary cards and partial-scan state;
325
+ - current and lifecycle tabs;
326
+ - severity, rule, inferred template, owner, and URL/text filters;
327
+ - evidence, before/after values, remediation, and fingerprint;
328
+ - engine and rule-set versions;
329
+ - client-side CSV export;
330
+ - print-friendly PDF layout;
331
+ - optional local agency name, logo, and primary color;
332
+ - clear clean-report and no-filter-match states.
333
+
334
+ Template grouping turns repeated findings such as `/products/red-shoe` and
335
+ `/products/blue-shirt` into `/products/:slug`. Numeric IDs, UUIDs, dates, and
336
+ hashes have stable placeholders. Grouping changes only presentation: rule IDs,
337
+ evidence, snapshots, and issue fingerprints remain unchanged.
338
+
339
+ Writes are atomic. Interactive scans refresh a partial report while results are
340
+ being checkpointed, so interruption does not discard already completed work.
341
+
342
+ ## GitHub Action
343
+
344
+ The Action crawls entirely inside the GitHub runner. It produces exit status,
345
+ JSON summary, HTML report, job summary, and annotations for error-level
346
+ regressions.
302
347
 
303
348
  ```yaml
304
349
  name: SEO regression check
305
-
306
- on:
307
- pull_request:
350
+ on: [pull_request]
308
351
 
309
352
  jobs:
310
353
  seo:
311
354
  runs-on: ubuntu-latest
312
355
  steps:
313
356
  - uses: actions/checkout@v4
314
- - uses: actions/setup-node@v4
357
+ - uses: MelnixDev/seo-crawl-audit@v0
358
+ id: seo
359
+ with:
360
+ url: https://preview.example.com/
361
+ baseline: .seo-audit.json
362
+ config: seo-audit.config.json
363
+ fail-on: error
364
+ report: seo-audit-report.html
365
+ - uses: actions/upload-artifact@v4
315
366
  with:
316
- node-version: 22
317
- - run: npm ci
318
- - run: node bin/seo-audit.js check https://preview.example.com/ --strict --json
367
+ name: seo-crawl-audit-report
368
+ path: |
369
+ ${{ steps.seo.outputs.report }}
370
+ ${{ steps.seo.outputs.summary }}
319
371
  ```
320
372
 
321
- Add `--report seo-regressions.html` and upload that file as a workflow artifact
322
- when a human-readable CI report is useful.
373
+ [Read all Action inputs and outputs](docs/github-action.md).
374
+
375
+ ## Core API and repository structure
376
+
377
+ The npm workspace separates reusable concerns:
323
378
 
324
- ## Responsible crawling
379
+ ```text
380
+ packages/core @seo-crawl-audit/core — scan, audit, diff, snapshots, reports
381
+ packages/cli seo-crawl-audit — terminal UX and npm executable
382
+ packages/action @seo-crawl-audit/action — GitHub runner entry point
383
+ ```
325
384
 
326
- The crawler respects `robots.txt` by default, stays on the starting origin,
327
- starts requests at least 100 milliseconds apart, limits concurrency to five
328
- in-flight requests, and applies a ten-second timeout. The same request gate is
329
- used for `robots.txt`, sitemap discovery, sitemap files, and HTML pages.
385
+ ```ts
386
+ import { audit, planScan, scan } from "@seo-crawl-audit/core";
387
+ import { createFileCheckpointStore } from "@seo-crawl-audit/core/node";
330
388
 
331
- Use a longer delay for a smaller site or a server you do not control:
389
+ const plan = await planScan({ url: "https://example.com/", maxPages: 100 });
390
+ const result = await scan(plan, {
391
+ signal: controller.signal,
392
+ checkpointStore: createFileCheckpointStore(".seo-audit.checkpoint.ndjson"),
393
+ onEvent(event) {
394
+ if (event.type === "progress") console.log(event.completed, event.total);
395
+ },
396
+ });
332
397
 
333
- ```bash
334
- seo-audit https://example.com/ --delay 500
398
+ const issues = audit(result.snapshot);
335
399
  ```
336
400
 
337
- `--delay 500` allows at most two new request starts per second. The default
338
- `--delay 100` allows at most ten. A value of `0` disables the delay and is best
339
- reserved for a local or otherwise trusted environment:
401
+ [Read the typed public API guide](docs/public-api.md) and the
402
+ [architecture notes](docs/architecture.md).
403
+
404
+ ## Responsible crawling and safe defaults
405
+
406
+ - delay: `100 ms` between request starts per origin;
407
+ - concurrency: `5`;
408
+ - timeout: `10 s`;
409
+ - `robots.txt` respected;
410
+ - same-origin page discovery;
411
+ - query strings excluded;
412
+ - HTML limited to `5 MiB` and robots to `512 KiB`;
413
+ - retries are bounded and use exponential backoff with jitter;
414
+ - `Retry-After` is honored up to 30 seconds;
415
+ - redirects are limited to 10.
416
+
417
+ Use a longer delay for a small site or a server you do not control:
340
418
 
341
419
  ```bash
342
- seo-audit http://localhost:3000/ --delay 0
420
+ seo-audit https://example.com/ --delay 500
343
421
  ```
344
422
 
345
- A very short value such as `--delay 10` can start up to 100 requests per second,
346
- so it is not a polite default for a public website. Increase concurrency or
347
- reduce the delay only on sites you are allowed to test.
423
+ Use `--delay 0` only for local or explicitly controlled fixtures.
348
424
 
349
425
  ## Current scope
350
426
 
351
- - server-rendered HTML only; JavaScript rendering is not included;
352
- - same-origin crawling;
353
- - sitemap and sitemap-index seeding;
354
- - query strings are removed by default to avoid crawl traps;
355
- - non-HTML URLs are not parsed for SEO metadata;
356
- - HTML responses are limited to 5 MiB;
357
- - `robots.txt` responses are limited to 512 KiB;
358
- - authenticated pages are not supported.
427
+ - server-rendered HTML; JavaScript rendering is not included;
428
+ - same-origin crawl discovery;
429
+ - sitemap and internal-link seeding;
430
+ - non-HTML responses are recorded but not parsed for page metadata;
431
+ - authenticated pages are not supported;
432
+ - results are normalized and ordered for reproducible output.
359
433
 
360
434
  ## Development
361
435
 
362
436
  ```bash
437
+ npm run build
363
438
  npm test
364
439
  npm run check
365
440
  ```
366
441
 
367
- The test suite covers crawling, robots rules, sitemap discovery, URL mapping,
368
- baseline comparisons, checkpoint recovery, HTML report safety, filtering data,
369
- and CLI behavior.
442
+ CI covers Node.js 20, 22, and 24. Tests use local HTTP fixtures for robots,
443
+ sitemaps, gzip, retries, redirects, cancellation, checkpoint resume, migration,
444
+ rules, lifecycle, HTML escaping, npm packaging, and the GitHub Action.
370
445
 
371
446
  ## License
372
447