sitemend 1.2.1__tar.gz

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.
sitemend-1.2.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 surendhar-v
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.
@@ -0,0 +1,286 @@
1
+ Metadata-Version: 2.4
2
+ Name: sitemend
3
+ Version: 1.2.1
4
+ Summary: Technical SEO audit and repair: crawls a site folder or live URL, finds indexing, duplicate-content, link, hreflang and schema problems, and never invents a number it did not measure.
5
+ Author: surendhar-v
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/SurendharVr/sitemend
8
+ Project-URL: Issues, https://github.com/SurendharVr/sitemend/issues
9
+ Project-URL: Changelog, https://github.com/SurendharVr/sitemend/blob/main/CHANGELOG.md
10
+ Keywords: seo,seo-audit,technical-seo,crawler,sitemap,structured-data,core-web-vitals,lighthouse,claude-code,claude-skill
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
13
+ Classifier: Environment :: Console
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: beautifulsoup4>=4.9
18
+ Requires-Dist: lxml>=4.6
19
+ Requires-Dist: requests>=2.25
20
+ Dynamic: license-file
21
+
22
+ # sitemend
23
+
24
+ [![tests](https://github.com/SurendharVr/seo-repair/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/SurendharVr/seo-repair/actions/workflows/tests.yml)
25
+ [![license](https://img.shields.io/github/license/SurendharVr/seo-repair)](LICENSE)
26
+
27
+ **Find the SEO problems Google actually penalises, then fix them in your code.**
28
+
29
+ Built for developers and site owners who keep their site in a codebase and want SEO
30
+ fixes as reviewable diffs, not a PDF of warnings. You approve every change before it's
31
+ applied.
32
+
33
+ A [Claude Code](https://claude.com/claude-code) skill: a site crawler and audit tool that finds indexing problems, orphan pages, duplicate
34
+ content, broken internal links, thin content, missing canonical tags, keyword
35
+ cannibalization and invalid schema markup — then proposes the fixes, applies the ones
36
+ you approve, and re-verifies with a second crawl.
37
+
38
+ `sitemend` is the PyPI package and command-line name. Inside Claude Code the skill and
39
+ plugin are still called `seo-repair`.
40
+
41
+ What makes it different from a checklist: **the order is enforced.** SEO findings are
42
+ not independent, so this treats them as a repair system with a dependency order.
43
+
44
+ ```
45
+ Crawl → Index → Architecture → Content → On-Page → Performance → Schema → Authority → Monitor
46
+ ```
47
+
48
+ Work done out of order is wasted. Optimising a title on a page Google cannot index
49
+ changes nothing. Writing schema for a page about to be merged away is thrown out with
50
+ the page. Building links to either is the most expensive mistake of the three. Three
51
+ **gates** make that ordering unskippable rather than advisory.
52
+
53
+ ---
54
+
55
+ ## What a run looks like
56
+
57
+ Auditing the bundled demo site — the gate lines are the point, and they say *why*, not just *blocked*:
58
+
59
+ ```console
60
+ $ python audit.py --crawl crawl.json --schema schema.json --out findings.json
61
+ 24 findings: 1 critical, 7 high, 7 medium, 9 low
62
+ stage 1: 5
63
+ stage 2: 6
64
+ stage 3: 11
65
+ stage 5: 2
66
+ gate A (Index before content): CLEAR -- every crawled page is indexable
67
+ gate B (Architecture before schema): BLOCKED -- 3 page(s) orphaned or pending consolidation: /, /old-home.html, /reviews.html
68
+ gate C (Everything before authority): BLOCKED -- 8 critical/high finding(s) open in stages 1-5: S1-CANONICAL-CROSS, S1-PLACEHOLDER-DOMAIN, S1-SITEMAP-ORPHAN, S2-ORPHAN
69
+ ```
70
+
71
+ Each run also produces a self-contained HTML dashboard:
72
+
73
+ ![The seo-repair dashboard: severity totals, the seven-stage repair pipeline with gates drawn between the stages, and the three gate cards showing why each is clear or blocked](docs/dashboard.png)
74
+
75
+ Note stage 04. Lighthouse was not run here, so Performance reads **not measured** rather
76
+ than *clear* — a stage that produced no findings because nobody looked at it is not a
77
+ stage that passed, and the dashboard will not imply otherwise.
78
+
79
+ ---
80
+
81
+ ## Two things that make it different
82
+
83
+ **It refuses to invent numbers.** Search volume, keyword difficulty, backlink counts and
84
+ field Core Web Vitals cannot be observed from a codebase. They are never estimated —
85
+ they become a handoff list naming the exact Search Console or Ahrefs report to open.
86
+ Every claim in a report is tagged `MEASURED` (observed directly), `INFERRED` (reasoned
87
+ from observation, stated as such), or `HANDOFF` (not observable here). A local crawl
88
+ proves a page is *crawlable*; it never proves the page is *indexed*, and the report will
89
+ not blur those.
90
+
91
+ The same standard applies to what it writes: no invented author bios, testimonials,
92
+ ratings or trust claims. A tool that refuses to guess at keyword volume has no business
93
+ guessing at a person's credentials.
94
+
95
+ **It checks whether your structured data is honest.** Most validators check that schema
96
+ parses and has its required properties. This one also checks whether the markup asserts
97
+ things the page never shows — a rating nobody can see, an address that appears nowhere,
98
+ or review markup naming people the page does not mention. That last one is a Google
99
+ rich-results policy violation and a manual-action risk, and a property-checker will
100
+ never catch it.
101
+
102
+ ## Versus asking for an SEO audit
103
+
104
+ The alternative to a tool like this is pasting a page into a chat and asking for an SEO
105
+ audit. That gives you advice. This gives you a crawl, with the differences that follow
106
+ from that:
107
+
108
+ | | A checklist prompt | seo-repair |
109
+ | --- | --- | --- |
110
+ | **Coverage** | The pages you paste or open, one at a time | Every page, from a folder or a live URL (200 by default), plus `robots.txt` and `sitemap.xml` |
111
+ | **What it sees** | Text or markup you supply | Real status codes and redirects, canonicals, internal links, orphans, click depth |
112
+ | **Repeatable** | Wording and findings can differ run to run | Same site, same crawl, same findings. `verify` diffs a new run against a baseline |
113
+ | **Evidence** | Advice in prose | Each finding names the page and cites the offending string |
114
+ | **Order of work** | One flat list | Dependency order, with three gates enforced in code: no content work on pages Google cannot index, no schema on orphaned pages, no link building while critical findings are open |
115
+ | **Numbers it cannot measure** | Nothing in a prompt stops a plausible figure | Never stated. Volume, difficulty, backlinks and field Core Web Vitals become a handoff list naming the report to open |
116
+ | **Structured data** | Required properties, if it checks at all | Required properties, and whether the markup claims things the page never shows, such as review authors |
117
+ | **Applying fixes** | Suggestions | One approved batch at a time, then a re-crawl to confirm it worked. Nothing is edited without approval |
118
+ | **In CI** | No | `--fail-on` sets the exit code. An example GitHub Action is in `examples/` |
119
+ | **Tested** | Not testable | 146 tests, many pinned to false positives found on real runs |
120
+
121
+ **How big is the gap?** We measured it on the demo site (5 pages, 14 planted defects).
122
+ Three plain "audit this site" runs by an AI agent with read-only file access found 14, 12
123
+ and 13 of the defects, with one false alarm between them. seo-repair found all 14 with no
124
+ false alarms, gave identical findings on two runs, and took about 3 seconds without using
125
+ a language model. On a site this small a good prompt does well, and it noticed things
126
+ seo-repair does not check, such as a placeholder domain in the sitemap and missing Open
127
+ Graph tags. The advantage is repeatability, scale and CI, not a better score on five
128
+ pages. The demo was built around what seo-repair detects, and this was one model and three
129
+ runs, so read it as an example, not a benchmark.
130
+
131
+ A prompt is the better tool for work that needs the live search results: keyword
132
+ research, reading what the top-ranking pages cover, and writing or rewriting content.
133
+ seo-repair does not do that, and hands it off by design. Use them in that order: fix
134
+ what stops a page being crawled and indexed first, then decide what it should say.
135
+
136
+ ---
137
+
138
+ ## Works with
139
+
140
+ - **Full workflow:** Claude Code (audit, plan, apply, verify).
141
+ - **Standalone:** one command, `sitemend audit <folder|URL>` (or
142
+ `python scripts/seo_repair.py audit ...` from a clone), runs the whole pipeline on
143
+ plain Python 3.9+. No agent needed. See below.
144
+ - **Tested on:** Linux, macOS and Windows. The Lighthouse step is verified on Windows only.
145
+
146
+ ## Install
147
+
148
+ **As a plugin:**
149
+
150
+ ```
151
+ /plugin marketplace add SurendharVr/seo-repair
152
+ ```
153
+
154
+ **Or clone straight into your skills directory:**
155
+
156
+ ```bash
157
+ git clone https://github.com/SurendharVr/seo-repair ~/.claude/skills/seo-repair
158
+ pip install -r ~/.claude/skills/seo-repair/requirements.txt
159
+ ```
160
+
161
+ **Or as a command-line tool, without Claude Code:**
162
+
163
+ ```bash
164
+ pip install git+https://github.com/SurendharVr/seo-repair
165
+ sitemend audit ./my-site
166
+ ```
167
+
168
+ (The wheel is built and tested in CI on every push. `pip install sitemend` from PyPI
169
+ works once a release has been published; see [`RELEASING.md`](RELEASING.md).)
170
+
171
+ Requires Python 3.9+ with `beautifulsoup4`, `lxml` and `requests` (`pip` installs them;
172
+ from a clone, `requirements.txt` lists them). Core Web Vitals and `--render` additionally
173
+ need a local Chrome, Chromium or Edge; Core Web Vitals also need Node, via
174
+ `npx lighthouse`.
175
+
176
+ ## Use it without an agent
177
+
178
+ One command audits a site folder or a live URL and writes a report and dashboard. It
179
+ edits nothing in the site.
180
+
181
+ ```bash
182
+ python scripts/seo_repair.py audit ./my-site # or https://example.com
183
+ python scripts/seo_repair.py audit ./my-site --fail-on high # exit 1 if a high/critical finding is open (CI gate)
184
+ python scripts/seo_repair.py verify ./my-site --baseline seo-repair-out/findings.json
185
+ ```
186
+
187
+ To guard a site on every pull request, copy
188
+ [`examples/github-action/seo-repair.yml`](examples/github-action/seo-repair.yml) to
189
+ `.github/workflows/`. It fails the check when a critical finding is open and attaches
190
+ the report and dashboard to the run.
191
+
192
+ Output lands in `./seo-repair-out`: `findings.json`, `SEO-REPORT-<date>.md` and a
193
+ self-contained `dashboard.html`. Applying fixes stays a Claude Code job, because each
194
+ edit needs your approval.
195
+
196
+ ## Try it on the demo site
197
+
198
+ The repo ships a small site with defects planted on purpose — an orphan duplicate, a
199
+ thin page, an oversized image behind `<picture>`, review markup for someone the page
200
+ never names, and more:
201
+
202
+ ```bash
203
+ cd scripts
204
+ python crawl.py --root ../examples/demo-site --out /tmp/crawl.json
205
+ python schema_check.py --crawl /tmp/crawl.json --out /tmp/schema.json
206
+ python audit.py --crawl /tmp/crawl.json --schema /tmp/schema.json --out /tmp/findings.json
207
+ ```
208
+
209
+ [`examples/demo-site/EXPECTED.md`](examples/demo-site/EXPECTED.md) lists exactly what a
210
+ correct run reports — **and what it must stay silent about**, which is the harder half.
211
+
212
+ ## Usage
213
+
214
+ Four verbs, driven through Claude Code:
215
+
216
+ | Verb | Does | Writes |
217
+ | --- | --- | --- |
218
+ | `seo-repair audit <path>` | Crawl → audit → report. Establishes the baseline. | report only |
219
+ | `seo-repair plan` | Ranks findings into stage-ordered batches, previews each diff | nothing |
220
+ | `seo-repair apply <batch>` | Applies **one approved batch**, re-checks that stage | source files |
221
+ | `seo-repair verify` | Re-crawl, diff vs. baseline, regression gate | report only |
222
+
223
+ Nothing is edited without approval. `plan` refuses to run without a baseline; `apply`
224
+ refuses without a named, approved batch.
225
+
226
+ ## What it finds
227
+
228
+ | Stage | Checks |
229
+ | --- | --- |
230
+ | **Crawling & indexing** | `robots.txt` rules, XML sitemap coverage and contradictions, `noindex` directives, canonical tags (missing, cross-page, broken, off-origin), placeholder domains (example.com, localhost) in canonicals and the sitemap, broken internal links, URL hygiene, redirect chains and loops, mixed content, `hreflang` (invalid codes, broken targets, missing self and return tags), sitemap `<lastmod>` validity, response security headers, and client-rendered shells (`--render` compares raw HTML to the rendered DOM) |
231
+ | **Site architecture** | Orphan pages, unreachable pages, click depth, internal link distribution, heading structure, breadcrumbs |
232
+ | **Content & on-page** | Duplicate and near-duplicate content (MinHash), keyword cannibalization, thin content, title tags, meta descriptions, Open Graph tags, image alt text, oversized images, unused assets |
233
+ | **Core Web Vitals** | Lighthouse LCP, CLS and TBT — reported as *lab* metrics, with the localhost caveat stated |
234
+ | **Schema markup** | JSON-LD validity, required and recommended properties, and whether the markup's claims are corroborated by visible page text |
235
+ | **Authority / off-page** | Advisory only. It cannot measure a backlink profile and does not pretend to — it produces a human action list, and refuses paid-link and PBN tactics outright |
236
+
237
+ Findings cite the offending string from your source, so every one is checkable.
238
+
239
+ ## Limitations, stated plainly
240
+
241
+ - **JS rendering is for live URLs.** `seo-repair audit https://... --render` parses
242
+ Chrome's post-JavaScript DOM with a local Chrome, Chromium or Edge, for up to 50 pages
243
+ (`--render-limit`, about 5 seconds each, one browser launch per page). A folder has no
244
+ running site to render, so fs mode only gets the static-shell hint `S1-JS-SHELL`. The
245
+ mobile-overflow check is still Claude Code only (it uses the built-in browser tools).
246
+ The render path is verified against real Chrome on Windows, and in CI on Ubuntu; the
247
+ opt-in test is `SEO_REPAIR_RENDER_TEST=1`. Chrome runs with its sandbox on; as root, or in a container
248
+ where it will not start, set SEO_REPAIR_NO_SANDBOX=1.
249
+ - **Redirect chains, response headers and rendering need an http crawl**, because a
250
+ folder on disk has none of them. Pagination (`rel=next/prev`) is not checked: Google
251
+ stopped using it.
252
+ - **Core Web Vitals need local Chrome.** These are lab numbers from your machine, not
253
+ field data. Real CWV comes from CrUX via Search Console, which is a handoff item.
254
+ - **`vitals.py` is verified on Windows only.** CI runs the test suite on Linux, macOS
255
+ and Windows, but excludes Lighthouse because it needs a browser — so that one script's
256
+ cross-platform behaviour is untested rather than proven. Reports welcome. One opt-in
257
+ test (`SEO_REPAIR_LIGHTHOUSE_TEST=1`) runs real Lighthouse against a local server.
258
+ - **Stage 6 does no off-page work.** By design.
259
+ - **The unused-asset check recommends deletion**, so it is deliberately conservative: a
260
+ filename appearing anywhere in any page's source counts as used. Verify before
261
+ deleting anyway — files can be referenced from a CMS or hot-linked externally.
262
+
263
+ ## Tests
264
+
265
+ ```bash
266
+ python tests/test_skill.py
267
+ ```
268
+
269
+ 146 tests (two are opt-in: real Lighthouse and real Chrome rendering), no fixture files — each builds a throwaway site in a temp directory. They pin
270
+ down calibration decisions made after real false positives: build-directory exclusion,
271
+ deliberate `noindex`, finding grouping, title thresholds, heading order, schema claim
272
+ corroboration, gate boundaries. A failure means *"was this behaviour meant to change"*,
273
+ not *"make it pass"*.
274
+
275
+ ## Contributing
276
+
277
+ Bug reports and pull requests welcome, particularly on non-Windows platforms — the
278
+ Lighthouse integration is the least-tested part of this project.
279
+
280
+ If you change a rule, three things move together: the counts and defect table in
281
+ [`examples/demo-site/EXPECTED.md`](examples/demo-site/EXPECTED.md), and the `required`
282
+ finding ids in the CI workflow. [`RELEASING.md`](RELEASING.md) has the full checklist.
283
+
284
+ ## License
285
+
286
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,265 @@
1
+ # sitemend
2
+
3
+ [![tests](https://github.com/SurendharVr/seo-repair/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/SurendharVr/seo-repair/actions/workflows/tests.yml)
4
+ [![license](https://img.shields.io/github/license/SurendharVr/seo-repair)](LICENSE)
5
+
6
+ **Find the SEO problems Google actually penalises, then fix them in your code.**
7
+
8
+ Built for developers and site owners who keep their site in a codebase and want SEO
9
+ fixes as reviewable diffs, not a PDF of warnings. You approve every change before it's
10
+ applied.
11
+
12
+ A [Claude Code](https://claude.com/claude-code) skill: a site crawler and audit tool that finds indexing problems, orphan pages, duplicate
13
+ content, broken internal links, thin content, missing canonical tags, keyword
14
+ cannibalization and invalid schema markup — then proposes the fixes, applies the ones
15
+ you approve, and re-verifies with a second crawl.
16
+
17
+ `sitemend` is the PyPI package and command-line name. Inside Claude Code the skill and
18
+ plugin are still called `seo-repair`.
19
+
20
+ What makes it different from a checklist: **the order is enforced.** SEO findings are
21
+ not independent, so this treats them as a repair system with a dependency order.
22
+
23
+ ```
24
+ Crawl → Index → Architecture → Content → On-Page → Performance → Schema → Authority → Monitor
25
+ ```
26
+
27
+ Work done out of order is wasted. Optimising a title on a page Google cannot index
28
+ changes nothing. Writing schema for a page about to be merged away is thrown out with
29
+ the page. Building links to either is the most expensive mistake of the three. Three
30
+ **gates** make that ordering unskippable rather than advisory.
31
+
32
+ ---
33
+
34
+ ## What a run looks like
35
+
36
+ Auditing the bundled demo site — the gate lines are the point, and they say *why*, not just *blocked*:
37
+
38
+ ```console
39
+ $ python audit.py --crawl crawl.json --schema schema.json --out findings.json
40
+ 24 findings: 1 critical, 7 high, 7 medium, 9 low
41
+ stage 1: 5
42
+ stage 2: 6
43
+ stage 3: 11
44
+ stage 5: 2
45
+ gate A (Index before content): CLEAR -- every crawled page is indexable
46
+ gate B (Architecture before schema): BLOCKED -- 3 page(s) orphaned or pending consolidation: /, /old-home.html, /reviews.html
47
+ gate C (Everything before authority): BLOCKED -- 8 critical/high finding(s) open in stages 1-5: S1-CANONICAL-CROSS, S1-PLACEHOLDER-DOMAIN, S1-SITEMAP-ORPHAN, S2-ORPHAN
48
+ ```
49
+
50
+ Each run also produces a self-contained HTML dashboard:
51
+
52
+ ![The seo-repair dashboard: severity totals, the seven-stage repair pipeline with gates drawn between the stages, and the three gate cards showing why each is clear or blocked](docs/dashboard.png)
53
+
54
+ Note stage 04. Lighthouse was not run here, so Performance reads **not measured** rather
55
+ than *clear* — a stage that produced no findings because nobody looked at it is not a
56
+ stage that passed, and the dashboard will not imply otherwise.
57
+
58
+ ---
59
+
60
+ ## Two things that make it different
61
+
62
+ **It refuses to invent numbers.** Search volume, keyword difficulty, backlink counts and
63
+ field Core Web Vitals cannot be observed from a codebase. They are never estimated —
64
+ they become a handoff list naming the exact Search Console or Ahrefs report to open.
65
+ Every claim in a report is tagged `MEASURED` (observed directly), `INFERRED` (reasoned
66
+ from observation, stated as such), or `HANDOFF` (not observable here). A local crawl
67
+ proves a page is *crawlable*; it never proves the page is *indexed*, and the report will
68
+ not blur those.
69
+
70
+ The same standard applies to what it writes: no invented author bios, testimonials,
71
+ ratings or trust claims. A tool that refuses to guess at keyword volume has no business
72
+ guessing at a person's credentials.
73
+
74
+ **It checks whether your structured data is honest.** Most validators check that schema
75
+ parses and has its required properties. This one also checks whether the markup asserts
76
+ things the page never shows — a rating nobody can see, an address that appears nowhere,
77
+ or review markup naming people the page does not mention. That last one is a Google
78
+ rich-results policy violation and a manual-action risk, and a property-checker will
79
+ never catch it.
80
+
81
+ ## Versus asking for an SEO audit
82
+
83
+ The alternative to a tool like this is pasting a page into a chat and asking for an SEO
84
+ audit. That gives you advice. This gives you a crawl, with the differences that follow
85
+ from that:
86
+
87
+ | | A checklist prompt | seo-repair |
88
+ | --- | --- | --- |
89
+ | **Coverage** | The pages you paste or open, one at a time | Every page, from a folder or a live URL (200 by default), plus `robots.txt` and `sitemap.xml` |
90
+ | **What it sees** | Text or markup you supply | Real status codes and redirects, canonicals, internal links, orphans, click depth |
91
+ | **Repeatable** | Wording and findings can differ run to run | Same site, same crawl, same findings. `verify` diffs a new run against a baseline |
92
+ | **Evidence** | Advice in prose | Each finding names the page and cites the offending string |
93
+ | **Order of work** | One flat list | Dependency order, with three gates enforced in code: no content work on pages Google cannot index, no schema on orphaned pages, no link building while critical findings are open |
94
+ | **Numbers it cannot measure** | Nothing in a prompt stops a plausible figure | Never stated. Volume, difficulty, backlinks and field Core Web Vitals become a handoff list naming the report to open |
95
+ | **Structured data** | Required properties, if it checks at all | Required properties, and whether the markup claims things the page never shows, such as review authors |
96
+ | **Applying fixes** | Suggestions | One approved batch at a time, then a re-crawl to confirm it worked. Nothing is edited without approval |
97
+ | **In CI** | No | `--fail-on` sets the exit code. An example GitHub Action is in `examples/` |
98
+ | **Tested** | Not testable | 146 tests, many pinned to false positives found on real runs |
99
+
100
+ **How big is the gap?** We measured it on the demo site (5 pages, 14 planted defects).
101
+ Three plain "audit this site" runs by an AI agent with read-only file access found 14, 12
102
+ and 13 of the defects, with one false alarm between them. seo-repair found all 14 with no
103
+ false alarms, gave identical findings on two runs, and took about 3 seconds without using
104
+ a language model. On a site this small a good prompt does well, and it noticed things
105
+ seo-repair does not check, such as a placeholder domain in the sitemap and missing Open
106
+ Graph tags. The advantage is repeatability, scale and CI, not a better score on five
107
+ pages. The demo was built around what seo-repair detects, and this was one model and three
108
+ runs, so read it as an example, not a benchmark.
109
+
110
+ A prompt is the better tool for work that needs the live search results: keyword
111
+ research, reading what the top-ranking pages cover, and writing or rewriting content.
112
+ seo-repair does not do that, and hands it off by design. Use them in that order: fix
113
+ what stops a page being crawled and indexed first, then decide what it should say.
114
+
115
+ ---
116
+
117
+ ## Works with
118
+
119
+ - **Full workflow:** Claude Code (audit, plan, apply, verify).
120
+ - **Standalone:** one command, `sitemend audit <folder|URL>` (or
121
+ `python scripts/seo_repair.py audit ...` from a clone), runs the whole pipeline on
122
+ plain Python 3.9+. No agent needed. See below.
123
+ - **Tested on:** Linux, macOS and Windows. The Lighthouse step is verified on Windows only.
124
+
125
+ ## Install
126
+
127
+ **As a plugin:**
128
+
129
+ ```
130
+ /plugin marketplace add SurendharVr/seo-repair
131
+ ```
132
+
133
+ **Or clone straight into your skills directory:**
134
+
135
+ ```bash
136
+ git clone https://github.com/SurendharVr/seo-repair ~/.claude/skills/seo-repair
137
+ pip install -r ~/.claude/skills/seo-repair/requirements.txt
138
+ ```
139
+
140
+ **Or as a command-line tool, without Claude Code:**
141
+
142
+ ```bash
143
+ pip install git+https://github.com/SurendharVr/seo-repair
144
+ sitemend audit ./my-site
145
+ ```
146
+
147
+ (The wheel is built and tested in CI on every push. `pip install sitemend` from PyPI
148
+ works once a release has been published; see [`RELEASING.md`](RELEASING.md).)
149
+
150
+ Requires Python 3.9+ with `beautifulsoup4`, `lxml` and `requests` (`pip` installs them;
151
+ from a clone, `requirements.txt` lists them). Core Web Vitals and `--render` additionally
152
+ need a local Chrome, Chromium or Edge; Core Web Vitals also need Node, via
153
+ `npx lighthouse`.
154
+
155
+ ## Use it without an agent
156
+
157
+ One command audits a site folder or a live URL and writes a report and dashboard. It
158
+ edits nothing in the site.
159
+
160
+ ```bash
161
+ python scripts/seo_repair.py audit ./my-site # or https://example.com
162
+ python scripts/seo_repair.py audit ./my-site --fail-on high # exit 1 if a high/critical finding is open (CI gate)
163
+ python scripts/seo_repair.py verify ./my-site --baseline seo-repair-out/findings.json
164
+ ```
165
+
166
+ To guard a site on every pull request, copy
167
+ [`examples/github-action/seo-repair.yml`](examples/github-action/seo-repair.yml) to
168
+ `.github/workflows/`. It fails the check when a critical finding is open and attaches
169
+ the report and dashboard to the run.
170
+
171
+ Output lands in `./seo-repair-out`: `findings.json`, `SEO-REPORT-<date>.md` and a
172
+ self-contained `dashboard.html`. Applying fixes stays a Claude Code job, because each
173
+ edit needs your approval.
174
+
175
+ ## Try it on the demo site
176
+
177
+ The repo ships a small site with defects planted on purpose — an orphan duplicate, a
178
+ thin page, an oversized image behind `<picture>`, review markup for someone the page
179
+ never names, and more:
180
+
181
+ ```bash
182
+ cd scripts
183
+ python crawl.py --root ../examples/demo-site --out /tmp/crawl.json
184
+ python schema_check.py --crawl /tmp/crawl.json --out /tmp/schema.json
185
+ python audit.py --crawl /tmp/crawl.json --schema /tmp/schema.json --out /tmp/findings.json
186
+ ```
187
+
188
+ [`examples/demo-site/EXPECTED.md`](examples/demo-site/EXPECTED.md) lists exactly what a
189
+ correct run reports — **and what it must stay silent about**, which is the harder half.
190
+
191
+ ## Usage
192
+
193
+ Four verbs, driven through Claude Code:
194
+
195
+ | Verb | Does | Writes |
196
+ | --- | --- | --- |
197
+ | `seo-repair audit <path>` | Crawl → audit → report. Establishes the baseline. | report only |
198
+ | `seo-repair plan` | Ranks findings into stage-ordered batches, previews each diff | nothing |
199
+ | `seo-repair apply <batch>` | Applies **one approved batch**, re-checks that stage | source files |
200
+ | `seo-repair verify` | Re-crawl, diff vs. baseline, regression gate | report only |
201
+
202
+ Nothing is edited without approval. `plan` refuses to run without a baseline; `apply`
203
+ refuses without a named, approved batch.
204
+
205
+ ## What it finds
206
+
207
+ | Stage | Checks |
208
+ | --- | --- |
209
+ | **Crawling & indexing** | `robots.txt` rules, XML sitemap coverage and contradictions, `noindex` directives, canonical tags (missing, cross-page, broken, off-origin), placeholder domains (example.com, localhost) in canonicals and the sitemap, broken internal links, URL hygiene, redirect chains and loops, mixed content, `hreflang` (invalid codes, broken targets, missing self and return tags), sitemap `<lastmod>` validity, response security headers, and client-rendered shells (`--render` compares raw HTML to the rendered DOM) |
210
+ | **Site architecture** | Orphan pages, unreachable pages, click depth, internal link distribution, heading structure, breadcrumbs |
211
+ | **Content & on-page** | Duplicate and near-duplicate content (MinHash), keyword cannibalization, thin content, title tags, meta descriptions, Open Graph tags, image alt text, oversized images, unused assets |
212
+ | **Core Web Vitals** | Lighthouse LCP, CLS and TBT — reported as *lab* metrics, with the localhost caveat stated |
213
+ | **Schema markup** | JSON-LD validity, required and recommended properties, and whether the markup's claims are corroborated by visible page text |
214
+ | **Authority / off-page** | Advisory only. It cannot measure a backlink profile and does not pretend to — it produces a human action list, and refuses paid-link and PBN tactics outright |
215
+
216
+ Findings cite the offending string from your source, so every one is checkable.
217
+
218
+ ## Limitations, stated plainly
219
+
220
+ - **JS rendering is for live URLs.** `seo-repair audit https://... --render` parses
221
+ Chrome's post-JavaScript DOM with a local Chrome, Chromium or Edge, for up to 50 pages
222
+ (`--render-limit`, about 5 seconds each, one browser launch per page). A folder has no
223
+ running site to render, so fs mode only gets the static-shell hint `S1-JS-SHELL`. The
224
+ mobile-overflow check is still Claude Code only (it uses the built-in browser tools).
225
+ The render path is verified against real Chrome on Windows, and in CI on Ubuntu; the
226
+ opt-in test is `SEO_REPAIR_RENDER_TEST=1`. Chrome runs with its sandbox on; as root, or in a container
227
+ where it will not start, set SEO_REPAIR_NO_SANDBOX=1.
228
+ - **Redirect chains, response headers and rendering need an http crawl**, because a
229
+ folder on disk has none of them. Pagination (`rel=next/prev`) is not checked: Google
230
+ stopped using it.
231
+ - **Core Web Vitals need local Chrome.** These are lab numbers from your machine, not
232
+ field data. Real CWV comes from CrUX via Search Console, which is a handoff item.
233
+ - **`vitals.py` is verified on Windows only.** CI runs the test suite on Linux, macOS
234
+ and Windows, but excludes Lighthouse because it needs a browser — so that one script's
235
+ cross-platform behaviour is untested rather than proven. Reports welcome. One opt-in
236
+ test (`SEO_REPAIR_LIGHTHOUSE_TEST=1`) runs real Lighthouse against a local server.
237
+ - **Stage 6 does no off-page work.** By design.
238
+ - **The unused-asset check recommends deletion**, so it is deliberately conservative: a
239
+ filename appearing anywhere in any page's source counts as used. Verify before
240
+ deleting anyway — files can be referenced from a CMS or hot-linked externally.
241
+
242
+ ## Tests
243
+
244
+ ```bash
245
+ python tests/test_skill.py
246
+ ```
247
+
248
+ 146 tests (two are opt-in: real Lighthouse and real Chrome rendering), no fixture files — each builds a throwaway site in a temp directory. They pin
249
+ down calibration decisions made after real false positives: build-directory exclusion,
250
+ deliberate `noindex`, finding grouping, title thresholds, heading order, schema claim
251
+ corroboration, gate boundaries. A failure means *"was this behaviour meant to change"*,
252
+ not *"make it pass"*.
253
+
254
+ ## Contributing
255
+
256
+ Bug reports and pull requests welcome, particularly on non-Windows platforms — the
257
+ Lighthouse integration is the least-tested part of this project.
258
+
259
+ If you change a rule, three things move together: the counts and defect table in
260
+ [`examples/demo-site/EXPECTED.md`](examples/demo-site/EXPECTED.md), and the `required`
261
+ finding ids in the CI workflow. [`RELEASING.md`](RELEASING.md) has the full checklist.
262
+
263
+ ## License
264
+
265
+ MIT. See [LICENSE](LICENSE).