@seoagent-official/seoagent 1.65.0 → 1.66.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 +4 -0
- package/index.js +107 -90
- package/package.json +5 -3
- package/skills/references/audit-checks.md +35 -9
- package/skills/references/landing-pages.md +2 -0
- package/skills/references/rewrite-protocol.md +1 -0
- package/skills/references/screenshots.md +83 -0
- package/skills/seoagent.md +16 -6
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seoagent-official/seoagent",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "The persistent AI SEO agent for Claude Code. Audits, keyword strategy, briefs, articles, and the autopilot loop (cloud detects → CLI executes → ack closes) — other SEO tools write the prompt, SEOAgent runs it.",
|
|
3
|
+
"version": "1.66.1",
|
|
4
|
+
"description": "The persistent AI SEO agent for Claude Code. Audits, keyword strategy, briefs, articles, real product screenshots from your repo, and the autopilot loop (cloud detects → CLI executes → ack closes) — other SEO tools write the prompt, SEOAgent runs it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"seoagent": "index.js"
|
|
@@ -48,7 +48,9 @@
|
|
|
48
48
|
"keyword-research",
|
|
49
49
|
"internal-links",
|
|
50
50
|
"schema-markup",
|
|
51
|
-
"autopilot"
|
|
51
|
+
"autopilot",
|
|
52
|
+
"product-screenshots",
|
|
53
|
+
"saas-seo"
|
|
52
54
|
],
|
|
53
55
|
"license": "MIT",
|
|
54
56
|
"homepage": "https://seoagent.com",
|
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Loaded by Phase 1 (Technical SEO Audit) when running a full audit. The main `SKILL.md` summarizes the categories; this reference holds the complete check list with the exact pattern to match and the recommendation text.
|
|
4
4
|
|
|
5
|
+
## Verify-before-assert (read first — non-negotiable)
|
|
6
|
+
|
|
7
|
+
**Every factual claim about a page's live state must be grounded in an actual fetch of the live URL — never in repo source, memory, or a prior.** Before running these checks, run `seoagent crawl` (Phase 1 Step 0). It writes `.seoagent/audit/evidence.md` — the live-crawl evidence base (exact title, meta, ALL H1s, canonical + server/client-render flag, every JSON-LD `@type`, OG/Twitter tags, the ACTUAL robots.txt contents, the sitemap URL + blog-post counts, client-rendered-shell detection). Read that file and derive Confirmed findings from it.
|
|
8
|
+
|
|
9
|
+
Three rules govern every finding:
|
|
10
|
+
|
|
11
|
+
1. **Confidence label (mandatory on every finding).** Tag each finding `Confirmed` (verified against the live evidence in `evidence.md` / a fetch you just did), `Likely` (strong inference, not directly verified), or `Hypothesis` (unverified). **Never emit an unverified specific — a price, a line number, a competitor name/roster, a dynamic on-page metric — as a bare fact.** A "2,184 families" style counter that is NOT in the server-fetched HTML is at most `Likely`/`Hypothesis`, never `Confirmed`.
|
|
12
|
+
|
|
13
|
+
2. **Never recommend adding something that already exists.** If `evidence.md` shows the page already serves `Organization` JSON-LD, a canonical tag, OG tags, etc., do NOT recommend adding them — that's the stale-source hallucination this guardrail exists to stop. Only recommend adding what the live evidence shows is genuinely absent.
|
|
14
|
+
|
|
15
|
+
3. **Live-vs-source reconciliation.** When repo/source state and the live-rendered page can disagree, grade the finding against the LIVE site. A repo-only issue (e.g. a `noindex` in a source file that isn't in the served HTML, a robots rule in a committed file that the live `/robots.txt` doesn't serve) must be labeled **"repo-only, unconfirmed on live"** and reported separately — never as production reality.
|
|
16
|
+
|
|
17
|
+
**Do not assert repo-internal specifics (file paths, line numbers) as fact in a live-state finding.** They are fixing *hints*, not verified live facts — mark them `Likely` and phrase as "likely in `app/layout.tsx`", never "on line 42".
|
|
18
|
+
|
|
5
19
|
## Crawlability & Indexation
|
|
6
20
|
|
|
7
21
|
### `robots_txt_exists`
|
|
@@ -10,9 +24,9 @@ Severity if fail: `high`
|
|
|
10
24
|
Recommendation: "Create a robots.txt file at {domain}/robots.txt. At minimum: `User-agent: *\nAllow: /\nSitemap: {domain}/sitemap.xml`."
|
|
11
25
|
|
|
12
26
|
### `robots_txt_blocks_important_paths`
|
|
13
|
-
Check:
|
|
27
|
+
Check: use the ACTUAL robots.txt contents from `evidence.md` (the crawl fetched and parsed the live file). Match its real `Disallow:` rules against the URL list in `pages.md`.
|
|
14
28
|
Severity: `critical` if blocks > 5 known important pages; `high` if blocks any important page.
|
|
15
|
-
Recommendation: List the blocking rules and which pages they affect.
|
|
29
|
+
Recommendation: List **only the blocking rules that actually appear in the fetched robots.txt** and which pages they affect. **Never invent a rule** (e.g. do NOT claim `Disallow: /private/` unless it is verbatim in the fetched file) — quoting a rule that isn't there is the exact hallucination this audit must avoid. If robots.txt wasn't fetched, this check is `Hypothesis` — say "couldn't verify robots.txt" rather than asserting any rule.
|
|
16
30
|
|
|
17
31
|
### `sitemap_exists`
|
|
18
32
|
Check: WebFetch `{domain}/sitemap.xml`. Pass = 200 OK and parseable XML.
|
|
@@ -67,6 +81,11 @@ Recommendation: "{dependency_url} returned {status}. The pages it powers ({list}
|
|
|
67
81
|
|
|
68
82
|
> **Why this check matters:** the most common SEO disaster on a live site is a CMS that's been quietly down for weeks — every page returns 200, the audit looks clean, but Google has been deindexing the blog the whole time. This check catches it on the first audit.
|
|
69
83
|
|
|
84
|
+
### `client_rendered_shell`
|
|
85
|
+
Check: `evidence.md` flags the page as a client-rendered shell — the server HTML is near-empty and/or shows a "Loading…" placeholder with no in-body links. The classic case is a blog index that ships a `Loading…` shell with no post `<a>` links in the server HTML: crawlers (and this fetch) see zero posts.
|
|
86
|
+
Severity: `critical` if it's a content-listing / blog-index / indexable page; `high` otherwise.
|
|
87
|
+
Recommendation: "This page renders client-side — the server HTML has no content/links, so crawlers can't see it (Confirmed from the crawl). Server-render or pre-render it (SSR/SSG/ISR) so the {posts/listings} are in the initial HTML. Any on-page data on this page (counts, listings) is Likely/Hypothesis until it's server-rendered."
|
|
88
|
+
|
|
70
89
|
## On-Page SEO
|
|
71
90
|
|
|
72
91
|
### `title_missing`
|
|
@@ -105,9 +124,9 @@ Severity: `high`
|
|
|
105
124
|
Recommendation: "Add exactly one `<h1>` containing the primary keyword."
|
|
106
125
|
|
|
107
126
|
### `h1_multiple`
|
|
108
|
-
Check: more than one `<h1>` in
|
|
127
|
+
Check: `evidence.md` lists more than one `<h1>` for the page (it captures ALL H1s in document order, so conflicting H1s are detected).
|
|
109
128
|
Severity: `medium`
|
|
110
|
-
Recommendation: "Reduce to one
|
|
129
|
+
Recommendation: "Page has {N} `<h1>`s ({list}). Reduce to one; demote the others to `<h2>`/`<h3>`."
|
|
111
130
|
|
|
112
131
|
### `heading_hierarchy_skipped`
|
|
113
132
|
Check: H1 → H3 with no H2 between, or H2 → H4 with no H3.
|
|
@@ -141,6 +160,11 @@ Check: `<img>` tags without `alt=""` attribute (decorative images should have em
|
|
|
141
160
|
Severity: `medium` if > 3 images; `low` otherwise.
|
|
142
161
|
Recommendation: "Add descriptive alt text to {N} images. SEOAgent can write these — `seoagent.js` does it automatically on production."
|
|
143
162
|
|
|
163
|
+
### `missing_product_screenshots`
|
|
164
|
+
Applies only when `project.md` has `site_type: saas` (or the repo renders a real product UI). Check: a landing / feature / how-to page that describes the product but has **no real product screenshot** in its hero or feature sections (illustration-only, stock photo, or no image where a UI shot belongs).
|
|
165
|
+
Severity: `low` (a conversion + trust gap, not an indexation issue).
|
|
166
|
+
Recommendation: "Add a real product screenshot to the hero + feature sections — read `references/screenshots.md` to capture them from the product's own code in this repo. Real UI shots out-convert AI illustrations on a SaaS page."
|
|
167
|
+
|
|
144
168
|
### `internal_links_count`
|
|
145
169
|
Check: number of `<a>` tags pointing to same-domain URLs in body.
|
|
146
170
|
Severity: `medium` if 0 (orphan); `low` if < 3.
|
|
@@ -197,18 +221,20 @@ Recommendation: "Add an FAQ section with 5-7 H3 questions. Powers FAQ schema and
|
|
|
197
221
|
|
|
198
222
|
## Schema Markup
|
|
199
223
|
|
|
224
|
+
> **Schema checks MUST use `evidence.md`, not WebFetch.** WebFetch strips `<script>` tags — it CANNOT see JSON-LD, so "no schema found" from WebFetch is a false negative that leads directly to recommending schema the page already serves. The `seoagent crawl` evidence base parses raw HTML and lists every JSON-LD `@type` present per page. Read that. **Only flag a schema type as missing when `evidence.md` shows it is genuinely absent — never recommend adding a `@type` that already appears in the evidence.**
|
|
225
|
+
|
|
200
226
|
### `no_json_ld_on_article`
|
|
201
|
-
Check: page is a blog article (URL pattern `/blog/*`)
|
|
227
|
+
Check: page is a blog article (URL pattern `/blog/*`) AND `evidence.md` shows **no `Article` (or `BlogPosting`/`NewsArticle`) `@type`** for it.
|
|
202
228
|
Severity: `medium`
|
|
203
|
-
Recommendation: "Add `Article` JSON-LD with headline, author, datePublished, dateModified, image, publisher.logo. See `references/schema-markup.md`."
|
|
229
|
+
Recommendation (only if genuinely absent): "Add `Article` JSON-LD with headline, author, datePublished, dateModified, image, publisher.logo. See `references/schema-markup.md`."
|
|
204
230
|
|
|
205
231
|
### `no_organization_schema_on_homepage`
|
|
206
|
-
Check: homepage has no `Organization`
|
|
232
|
+
Check: `evidence.md` shows the homepage has **no `Organization` `@type`** (and no `SoftwareApplication`/`WebSite` that would already cover the brand entity). If the evidence lists `Organization`/`SoftwareApplication`, this check PASSES — do not recommend adding it.
|
|
207
233
|
Severity: `medium`
|
|
208
|
-
Recommendation: "Add `Organization` JSON-LD on homepage with name, url, logo, sameAs links to social profiles."
|
|
234
|
+
Recommendation (only if genuinely absent): "Add `Organization` JSON-LD on homepage with name, url, logo, sameAs links to social profiles."
|
|
209
235
|
|
|
210
236
|
### `note_schema_detection_limitation`
|
|
211
|
-
|
|
237
|
+
Schema is verified from `evidence.md` (raw-HTML JSON-LD parse), not WebFetch. If the crawl couldn't run, treat any "no schema" conclusion as `Hypothesis` and tell the user: "Test your pages at https://search.google.com/test/rich-results — I couldn't verify JSON-LD via WebFetch (it strips `<script>` blocks). Run `seoagent crawl` for a verified read."
|
|
212
238
|
|
|
213
239
|
## Site Architecture
|
|
214
240
|
|
|
@@ -145,6 +145,8 @@ Landing pages need:
|
|
|
145
145
|
- 2-4 feature/inline images — actual screenshots, not stock photography
|
|
146
146
|
- 1 OG image — branded, includes product name and value prop, 1200×630
|
|
147
147
|
|
|
148
|
+
**For a SaaS / product site, the hero + feature images should be real product screenshots — read `references/screenshots.md`** for how to capture them from the product's own code in this repo (no Playwright/paid API) and where to place them. Real UI shots out-convert AI illustrations on a SaaS landing page; only fall back to a generated image when a screenshot isn't possible.
|
|
149
|
+
|
|
148
150
|
In article frontmatter:
|
|
149
151
|
```yaml
|
|
150
152
|
images:
|
|
@@ -125,6 +125,7 @@ Same protocol but:
|
|
|
125
125
|
- Don't ship the rewrite during a campaign in flight — coordinate with the user
|
|
126
126
|
- Update OG card and Twitter card alt text (often forgotten)
|
|
127
127
|
- Update JSON-LD `Product` / `Offer` if pricing or feature claims changed
|
|
128
|
+
- **Screenshot-gap pass (SaaS sites):** during the diagnosis (Step 3), scan the page for hero/feature sections that describe the product but show no real screenshot (illustration-only, stock, or empty). For each gap, capture a real product screenshot from this repo's UI per `references/screenshots.md` and fold it into the rewrite — this is how an *existing* SaaS landing page gets the screenshots it's missing.
|
|
128
129
|
|
|
129
130
|
### Rewriting Without an Existing Brief
|
|
130
131
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Product Screenshot Protocol
|
|
2
|
+
|
|
3
|
+
Use when the site is a **SaaS / product app** and a page or article would be stronger with a **real screenshot of the product's UI**. A genuine product screenshot is the single highest-converting visual on a SaaS landing page or how-to article — it beats AI illustrations and stock photography every time.
|
|
4
|
+
|
|
5
|
+
**You capture these yourself, from the product's own code in this repo.** No Playwright/Puppeteer dependency, no paid screenshot API — use the screenshot capability already available in your environment (a connected browser/preview tool, or the project's own dev server). If you have no way to capture, fall back gracefully (see **Fallback**) — never block a page on a screenshot.
|
|
6
|
+
|
|
7
|
+
## When this applies (SaaS gate)
|
|
8
|
+
|
|
9
|
+
Only pursue product screenshots when **both** are true:
|
|
10
|
+
|
|
11
|
+
1. **The site is a SaaS / product app**, not a content/local/services site. Confirm from the repo, which is the ground truth:
|
|
12
|
+
- `project.md` has `site_type: saas`, **or**
|
|
13
|
+
- the repo renders a real UI (an app shell, dashboard, feature components under `app/`, `src/components/`, etc.) — a product you could screenshot.
|
|
14
|
+
- A plumber's blog, a media site, or a pure-marketing repo with no product UI → **skip this protocol**.
|
|
15
|
+
2. **A specific spot would be stronger with a UI shot and doesn't have one** (see Gap Evaluation).
|
|
16
|
+
|
|
17
|
+
If the cloud queued an action whose body has a **"Screenshots to capture"** section, the SaaS gate is already a yes — go straight to Gap Evaluation + Capture.
|
|
18
|
+
|
|
19
|
+
## Where product screenshots add value
|
|
20
|
+
|
|
21
|
+
| Page / section | Shot to capture |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Landing **hero** | The product's primary screen (dashboard, main view) — the "this is the thing" shot |
|
|
24
|
+
| Landing **feature deep-dives** | The specific UI for each feature being described (one shot per feature section) |
|
|
25
|
+
| **How-to / tutorial** article steps | The screen the step is describing — capture the actual state for that step |
|
|
26
|
+
| **Comparison** pages | The product's UI for the capability being compared |
|
|
27
|
+
|
|
28
|
+
Don't over-shoot: 1 hero + 2–4 feature shots is the sweet spot for a landing page. A how-to gets one shot per major step that has a UI.
|
|
29
|
+
|
|
30
|
+
## Gap Evaluation (new pages AND existing ones)
|
|
31
|
+
|
|
32
|
+
Scan the page for **missing visuals** — places where the reader is asked to imagine UI that you could just show:
|
|
33
|
+
|
|
34
|
+
- A feature `<section>` / feature block describing the product with **no image**.
|
|
35
|
+
- A how-to step ("Click **Connect**", "Open the dashboard") with **no screenshot** of that screen.
|
|
36
|
+
- A landing **hero** with no product shot (or a stock/illustration placeholder where a real screen belongs).
|
|
37
|
+
- Prose like "see the X view", "your dashboard shows…", "the editor lets you…" with nothing to look at.
|
|
38
|
+
|
|
39
|
+
Each gap that passes the SaaS gate is a screenshot to capture. When auditing/refreshing an **existing** landing page, this same scan is how you find screenshots to add — fold the gaps into the rewrite (see `references/rewrite-protocol.md`).
|
|
40
|
+
|
|
41
|
+
## Capture
|
|
42
|
+
|
|
43
|
+
1. **Find the route/component** in this repo that renders the UI you want — the page route (e.g. `app/dashboard/page.tsx`, a feature page) or a self-contained component you can render in isolation.
|
|
44
|
+
2. **Render it.** Detect the project's dev command from `package.json` `scripts` (`dev`, then `start`) and start it (or reuse a server that's already running). Note the local URL (e.g. `http://localhost:3000/<route>`).
|
|
45
|
+
3. **Capture a PNG** of the rendered route using the screenshot capability available in your environment. Frame/crop to the relevant UI — show the feature, not the whole browser chrome. Use a clean state (seeded/demo data, no personal info, no error toasts).
|
|
46
|
+
- **Do NOT** add Playwright/Puppeteer to the project, and **do NOT** call a paid screenshot API just for this. Use what's already available.
|
|
47
|
+
4. **Save it** to the repo's public asset directory — detect the convention (`public/screenshots/`, `static/screenshots/`, `assets/`) and create `screenshots/` there if absent. Name it `{page-slug}-{section}.png` (e.g. `pricing-hero.png`, `seo-audit-feature.png`).
|
|
48
|
+
5. **Reference it** in the page/article with descriptive, keyword-aware alt text and responsive markup that matches how the site embeds images (Next.js `<Image>`, MDX ``, an existing image component — match the site's pattern). Alt text describes the screen + the keyword, e.g. `alt="SEOAgent dashboard showing a completed technical SEO audit with severity badges"`.
|
|
49
|
+
|
|
50
|
+
## Frontmatter
|
|
51
|
+
|
|
52
|
+
When the page uses `images:` frontmatter (landing pages, content), record the screenshot as a captured asset, not an AI prompt:
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
images:
|
|
56
|
+
hero:
|
|
57
|
+
alt: "SEOAgent dashboard showing a completed audit with green/red severity badges"
|
|
58
|
+
src: /screenshots/dashboard-hero.png # captured product screenshot (preferred for SaaS)
|
|
59
|
+
inline:
|
|
60
|
+
- alt: "The keyword research view with volume and difficulty columns"
|
|
61
|
+
src: /screenshots/keywords-feature.png
|
|
62
|
+
placement: "after H2 'Keyword research'"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`src` = a real captured screenshot. Fall back to `prompt:` (AI image) only when a screenshot isn't possible.
|
|
66
|
+
|
|
67
|
+
## Fallback (never block the page)
|
|
68
|
+
|
|
69
|
+
If the product can't be rendered/captured (no dev server, no screenshot tool available, the route needs auth you don't have, or there's no real UI yet):
|
|
70
|
+
|
|
71
|
+
- Leave a marker where the shot belongs so the gap is visible and actionable later:
|
|
72
|
+
```html
|
|
73
|
+
<!-- SCREENSHOT-TODO: capture the {feature} screen at {route} and place here -->
|
|
74
|
+
```
|
|
75
|
+
- Also write an AI image `prompt:` into the frontmatter (existing flow in `references/landing-pages.md` → Images) so publishing still succeeds with *some* visual.
|
|
76
|
+
- Mention to the user in one line what you couldn't capture and why, so they can run the dev server / point you at the right screen.
|
|
77
|
+
|
|
78
|
+
## Conventions
|
|
79
|
+
|
|
80
|
+
- One folder for captures (`public/screenshots/` or the repo's equivalent) — don't scatter PNGs.
|
|
81
|
+
- Real, current UI only — never fabricate a screenshot or reuse a competitor's.
|
|
82
|
+
- No PII / no real customer data in the frame — use demo/seed state.
|
|
83
|
+
- Re-capture when the UI changes materially (a feature redesign stales old shots) — the Gap Evaluation on a refresh catches this.
|
package/skills/seoagent.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: seoagent
|
|
3
|
-
description: "Persistent AI SEO agent. ALWAYS use when the user mentions: SEO, ranking, rank, keywords, meta tags, search traffic, organic traffic, content strategy, audit, Google, Bing, Search Console, GSC, schema markup, JSON-LD, sitemap, robots.txt, internal linking, AI search, AEO, GEO, OKF, Open Knowledge Format, AI knowledge bundle, llms.txt, alt text, page speed, Core Web Vitals, slug, URL structure, canonical, breadcrumbs, hub and spoke, pillar content, topic cluster, programmatic SEO, landing page SEO, blog SEO, listicle, best-of / top-N roundup, why am I not ranking. Also use SILENTLY when the user asks to write, edit, or improve a blog post, landing page, marketing copy, or any file under content/, posts/, blog/, pages/ — these are SEO-adjacent and should persist to .seoagent/ even without an explicit invocation. Replaces separate seo-audit, content-strategy, programmatic-seo, ai-seo, site-architecture, and schema-markup skills with one unified, persistent workflow."
|
|
3
|
+
description: "Persistent AI SEO agent. ALWAYS use when the user mentions: SEO, ranking, rank, keywords, meta tags, search traffic, organic traffic, content strategy, audit, Google, Bing, Search Console, GSC, schema markup, JSON-LD, sitemap, robots.txt, internal linking, AI search, AEO, GEO, OKF, Open Knowledge Format, AI knowledge bundle, llms.txt, alt text, page speed, Core Web Vitals, slug, URL structure, canonical, breadcrumbs, hub and spoke, pillar content, topic cluster, programmatic SEO, landing page SEO, blog SEO, listicle, best-of / top-N roundup, product screenshots, SaaS screenshots, why am I not ranking. Also use SILENTLY when the user asks to write, edit, or improve a blog post, landing page, marketing copy, or any file under content/, posts/, blog/, pages/ — these are SEO-adjacent and should persist to .seoagent/ even without an explicit invocation. Replaces separate seo-audit, content-strategy, programmatic-seo, ai-seo, site-architecture, and schema-markup skills with one unified, persistent workflow."
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, WebFetch, WebSearch
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -43,6 +43,7 @@ This SKILL.md is the orchestration layer. Detailed protocols live in `references
|
|
|
43
43
|
| Writing a sub-pillar article | `references/sub-pillar-articles.md` |
|
|
44
44
|
| Writing a long-tail article | `references/long-tail-articles.md` |
|
|
45
45
|
| Writing a listicle ("Top N" / "Best X") | `references/listicle-articles.md` |
|
|
46
|
+
| Adding **product screenshots** to a SaaS page/article (or a "Screenshots to capture" inbox action) | `references/screenshots.md` |
|
|
46
47
|
| Programmatic SEO at scale | `references/programmatic.md` |
|
|
47
48
|
| Adding schema markup / JSON-LD | `references/schema-markup.md` |
|
|
48
49
|
| Refreshing or rewriting an existing page | `references/rewrite-protocol.md` |
|
|
@@ -166,6 +167,7 @@ Offer **once per session per topic**; if declined, drop it and keep working. Nev
|
|
|
166
167
|
- `Read` it. The frontmatter has `action_id`, `brief_slug`, `primary_keyword`, `cluster`, and `priority`. The body points at the synced brief.
|
|
167
168
|
- **Read the full brief** under `.seoagent/` (briefs file or `strategy/` entry matching `brief_slug`) for the outline, word-count target, and internal-link plan.
|
|
168
169
|
- Write the article following the skill's **content-production protocol** (Phase 4 below), then publish it where this project's content lives (repo `content/` or the connected CMS — you are the publishing engine). Show the user the draft before publishing.
|
|
170
|
+
- **If the action body has a "Screenshots to capture" section** (autopilot flagged this as a SaaS product), follow `references/screenshots.md` — capture real product screenshots from this repo's UI for the relevant sections instead of shipping illustration-only.
|
|
169
171
|
- Acknowledge it: `seoagent ack <action_id>` (or `--failed --reason "skipped; off-strategy"` to decline).
|
|
170
172
|
|
|
171
173
|
5. For each `cli_content_update-<id>.md` file:
|
|
@@ -185,6 +187,7 @@ Offer **once per session per topic**; if declined, drop it and keep working. Nev
|
|
|
185
187
|
- Cross-reference `.seoagent/keywords.md` for related keywords — they tell you which cluster this page belongs to and which secondary keywords to weave in.
|
|
186
188
|
- Pick an article type from `intent` (commercial/transactional → product or comparison page; informational → guide or pillar). Pick a clean URL slug from `keyword`.
|
|
187
189
|
- Write the article following the skill's **content-production protocol** (Phase 4 — match the article type's quality rules, add internal links from related cluster pages, etc.). Show the user the draft before publishing.
|
|
190
|
+
- **If the action body has a "Screenshots to capture" section** (SaaS product), follow `references/screenshots.md` — a landing page for a SaaS product should lead with a real product screenshot in the hero + feature sections, captured from this repo's UI.
|
|
188
191
|
- Publish where this project's content lives (repo `content/` or the connected CMS). Safe (new content) — but still confirm the user wants this specific page before committing.
|
|
189
192
|
- Acknowledge it: `seoagent ack <action_id>` (or `--failed --reason "already covered by /existing-page"` to decline).
|
|
190
193
|
|
|
@@ -389,9 +392,12 @@ Once approved, work **a cluster at a time**, top of the plan down:
|
|
|
389
392
|
|
|
390
393
|
## Phase 1: Technical SEO Audit
|
|
391
394
|
|
|
392
|
-
### Step 0 (mandatory)
|
|
395
|
+
### Step 0 (mandatory — capture the live-crawl evidence base, then read the checks)
|
|
393
396
|
|
|
394
|
-
**
|
|
397
|
+
1. **Run `seoagent crawl` first.** It fetches the homepage + top pages, the real robots.txt, and the live sitemap, and writes `.seoagent/audit/evidence.md` — the verified evidence base (exact title/meta, ALL H1s, canonical + server/client-render flag, every JSON-LD `@type`, OG/Twitter tags, the ACTUAL robots.txt contents, sitemap URL + blog-post counts, client-rendered-shell detection). **`Read` that file — every `Confirmed` finding must be derived from it, not from repo source or memory.** (Use `seoagent crawl --json` if you want the structured bundle.)
|
|
398
|
+
2. **Read `.claude/skills/seoagent/references/audit-checks.md`.** It contains the full check list, the **Verify-before-assert** rules (confidence labels, never-recommend-what-exists, live-vs-source reconciliation), severity tiers, and recommendation text per check. Do not run the audit from memory — the reference is the source of truth and gives consistent results across sessions.
|
|
399
|
+
|
|
400
|
+
**Verify-before-assert is the load-bearing rule of the whole audit.** Never state a live-page fact you didn't fetch: don't invent a robots.txt rule, don't recommend adding schema/canonical/OG tags the evidence shows already exist, don't report a dynamic on-page number (a "2,184 families" counter) as `Confirmed` unless it's in the server-fetched HTML. Tag every finding `Confirmed` / `Likely` / `Hypothesis`. If `seoagent crawl` couldn't run (offline, no domain), fall back to per-page WebFetch — but remember WebFetch strips `<script>`, so schema conclusions from it are `Hypothesis`, never `Confirmed`.
|
|
395
401
|
|
|
396
402
|
### Procedure
|
|
397
403
|
|
|
@@ -451,7 +457,7 @@ When the user says "I fixed X":
|
|
|
451
457
|
2. Append to `changelog.md`: `[date] Fixed: {finding}`.
|
|
452
458
|
3. Run `seoagent sync`.
|
|
453
459
|
|
|
454
|
-
> **Rule**: Before reporting
|
|
460
|
+
> **Rule (verify-before-assert)**: Before reporting ANY live-state fact — a URL is missing/broken, robots.txt blocks a path, a page lacks schema, a title/H1/canonical value — it must be grounded in an actual fetch (`seoagent crawl`'s `evidence.md`, or a WebFetch you just ran). Never assume a 404, a robots rule, or a missing schema from inference/repo source alone. Every finding carries a confidence tag (`Confirmed`/`Likely`/`Hypothesis`); unverified specifics (prices, line numbers, competitor names, dynamic counters) are never emitted as bare fact.
|
|
455
461
|
|
|
456
462
|
---
|
|
457
463
|
|
|
@@ -737,9 +743,13 @@ This is the per-article procedure. When executing an approved **plan** (see "Pla
|
|
|
737
743
|
- **Cloud-hosted (`managed_proxy` / `subdomain`)** — the SEOAgent cloud renders the article, so the body DOES live in `.seoagent/`: write the full article to `.seoagent/content/{slug}.md` with full SEO frontmatter (slug, page_type, title, meta_title, meta_description, canonical, og, twitter, json_ld, images, internal_links) and `seoagent sync`. (No `content track` needed — the full file is the record.)
|
|
738
744
|
8. **Update the cluster's link graph** — for sub_pillar/long_tail writes, edit the parent (and the cluster file) to add the new link UP. For pillar writes, ensure all sub_pillars are referenced.
|
|
739
745
|
|
|
746
|
+
### Product Screenshots (SaaS — do this before AI images)
|
|
747
|
+
|
|
748
|
+
**If `project.md` has `site_type: saas` (or the repo renders a real product UI), prefer real product screenshots over AI illustrations** — they're the highest-converting visual on a SaaS landing page or how-to article. Before falling back to a generated image, **read `references/screenshots.md`** and follow it: scan the page for spots where a UI shot would add value and is missing (hero, feature sections, how-to steps), then capture those screens **from the product's own code in this repo** (using your environment's screenshot capability + the project's dev server — no Playwright/Puppeteer dependency, no paid API), save them under `public/screenshots/`, and reference them with descriptive alt text. If you can't capture (no dev server / no screenshot tool / no real UI), the protocol's fallback leaves a `<!-- SCREENSHOT-TODO -->` marker + an AI image prompt so publishing still works. Non-SaaS sites skip this and go straight to image generation below.
|
|
749
|
+
|
|
740
750
|
### Image Generation (Free Tier)
|
|
741
751
|
|
|
742
|
-
Always write `images:` frontmatter with `alt` and `prompt
|
|
752
|
+
Always write `images:` frontmatter with `alt` and `prompt` (or `src` for a captured screenshot — see Product Screenshots above). Then resolve a provider — **don't silently ship imageless articles:**
|
|
743
753
|
|
|
744
754
|
1. **If `project.md` has `image_provider` set to `openai|fal|replicate`**, offer to generate the hero image:
|
|
745
755
|
|
|
@@ -904,7 +914,7 @@ The CLI manages credentials at `~/.config/seoagent/auth.json` — outside the pr
|
|
|
904
914
|
7. **End with the plan's next step, not a menu.** When executing an approved plan, close with progress + what's next in the plan ("3 of 8 in this cluster done; writing the next now"), not a 2–3-option menu every turn. Offer explicit choices only at real decision points (the plan-approval gate, a cluster boundary, an ambiguous call).
|
|
905
915
|
8. **Update the roadmap and changelog** after every action.
|
|
906
916
|
9. **Sync after every artifact write.** Run `seoagent sync` (no-op when not logged in — always run it).
|
|
907
|
-
10. **
|
|
917
|
+
10. **Verify before you assert.** Every claim about a page's live state (robots.txt rules, schema/JSON-LD, meta tags, titles, headings, canonical, sitemap contents, whether a URL exists) must be grounded in an actual live fetch — `seoagent crawl`'s `.seoagent/audit/evidence.md` or a WebFetch you just ran — never repo source, memory, or a prior. **Never recommend adding something the live page already has.** Tag every finding `Confirmed` / `Likely` / `Hypothesis`; never emit an unverified specific (price, line number, competitor, dynamic on-page metric) as a bare fact. Repo-only issues that aren't confirmed on the live site are labeled and reported separately, not as production reality.
|
|
908
918
|
11. **Use the output template** for all top-level reports.
|
|
909
919
|
12. **Read context before generating.** Before any strategy, brief, or article, read `.seoagent/context.md`.
|
|
910
920
|
13. **Plan once, then execute** (see "Plan & Execute"). Get one approval on the content plan, then run it in batches (a cluster at a time) — don't ask `Continue?` between articles or phases. Pause only for: the plan approval, cluster boundaries (show drafts + open a PR), ambiguous decisions, and destructive actions. Go fully autonomous or step-by-step if the user asks.
|