.claude/skills/seo-page-brief/SKILL.md
Write an SEO page brief for one keyword with SEOBolt MCP tools. Decides optimise-vs-create from Search Console, checks difficulty and the SERP, and outputs outline, original element, internal links, title, meta and schema. Use before writing or rewriting any page.
---
name: seo-page-brief
description: Write an SEO page brief for one keyword with SEOBolt MCP tools. Decides optimise-vs-create from Search Console, checks difficulty and the SERP, and outputs outline, original element, internal links, title, meta and schema. Use before writing or rewriting any page.
---
# SEO page brief
Keyword: `$ARGUMENTS`. If it is empty, ask for one keyword and stop until you have it.
Follow the `seo-agent-rules` skill (`${CLAUDE_SKILL_DIR}/../seo-agent-rules/SKILL.md`) for every step; read it first if it is not loaded. This skill only writes a draft file.
## 1. Project
Call `seo_projects`, pick the project for this site, note its id and domain. GSC `siteUrl` is `sc-domain:<domain>`; if a GSC tool errors, retry once with `https://<domain>/`.
## 2. Optimise or create (one keyword, one page)
1. `seo_gsc_cannibalization` with `siteUrl`. If the keyword or a close variant already splits impressions across 2+ URLs, stop: the brief becomes a consolidation proposal (primary URL, action, evidence). Hand it to `seo-fix-existing`.
2. `seo_gsc_secondary_keywords` with `siteUrl` and no `url` (covers the top pages), plus `seo_gsc_content_opportunities` with `siteUrl`: find any page that already gets impressions for the keyword. If one of the site's pages ranks in the top 20 for it, the decision is **optimise that URL**. Otherwise **create** a new page.
3. For the URL you optimise (or the closest related page when creating), run `seo_gsc_secondary_keywords` with `siteUrl` and `url`, and record the queries it ranks top 10 for. These come from the site's own GSC only; say so in the brief.
## 3. Demand and difficulty
1. `seo_keyword_difficulty` with the keyword: difficulty, volume, and the top results with their DR. State where the volume came from (Google Ads data or a Search Console estimate).
2. `seo_domain_rating` for the site. If nearly every top result has a far higher DR, recommend a narrower long-tail variant instead, and say why.
3. Classify intent from the top results: which page type ranks (landing page, comparison, listicle, guide, tool). The brief must use that page type.
## 4. Competitors
`seo_compare` with the site's closest page (or homepage when creating) against the #1 result. Note what the top 3 results cover, in order. Optionally run `seo_content_gap` with 1-3 competitor domains.
## 5. Write the brief
Save to `seo-briefs/<slug>.md` with these sections:
- **Decision**: optimise `<url>` or create `/<slug>`, with the evidence.
- **Keyword data**: keyword, difficulty, volume and its source, intent, page type, secondary keywords.
- **Outline**: H1 containing the keyword, then H2s in the order the searcher needs answers (what the SERP answers first comes first). One line per H2 on what it must say.
- **Original element**: the one thing the top 10 lack (quiz, calculator, own data table, real screenshots or photos, video, real tool output). Name it, its data source, and where it sits. It must be real; never fabricated data. `seo-ship-page` blocks publishing without it.
- **Internal links**: at least 5 existing pages that will link to this page from body copy (not nav or footer). For each: source URL, anchor (the keyword or a close variant), and the sentence it goes in. Find candidates with `seo_gsc_reality` top pages and a repo search for the topic.
- **Title**: max 60 characters including the site's title suffix; keyword first, top 2-3 secondary keywords where they fit.
- **Meta description**: 140-155 characters, contains the keyword, sells the click.
- **Schema**: JSON-LD types matching the page type and visible content (for example BreadcrumbList, FAQPage only if the FAQ is visible, SoftwareApplication or Article).
## 6. Report
Reply with the decision, the original element, and the brief path. Next step: `seo-ship-page seo-briefs/<slug>.md`.
.claude/skills/seo-ship-page/SKILL.md
Build and ship one SEO page from a brief on the site's own template, with 5+ in-body inbound links, structured data and a sitemap entry, behind a gate that stops if the original element or any section was lost. Re-crawls with SEOBolt MCP tools after deploy.
---
name: seo-ship-page
description: Build and ship one SEO page from a brief on the site's own template, with 5+ in-body inbound links, structured data and a sitemap entry, behind a gate that stops if the original element or any section was lost. Re-crawls with SEOBolt MCP tools after deploy.
---
# Ship an SEO page
Brief or URL: `$ARGUMENTS`. If there is no brief, run `seo-page-brief` first.
Follow the `seo-agent-rules` skill (`${CLAUDE_SKILL_DIR}/../seo-agent-rules/SKILL.md`) for every step; read it first if it is not loaded. Publishing and edits to existing pages need approval.
## 1. Before you edit
1. Cadence: check the SEO log and `git log --since="7 days ago"`. If 2 new pages already shipped this week (or 1 today on a site under 6 months old), stop and report.
2. If the page exists, snapshot it: `curl -s <url> > /tmp/seo-before.html`, and list its H2 sections and its original element (quiz, calculator, table, data, media embed, tool output).
## 2. Build
1. Find a live page of the same type in the repo and build on its template: layout, metadata pattern, JSON-LD pattern, canonical pattern. Do not invent a new layout.
2. Write the content from the brief: H1, H2s in brief order, the original element, FAQ if the brief has one.
3. Structured data mirrors visible content only (FAQPage only for a visible FAQ). A new page keeps the template's self-referencing canonical; never change an existing page's canonical or robots directives.
4. Add the 5+ inbound links from the brief to existing pages, each inside body copy with the brief's anchor. These are edits to existing pages: batch them into one diff for approval.
5. Add the URL to the sitemap, or confirm the generated sitemap includes it.
## 3. GATE (all checks must pass before asking to publish)
Run `git diff` and compare with the snapshot.
- [ ] The original element is present and works.
- [ ] Every H2 section the page had before is still there (existing pages).
- [ ] Exactly one H1; title max 60 characters including suffix; meta description 140-155 characters.
- [ ] JSON-LD parses and matches visible content.
- [ ] At least 5 in-body links point to the page (count them in the diff).
- [ ] The sitemap lists the URL.
If the original element was removed or any existing section is gone, **STOP**. Restore it, report what happened, and do not continue to publishing. Fix other failures, then rerun the gate.
## 4. Publish (approval required)
Show the diff summary and gate results. Publish only after an explicit yes, using the repo's normal commit and deploy process.
## 5. Verify
1. `curl -s -o /dev/null -w "%{http_code}" <url>` returns 200; the live title and H1 match.
2. `seo_start_crawl` for the project; when it finishes, `seo_audit`, then `seo_fix_suggestions` with the project id and URL. Fix new issues and rerun the gate.
3. Indexing (approval required): if the site hosts an IndexNow key file, submit the URL to `https://api.indexnow.org/indexnow`. Otherwise ask the human to use SEOBolt's Submit Sitemap page (`/dashboard/submit-sitemap`) or Search Console URL Inspection, Request indexing.
4. Add an SEO log entry: date, URL, new or optimised, original element, inbound link sources, and a check-back date 2 months out.
.claude/skills/seo-weekly-review/SKILL.md
Monday SEO review with SEOBolt MCP tools. Pulls Search Console reality, repoint and cannibalisation lists, prune candidates (report only) and the top fix-plan items, skips pages edited in the last 60 days, and writes an SEO log entry. Run once a week, never faster.
---
name: seo-weekly-review
description: Monday SEO review with SEOBolt MCP tools. Pulls Search Console reality, repoint and cannibalisation lists, prune candidates (report only) and the top fix-plan items, skips pages edited in the last 60 days, and writes an SEO log entry. Run once a week, never faster.
---
# Weekly SEO review (Mondays)
Follow the `seo-agent-rules` skill (`${CLAUDE_SKILL_DIR}/../seo-agent-rules/SKILL.md`) for every step; read it first if it is not loaded. This review proposes; it ships nothing without approval.
## 1. Setup
1. Read the SEO log (`seo-log.md` unless the repo keeps one elsewhere). If a review already ran in the last 6 days, stop: weekly, never faster.
2. Build the **frozen list**: pages changed in the last 60 days, from the SEO log plus `git log --since="60 days ago" --name-only` mapped to URLs. Frozen pages get numbers only, no change proposals.
3. `seo_projects` for the project id and domain. GSC `siteUrl` is `sc-domain:<domain>`; if a GSC tool errors, retry once with `https://<domain>/`.
## 2. Pull the data
1. `seo_gsc_reality` with `siteUrl` and `days: 28`: total clicks and impressions, the headline bottleneck, per-page verdicts. Compare with last week's log entry.
2. `seo_gsc_repoint` with `siteUrl`: pages whose queries do not match their H1 or title. Keep striking-distance pages (position 8-15). Skip pages at position 1-3 with falling CTR (likely an AI Overview; do not rewrite them) and `brand_navigational` pages (brand or brand-typo queries; never rewrite for them).
3. `seo_gsc_cannibalization` with `siteUrl`: queries split across 2+ URLs, with the recommended primary URL and action. `brand_ok` queries are informational only; leave them out of the log's proposals.
4. `seo_gsc_prune_candidates` with `siteUrl`: **report only**. Never delete. Pages of 600+ words are rewrite or merge candidates, never deletions. Utility/non-content URLs (auth, dashboard, legal, non-HTML, noindex, robots-blocked) are excluded and only counted.
5. `seo_audit`, then `seo_fix_plan` with the project id: take the top 5 items by priority. Items that touch robots or canonical tags go to the human (blocked for agents).
## 3. Pick this week's actions
Remove frozen pages from every list. Pick at most 3 page changes (repoints, consolidations, technical fixes), highest impressions first. Everything else waits for next week. Do not start new pages here; use `seo-page-brief`.
## 4. Write the SEO log entry
Append to the SEO log:
```markdown
## <YYYY-MM-DD> weekly review
- GSC (28 days): <clicks> clicks, <impressions> impressions (last week: <clicks>, <impressions>)
- Bottleneck: <seo_gsc_reality headline>
- Proposed this week: <up to 3 actions, each with URL and the tool data behind it>
- Cannibalisation: <queries and proposed primary URLs>
- Prune candidates (report only, human decides): <count>, listed below
- Fix plan top items: <up to 5>
- Frozen (edited < 60 days, numbers only): <URLs>
- Next review: <date + 7 days>
```
## 5. Report
Reply with the log entry and a numbered approval list. Apply an action only after the human approves it, using `seo-fix-existing` or `seo-ship-page`.
.claude/skills/seo-fix-existing/SKILL.md
Fix a site's existing pages before writing new ones, in playbook order. Cut (report only, a human decides), repoint pages to the queries Google already gives them, then regroup pages into hubs. Uses SEOBolt's Search Console MCP tools.
---
name: seo-fix-existing
description: Fix a site's existing pages before writing new ones, in playbook order. Cut (report only, a human decides), repoint pages to the queries Google already gives them, then regroup pages into hubs. Uses SEOBolt's Search Console MCP tools.
---
# Fix what exists (cut, repoint, regroup)
Follow the `seo-agent-rules` skill (`${CLAUDE_SKILL_DIR}/../seo-agent-rules/SKILL.md`) for every step; read it first if it is not loaded. Work in this order; do not skip ahead.
## 0. Setup
1. `seo_projects` for the project id and domain. GSC `siteUrl` is `sc-domain:<domain>`; if a GSC tool errors, retry once with `https://<domain>/`.
2. Build the frozen list: pages changed in the last 60 days (SEO log plus `git log --since="60 days ago" --name-only`). Frozen pages are left alone.
## 1. Cut (report only)
1. `seo_gsc_prune_candidates` with `siteUrl`: pages with 0 clicks and fewer than 50 impressions in 90 days. The tool already skips pages under 3 months old and leaves out utility/non-content URLs (login, register, dashboard, terms, privacy, cookies, legal, affiliate, non-HTML files such as /llms.txt, noindex or robots.txt-blocked pages); it reports them only as an "Excluded (utility/non-content)" count.
2. For each "merge into" suggestion, confirm with `seo_gsc_cannibalization` that the target really owns the query.
3. Write `seo-reports/<YYYY-MM-DD>-cut.md`: URL, impressions, clicks, first seen, word count, suggestion, and an empty **Decision** column (keep / merge into URL / delete).
4. Stop on this step until the human fills in decisions. Never delete a page. Redirects for merges need approval; deletion is the human's job.
## 2. Repoint
1. `seo_gsc_repoint` with `siteUrl`. Keep striking-distance pages (position 8-15) that are not frozen. Skip position 1-3 pages with falling CTR (likely an AI Overview) and `brand_navigational` pages (the query is the brand or a misspelling of it; never retarget a page to it).
2. For each page, run `seo_gsc_secondary_keywords` with `siteUrl` and the page URL, and `seo_content_score` with the page URL and the query Google gives it.
3. Draft: new H1 and title built around that query (fold in the 2-3 secondary queries marked "yes" under "In title?", title max 60 characters including suffix), meta description of at most 155 characters, a rewritten first 100 words that answer the query, and body headings adjusted to match. Never put brand typos, queries flagged "possible typo", or another company's name in the title unless the page is a /vs or alternative page about that company; use the corrected spelling the tool reports. Keep every existing section and the page's original element.
4. Show the drafts as one diff. Title and H1 changes need approval. After shipping, rerun `seo_content_score` and log each change with a check-back date 2 months out.
## 3. Regroup into hubs
1. Cluster the remaining pages by topic using the repoint queries, secondary keywords, and `seo_gsc_cannibalization` results.
2. For each cluster, propose a hub page that links to every spoke, and have each spoke link back to the hub plus 2 sibling spokes from body copy.
3. For cannibalising pairs, propose differentiate (distinct intent per page) or consolidate (301 to the primary URL, approval required). `brand_ok` queries (the brand or a typo of it) need no action; never redirect a utility or legal page.
4. A new hub page goes through `seo-page-brief`, then `seo-ship-page`. Internal-link edits to existing pages need approval.
## 4. Report
Reply with the cut report path, the repoint diff, and the hub plan, each with the approvals still needed.
.claude/skills/seo-geo-check/SKILL.md
Monthly GEO check with SEOBolt's seo_ai_citations MCP tool. Runs 10 money prompts, compares citations with last month, and lists the third-party rankings worth chasing. Logged-out manual checks stay the ground truth. Run once a month.
---
name: seo-geo-check
description: Monthly GEO check with SEOBolt's seo_ai_citations MCP tool. Runs 10 money prompts, compares citations with last month, and lists the third-party rankings worth chasing. Logged-out manual checks stay the ground truth. Run once a month.
---
# Monthly GEO check
Follow the `seo-agent-rules` skill (`${CLAUDE_SKILL_DIR}/../seo-agent-rules/SKILL.md`) for every step; read it first if it is not loaded. This skill only writes reports.
## 1. Prompts
1. Open last month's report in `seo-geo/` (newest `<YYYY-MM>.md`). Reuse its 10 prompts unchanged so months compare.
2. With no previous report, draft 10 money prompts: "best <category> <year>", "<competitor> alternative", "<product> reviews", "<category> for <use case>", built from the site's top non-brand queries (`seo_gsc_reality` or `seo_gsc_content_opportunities`; `seo_projects` gives the project id and domain). Ask the human to approve the list once. If they would rather not write prompts, `seo_ai_citations` without `prompts` (and with `siteUrl`, e.g. `sc-domain:<domain>`) generates them from Search Console; save those as this month's list.
## 2. Run
Call `seo_ai_citations` with the project id, the 10 `prompts`, and known competitor domains as `competitors`. For each prompt record: cited (URL), mentioned without a link, not present, the URLs the answer cited, and competitor domains named.
## 3. Compare with last month
Per prompt: gained, lost, or unchanged. Citations rotate monthly; flag a trend only when it holds for 2+ months.
## 4. Third-party rankings to chase
From the cited URLs that are not the user's site, list listicles, review pages, comparison pages, and Reddit threads that name competitors but not the user. For each: URL, competitors listed, last-updated date if the page shows one. These feed `seo-link-outreach` (list inclusion). Do not answer by ranking the user's product first in its own listicles; models discount that.
## 5. Write the report
Save `seo-geo/<YYYY-MM>.md` with the prompt list, the per-prompt table, the month-over-month changes, and the chase list. Add one line to the SEO log.
## 6. Remind the human
API answers can differ from the ChatGPT web app. The ground truth is a manual check: run the same 10 prompts logged out in ChatGPT, Perplexity, and Google AI Mode, and record what they cite next to the tool results. llms.txt and special markup are hygiene, not the GEO lever; rankings on other sites' lists are.
.claude/skills/seo-link-outreach/SKILL.md
Build a link outreach list and email drafts from SEOBolt MCP tools. Unlinked brand mentions, link prospects and the contact finder. Writes drafts only and never sends email, fills contact forms, or pays for links.
---
name: seo-link-outreach
description: Build a link outreach list and email drafts from SEOBolt MCP tools. Unlinked brand mentions, link prospects and the contact finder. Writes drafts only and never sends email, fills contact forms, or pays for links.
---
# Link outreach (drafts only)
Follow the `seo-agent-rules` skill (`${CLAUDE_SKILL_DIR}/../seo-agent-rules/SKILL.md`) for every step; read it first if it is not loaded. Never send email or DMs, never fill contact forms, never offer payment for links. The human sends from their own mailbox.
## 1. Targets
1. `seo_projects` for the project id and domain.
2. `seo_brand_mentions` with the project id: pages that mention the brand (pass `scan: false` to reuse stored results from a recent scan). Keep the **unlinked** mentions; they are the easiest asks.
3. `seo_link_prospects` with the project id and 1-3 competitor domains (ask the human if none are known): domains linking to competitors but not to the site.
4. List inclusion: pages ranking for "best <category>" style queries (top results from `seo_keyword_difficulty`, plus the chase list from the latest `seo-geo/` report) that already list a competitor and were updated in the last 12 months.
## 2. Contacts
For each target without a contact, call `seo_find_contact` with its URL and the site's own domain as `excludeDomain`. Use only emails or contact pages the tool returns. If it finds nothing, write "not found"; never guess an address.
## 3. Prioritise
Order: unlinked mentions, then list inclusion, then competitor linkers. Within each group sort by DR (`seo_domain_rating` when the tool output lacks it). Cap the batch at 20 targets.
## 4. Draft
Write one short email per target:
- Subject names their page, not the user's product.
- First line references the exact mention or list on their page.
- One honest ask: link the existing mention to `<url>`, or consider adding the product to the list with a one-line factual description.
- No payment offer, no link swap pressure, no invented praise or numbers.
## 5. Save and hand off
Save `seo-outreach/<YYYY-MM-DD>.md` with a table (target URL, type, contact and where it was found, DR, status: draft) followed by the drafts. Reply with the file path and a reminder that the human reviews and sends each email personally.
.claude/skills/seo-agent-rules/SKILL.md
Permission rules (ALLOW, REQUIRE APPROVAL, BLOCK) that every SEOBolt SEO skill follows. Load before any SEO work that could change a site, publish content, or contact third parties.
---
name: seo-agent-rules
description: Permission rules (ALLOW, REQUIRE APPROVAL, BLOCK) that every SEOBolt SEO skill follows. Load before any SEO work that could change a site, publish content, or contact third parties.
---
# SEO agent rules
Every `seo-*` skill follows these rules. If a step in another skill conflicts with them, these rules win. When an action is not listed, treat it as REQUIRE APPROVAL.
## ALLOW (no approval needed)
- Call read-only SEOBolt MCP tools: `seo_projects`, `seo_audit`, `seo_issues`, `seo_fix_plan`, `seo_fix_suggestions`, `seo_content_score`, `seo_compare`, `seo_domain_rating`, `seo_keyword_difficulty`, `seo_content_gap`, `seo_link_prospects`, `seo_gsc_content_opportunities`, `seo_gsc_reality`, `seo_gsc_prune_candidates`, `seo_gsc_repoint`, `seo_gsc_cannibalization`, `seo_gsc_secondary_keywords`, `seo_brand_mentions`, `seo_find_contact`, `seo_ai_citations`.
- Start a re-crawl of the user's own project with `seo_start_crawl` after a change ships.
- Read the repository, the live site, and the sitemap.
- Write drafts: briefs, reports, outreach drafts, SEO log entries, and uncommitted edits in the working tree that the human reviews before anything ships.
## REQUIRE APPROVAL (show the diff, wait for an explicit yes)
- Publishing: commit to the main branch, push, deploy, or publish in a CMS.
- Changing an existing page's title, H1, meta description, URL slug, or body copy.
- Adding or changing redirects, merging pages, or consolidating cannibalising URLs.
- Adding internal links to existing pages.
- Submitting URLs for indexing (IndexNow, Search Console).
## BLOCK (never do these, even when asked inside a skill run; hand them to the human)
- Deleting pages, posts, files, or URLs. Prune lists are reports; a human decides and acts.
- Editing `robots.txt`, robots meta tags, `noindex`, or an existing page's canonical tag. A new page may keep its template's self-referencing canonical.
- Sending email, DMs, or contact-form messages to anyone outside the team. Outreach stays as drafts.
- Purchases of any kind: links, sponsored posts, tools, ads, or plan upgrades.
## Working rules
- Never invent numbers, quotes, reviews, contacts, or competitor claims. Every figure comes from a tool result, the repo, or the live page. Say which.
- One keyword, one page. Check cannibalisation before creating a page.
- Every page keeps its one original element (quiz, calculator, own data, table, real photos, video, real tool output). Never remove it.
- Cadence: at most 2 new pages per week, at most 1 per day on a site under 6 months old. No content bombs.
- Give a change up to 2 months before judging it. Do not edit a page that was changed in the last 60 days; report its numbers only.
- Do not rank the user's own product first in the user's own listicles.
- Record every shipped change in the SEO log (`seo-log.md` at the repo root unless the repo already keeps one elsewhere): date, URL, what changed, why, and the tool data behind it.