seo-crawl-audit 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MelnixDev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,350 @@
1
+ # SEO Crawl Audit
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
+ - a partial HTML report that remains useful even if the process is stopped;
19
+ - a saved baseline for later regression checks;
20
+ - exit codes suitable for CI and pull-request checks.
21
+
22
+ ## Requirements and installation
23
+
24
+ Node.js 20.19 or newer is required.
25
+
26
+ ```bash
27
+ git clone https://github.com/MelnixDev/seo-crawl-audit.git
28
+ cd seo-crawl-audit
29
+ npm install
30
+ npm link
31
+ ```
32
+
33
+ After linking, `seo-audit` can be run from any directory:
34
+
35
+ ```bash
36
+ seo-audit --version
37
+ seo-audit --help
38
+ ```
39
+
40
+ ## Five-minute demo
41
+
42
+ [Quotes to Scrape](https://quotes.toscrape.com/) is a public educational site
43
+ made for crawler practice. It is unrelated to this project and keeps the demo
44
+ small and reproducible.
45
+
46
+ ```bash
47
+ seo-audit scan https://quotes.toscrape.com/ \
48
+ --no-sitemap \
49
+ --pages 10 \
50
+ --output quotes-baseline.json \
51
+ --report quotes-report.html
52
+ ```
53
+
54
+ This scans ten internal pages, writes a JSON baseline, and creates a filterable
55
+ HTML report. In the current demo scan, the tool finds missing descriptions and
56
+ canonical URLs while the pages themselves remain reachable.
57
+
58
+ [View the included example report](examples/quotes-toscrape-report.html). GitHub
59
+ may show the HTML source; download the file and open it in any browser to use
60
+ the filters.
61
+
62
+ Run a fresh comparison later:
63
+
64
+ ```bash
65
+ seo-audit check https://quotes.toscrape.com/ \
66
+ --baseline quotes-baseline.json \
67
+ --pages 10 \
68
+ --report quotes-changes.html
69
+ ```
70
+
71
+ ## Commands
72
+
73
+ ### `seo-audit <url>`
74
+
75
+ A shortcut for `seo-audit scan <url>`.
76
+
77
+ ```bash
78
+ seo-audit https://example.com/
79
+ ```
80
+
81
+ ### `seo-audit scan <url>`
82
+
83
+ Crawls a site, audits its current SEO state, and saves a baseline.
84
+
85
+ ```bash
86
+ seo-audit scan https://example.com/
87
+ seo-audit scan https://example.com/ --pages 250
88
+ seo-audit scan https://example.com/ --all
89
+ ```
90
+
91
+ By default, the command:
92
+
93
+ 1. reads `robots.txt`;
94
+ 2. looks for a declared sitemap;
95
+ 3. tries `/sitemap.xml` and `/sitemap_index.xml` when needed;
96
+ 4. shows an interactive scan-size menu when a sitemap is found;
97
+ 5. saves the baseline to `.seo-audit.json`;
98
+ 6. creates `seo-audit-report.html` in an interactive terminal.
99
+
100
+ The menu offers the first 100 pages, the whole sitemap, batches of 100 with
101
+ confirmation, or any positive number entered by the user. `--pages` and `--all`
102
+ skip that menu.
103
+
104
+ If no sitemap is found, the interactive command asks for its full URL. Pressing
105
+ Enter instead starts a same-origin internal-link crawl.
106
+
107
+ ### `seo-audit check [url]`
108
+
109
+ Crawls the site again and compares it with a saved baseline.
110
+
111
+ ```bash
112
+ seo-audit check
113
+ seo-audit check https://preview.example.com/
114
+ seo-audit check --baseline production-seo.json --strict
115
+ ```
116
+
117
+ When `url` is omitted, the source URL stored in the baseline is used. Supplying
118
+ a different origin is useful for comparing a production baseline with a preview
119
+ deployment; same-path page and canonical URLs are mapped between the origins.
120
+
121
+ An error-level regression returns exit code `1`. Warnings also return `1` when
122
+ `--strict` is enabled.
123
+
124
+ ### `seo-audit report [baseline]`
125
+
126
+ Builds a new HTML audit report from an existing baseline without crawling or
127
+ making network requests.
128
+
129
+ ```bash
130
+ seo-audit report
131
+ seo-audit report quotes-baseline.json
132
+ seo-audit report quotes-baseline.json --report quotes-report.html
133
+ ```
134
+
135
+ The default input is `.seo-audit.json`, and the default output is
136
+ `seo-audit-report.html`.
137
+
138
+ ## HTML report
139
+
140
+ The report is one portable HTML file with no external scripts, fonts, tracking,
141
+ or uploaded data. It contains:
142
+
143
+ - summary cards for checked and affected pages;
144
+ - error, warning, and informational issue counts;
145
+ - free-text search across URL, rule, message, before, and after values;
146
+ - severity and rule filters;
147
+ - paginated results with 100, 250, or 500 rows per page;
148
+ - direct links to affected pages;
149
+ - before/after values for regression checks.
150
+
151
+ During an interactive `scan`, the report is created immediately and refreshed
152
+ after the first completed request batch, then periodically as the scan grows.
153
+ Writes are atomic, so interruption should not leave a half-written HTML file.
154
+ A partial report clearly says that it contains saved results and shows
155
+ `checked / target` page counts.
156
+
157
+ Interactive `scan` and `check` commands create the default report automatically.
158
+ For scripts or CI, request one explicitly:
159
+
160
+ ```bash
161
+ seo-audit scan https://example.com/ --report audit.html
162
+ seo-audit check --report regressions.html
163
+ ```
164
+
165
+ Use `--no-report` when an HTML file is not needed.
166
+
167
+ ## Resume cache and interrupted scans
168
+
169
+ `scan` stores completed page results in an append-only checkpoint beside the
170
+ baseline. For the default `.seo-audit.json` output, its name is:
171
+
172
+ ```text
173
+ .seo-audit.checkpoint.ndjson
174
+ ```
175
+
176
+ The checkpoint contains extracted SEO results and discovered links, not full
177
+ page HTML. Each completed request batch is appended immediately. If the process
178
+ is stopped, run the same compatible scan command again:
179
+
180
+ ```bash
181
+ seo-audit https://example.com/ --all
182
+ ```
183
+
184
+ The command reports how many pages were recovered and skips those URLs. A cache
185
+ is reused only when the start URL, sitemap, query-string policy, and robots
186
+ policy match. An incompatible checkpoint is replaced automatically.
187
+
188
+ The checkpoint is removed after the requested scan target finishes. It remains
189
+ when a stepped scan is stopped before its target or when the process is
190
+ interrupted. Checkpoint files are excluded by the included `.gitignore`.
191
+
192
+ To deliberately make every request without reading or writing a checkpoint:
193
+
194
+ ```bash
195
+ seo-audit https://example.com/ --pages 100 --no-cache
196
+ ```
197
+
198
+ `check` never reuses the scan checkpoint because regression detection must
199
+ observe the current response from every baseline URL.
200
+
201
+ ## What is checked
202
+
203
+ The baseline audit reports:
204
+
205
+ - unreachable pages and request failures;
206
+ - HTTP 4xx and 5xx responses;
207
+ - pages blocked by `robots.txt`;
208
+ - missing titles;
209
+ - missing meta descriptions;
210
+ - missing canonical URLs;
211
+ - missing or multiple H1 headings;
212
+ - `noindex` directives.
213
+
214
+ The regression check detects:
215
+
216
+ - a previously working page becoming unavailable;
217
+ - a new `noindex` directive;
218
+ - a page becoming blocked by `robots.txt`;
219
+ - a removed or changed title;
220
+ - a removed meta description;
221
+ - a removed or changed canonical URL;
222
+ - a removed H1 heading;
223
+ - a changed redirect destination;
224
+ - a changed `robots.txt`.
225
+
226
+ Errors represent changes or conditions likely to block indexing or make a page
227
+ unusable. Warnings identify important metadata problems. Informational findings
228
+ are worth reviewing but do not fail a normal check.
229
+
230
+ ## Options
231
+
232
+ ```text
233
+ --baseline <file> Baseline input for check (default: .seo-audit.json)
234
+ --output <file> Baseline output for scan (default: .seo-audit.json)
235
+ --report <file> HTML report output (default: seo-audit-report.html)
236
+ --no-report Disable automatic HTML report generation
237
+ --no-cache Disable scan checkpoint caching and resume
238
+ --pages <number> Scan an exact number of pages
239
+ --all Scan every URL found in the sitemap
240
+ --max-pages <number> Deprecated alias for --pages
241
+ --concurrency <number> Concurrent requests (default: 5)
242
+ --timeout <ms> Per-request timeout (default: 10000)
243
+ --sitemap <url> Use a specific sitemap or sitemap index
244
+ --no-sitemap Skip sitemap discovery and crawl internal links
245
+ --include-query Treat query-string URLs as separate pages
246
+ --ignore-robots Ignore robots.txt disallow rules
247
+ --strict Fail check on warnings as well as errors
248
+ --json Print machine-readable command output
249
+ --help Show command help
250
+ --version Show the installed version
251
+ ```
252
+
253
+ `--sitemap` and `--no-sitemap` cannot be used together. `--all` requires a
254
+ sitemap because an internal-link crawl cannot know the site's complete URL set
255
+ in advance.
256
+
257
+ ## Files
258
+
259
+ ### Baseline JSON
260
+
261
+ The baseline records the source configuration, sitemap and robots metadata, and
262
+ the extracted SEO state of every scanned page. It is deterministic enough to
263
+ review and commit when a team wants versioned regression protection.
264
+
265
+ ### Checkpoint NDJSON
266
+
267
+ The checkpoint is temporary recovery state. It is append-only for efficient
268
+ large scans and should not be committed.
269
+
270
+ ### HTML report
271
+
272
+ The report is a self-contained human-readable artifact. It can be opened
273
+ locally, attached to a CI run, or shared as a file without exposing data to a
274
+ third-party service.
275
+
276
+ ## JSON output and exit codes
277
+
278
+ Use `--json` for automation:
279
+
280
+ ```bash
281
+ seo-audit check --json
282
+ ```
283
+
284
+ Exit codes:
285
+
286
+ ```text
287
+ 0 Scan completed, or no blocking regressions were found
288
+ 1 SEO regressions were found
289
+ 2 Invalid input, invalid baseline, or crawler failure
290
+ ```
291
+
292
+ With `--strict`, warnings count as blocking regressions for exit code `1`.
293
+
294
+ ## GitHub Actions example
295
+
296
+ Create and commit a production baseline first. Then compare a deployed preview
297
+ in pull requests:
298
+
299
+ ```yaml
300
+ name: SEO regression check
301
+
302
+ on:
303
+ pull_request:
304
+
305
+ jobs:
306
+ seo:
307
+ runs-on: ubuntu-latest
308
+ steps:
309
+ - uses: actions/checkout@v4
310
+ - uses: actions/setup-node@v4
311
+ with:
312
+ node-version: 22
313
+ - run: npm ci
314
+ - run: node bin/seo-audit.js check https://preview.example.com/ --strict --json
315
+ ```
316
+
317
+ Add `--report seo-regressions.html` and upload that file as a workflow artifact
318
+ when a human-readable CI report is useful.
319
+
320
+ ## Responsible crawling
321
+
322
+ The crawler respects `robots.txt` by default, stays on the starting origin,
323
+ limits concurrency to five requests, and applies a ten-second timeout. Increase
324
+ concurrency carefully and only on sites you are allowed to test.
325
+
326
+ ## Current scope
327
+
328
+ - server-rendered HTML only; JavaScript rendering is not included;
329
+ - same-origin crawling;
330
+ - sitemap and sitemap-index seeding;
331
+ - query strings are removed by default to avoid crawl traps;
332
+ - non-HTML URLs are not parsed for SEO metadata;
333
+ - HTML responses are limited to 5 MiB;
334
+ - `robots.txt` responses are limited to 512 KiB;
335
+ - authenticated pages are not supported.
336
+
337
+ ## Development
338
+
339
+ ```bash
340
+ npm test
341
+ npm run check
342
+ ```
343
+
344
+ The test suite covers crawling, robots rules, sitemap discovery, URL mapping,
345
+ baseline comparisons, checkpoint recovery, HTML report safety, filtering data,
346
+ and CLI behavior.
347
+
348
+ ## License
349
+
350
+ MIT
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from "../src/cli.js";
4
+
5
+ main()
6
+ .then((exitCode) => {
7
+ process.exitCode = exitCode;
8
+ })
9
+ .catch((error) => {
10
+ console.error(`seo-audit: ${error.message}`);
11
+ process.exitCode = 2;
12
+ });