Sitemap audit
Collection of Claude Code and Claude Desktop skills for developer workflows, automation, and productivity
npx -y skills add mostafa-drz/claude-skills --skill sitemap-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Audits a website's SEO discoverability by cross-referencing the codebase with live production. Catches sitemap, robots.txt, and canonical inconsistencies, framework-specific anti-patterns (Next.js App Router metadata cascade, Astro/Nuxt equivalents), redirect-chain issues, and Google Search Console stuck states. Produces a prioritized, evidence-backed report with suggested fixes. Use when Search Console shows "Couldn't fetch", pages aren't being indexed, or you want an SEO health check before a launch or after a routing refactor.
SKILL.md
13.0 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
sitemap-audit
Diagnostic SEO audit. Report only — never modifies code or Search Console state. Cross-references the codebase with live production to catch issues that live-only tools miss (like framework metadata cascade bugs).
Preferences
Read ~/.claude/skills/sitemap-audit/preferences.md using the Read tool. If not found, proceed with onboarding.
Context
On startup, use Bash to detect (skip any that fail):
- Current repo path:
pwd - Framework fingerprint:
package.json(Next.js / Astro / Nuxt / SvelteKit / generic),astro.config.*,nuxt.config.* - Has
src/app/(App Router) orpages/(Pages Router) - Git state:
git status,git log -1 --format=%h
Command Routing
Check $ARGUMENTS for subcommands:
help
Display:
sitemap-audit — SEO health check across codebase + live production
Usage:
/sitemap-audit Audit site from preferences
/sitemap-audit <url> Audit a specific URL (one-off)
/sitemap-audit config Set preferences
/sitemap-audit reset Clear preferences
/sitemap-audit help This help
What it checks:
1. Sitemap fetchability + XML validity + URL count
2. robots.txt content + sitemap pointer consistency
3. Every URL in sitemap: 200 status, self-canonical match
4. Response headers: Content-Type, X-Robots-Tag, HSTS
5. Apex ↔ www redirect chain depth + consistency
6. Codebase anti-patterns (framework-specific)
7. SSR vs JS-only rendering (Googlebot compatibility)
8. DNS: site verification TXT records for GSC
9. (Optional, with permission) Live GSC check via Chrome extension
Output: prioritized report (P0 blocks indexing / P1 hurts rankings / P2 nice-to-have).
Current preferences: [read from preferences.md or "none — will onboard"]
Then stop.
config
Use AskUserQuestion to collect:
Q1 — "Production URL to audit? (e.g. https://www.example.com)"
- Free text.
Q2 — "Repo path for codebase-aware checks?"
- Options: "Current directory (
pwd)", "Specify path", "Skip codebase checks"
Q3 — "Do you have a Google Search Console property you want the skill to explore? (optional, requires Claude for Chrome extension)"
- Options: "Yes, and I'll grant browser access when asked", "No / skip GSC check", "Later — remind me in each run"
Q4 — "Save report to a file after each run?"
- Options: "No — just print to chat", "Yes —
.sitemap-audit/report-<date>.mdin repo", "Yes — custom path"
Save to ~/.claude/skills/sitemap-audit/preferences.md. Summary. Stop.
reset
Delete ~/.claude/skills/sitemap-audit/preferences.md. Confirm: Preferences cleared. Stop.
First-time experience (no preferences, no subcommand)
Show one-line invitation (don't block):
First time running /sitemap-audit? Run `/sitemap-audit config` for persistent setup,
or answer a couple of one-off questions to continue.
Then ask (via AskUserQuestion or inline) ONLY: production URL (required), codebase path (default: cwd). Skip GSC on first run.
Default — run the audit
Continue to Audit steps below.
Audit steps
Execute these in order. Run independent curls in parallel. Every finding must cite evidence (exact curl output, file:line, or DNS record).
1. Fetch baseline (live production)
Record HTTP status + final URL + Content-Type + first hop for each:
curl -sI <url>/
curl -sI <url>/sitemap.xml
curl -sI <url>/robots.txt
curl -sI <url-apex>/ # if www is canonical, or vice versa
curl -sIL <url-apex>/sitemap.xml # follow to detect redirect chain depth
Flag P0 if:
- Sitemap returns non-200
- Sitemap Content-Type is not
application/xmlortext/xml - robots.txt returns non-200
- Redirect chain depth > 1 (multiple hops slow Googlebot)
2. Validate sitemap XML
curl -s <sitemap-url> | xmllint --noout - # VALID or error
curl -s <sitemap-url> | grep -c "<loc>" # URL count
Flag P0 if XML invalid. Flag P1 if URL count is 0 or exceeds 50,000 (sitemap split needed).
3. Audit every URL in sitemap
For each <loc>:
- HEAD request — expect 200
- GET + extract
<link rel="canonical"> - Compare canonical to the URL itself (self-canonical)
Count: correct canonical (matches own URL), no canonical (Google self-canonicals by default, acceptable), WRONG canonical (points elsewhere — P0).
Classify wrong canonicals by where they point:
- All → same root URL? → framework cascade bug (e.g., Next.js root layout
alternates.canonicalleaking) - Inconsistent wrong targets? → per-page hardcoding issue
4. Headers audit
On homepage + sitemap + a sample article:
X-Robots-Tag— anynoindexhere silently de-indexes the URL. P0 if found unexpectedly.Strict-Transport-Security— presence is good.Content-Type—text/html; charset=utf-8expected for pages.
5. Canonical / host consistency
If site has both apex and www:
- Which one is canonical? (check
<link rel="canonical">on homepage) - Does DNS/redirect match the canonical? Both should agree.
- Does the sitemap use the canonical host? (Sitemap URLs mismatching canonical host → Google treats sitemap URLs as non-canonical alternates.)
- Does robots.txt's
Sitemap:pointer use the canonical host?
Common P0 pattern: sitemap + robots canonicalize one host, but page-level <link rel="canonical"> points to the other. Seen in Next.js sites that fix sitemap/robots but forget metadataBase or hardcoded URLs in layouts.
6. Codebase anti-pattern scan
Only if codebase path is set. Detect framework from package.json, run framework-specific checks.
Next.js App Router (15+)
Read these files:
next.config.*,next.config.tssrc/app/layout.tsx(root) — scan formetadata.alternates.canonicalsrc/app/sitemap.ts— checkbaseUrlconsistency with production canonical hostsrc/app/robots.ts— checksitemap:pointer matchessrc/lib/metadata.tsor similar — grep for hardcoded URLs:grep -rn "https?://<apex-domain>" src/
Anti-patterns to flag:
- P0 — Root canonical cascade:
alternates.canonicalset insrc/app/layout.tsxcascades to every child route that doesn't override. Result: every page claims to be the homepage. Fix: remove root canonical; let pages self-canonical or add explicit per-route. - P0 — Host mismatch:
siteUrlinsrc/lib/metadata.tsis apex but sitemap/robots/redirect canonicalize to www (or vice versa). Grep:grep -rn "https://<apex>" src/ --include="*.ts" --include="*.tsx". - P1 — Missing
metadataBase: root layout has nometadataBase, so relative URLs in metadata won't resolve. - P1 — Dynamic sitemap using filesystem at runtime:
readdirSync(join(process.cwd(),...))insitemap.tscan fail in serverless if files not bundled. Prefer compile-time aggregation. - P2 —
lastModifiedomitted: sitemap entries withoutlastModifiedgive Google no crawl-priority signal.
Next.js Pages Router
- Check
pages/sitemap.xml.tsor similar; flag if missing. - Check
<Head>in_document.js/_app.jsfor canonical setup. - Flag P1 if canonical is set in
_document(applies site-wide, same cascade trap).
Astro
- Check
astro.config.mjsforsite(required for canonical URLs). - Check
@astrojs/sitemapintegration — flag P1 if site has >20 pages and no sitemap integration. - Check
<BaseHead>or layout for canonical.
Nuxt
- Check
nuxt.config.ts→siteor@nuxtjs/sitemapmodule. - Check
useHeadcanonical usage.
SvelteKit
- Check
svelte.config.js→kit.prerender. - Check
+layout.svelte<svelte:head>for canonical.
Generic / unknown framework
- Grep for
<link rel="canonical"patterns in source. - Skip framework-specific checks, report "framework not auto-detected".
7. SSR / rendering check
curl -s <url>/ | grep -oE "<h1|<article|<main" | head -5
curl -s <url>/ | grep -c "<meta\|<link"
Flag P0 if the HTML response is essentially empty (client-rendered SPA). Googlebot renders JS but delays indexing.
8. DNS / verification check
dig +short <apex-domain> A
dig +short <apex-domain> TXT
dig +short www.<apex-domain> CNAME
Flag:
- P2 (info) — presence of
google-site-verification=...TXT. If present, Domain property is set up in GSC (ideal). - P1 — apex has no A record but www does (or vice versa) — bots that pick the "wrong" host will fail.
- P2 — multiple google-site-verification TXT (usually harmless but worth flagging).
9. Optional — Google Search Console live check
Only if user granted permission in preferences or this run.
Using the Claude for Chrome extension (mcp__claude-in-chrome__*):
- Navigate to
https://search.google.com/search-console/sitemaps?resource_id=sc-domain%3A<domain>(or?resource_id=<encoded-url>for URL-prefix properties) - Use
get_page_textto read the sitemaps table - Report: property type, submitted sitemaps, status, last read date, discovered pages count
Do NOT modify GSC state (no remove/resubmit). Read-only.
If any sitemap shows "Couldn't fetch" and production verifies healthy → flag as P1 with explicit user action: "remove + resubmit sitemap in GSC (use trailing slash trick to cache-bust if removal alone doesn't clear it)."
10. Build the report
Format:
╔═══════════════════════════════════════════════════════════════╗
║ sitemap-audit — <domain> ║
║ <date> · <framework> · <N urls> in sitemap ║
╚═══════════════════════════════════════════════════════════════╝
SUMMARY
P0 (blocks indexing): <n>
P1 (hurts rankings): <n>
P2 (nice-to-have): <n>
P0 — Blocks indexing
• <finding>
Evidence: <file:line or curl output>
Fix: <specific action>
P1 — Hurts rankings
• ...
P2 — Nice-to-have
• ...
CLEAN PASSES
✓ Sitemap XML valid
✓ All <N> URLs return 200
✓ robots.txt consistent
...
NEXT ACTIONS (prioritized)
1. [P0] <most important fix>
2. [P0] <next>
3. [P1] <next>
GSC ACTIONS (manual — skill does not modify GSC)
• <specific click path if applicable>
11. Offer follow-up
After displaying the report, ask:
Want me to open a fix PR for P0/P1 findings? This would modify code only — never GSC. You'll review the PR before merge.
If yes:
- Create branch
fix/seo-sitemap-audit-<date> - Apply per-framework fixes (e.g., remove Next.js root canonical, fix host mismatch)
- Include detailed commit message citing evidence
- Open PR with before/after expected canonical count
- Do not merge — hand back for review.
If no: done.
If preferences.md has saveReport: true: write the report to the configured path.
Memory and preferences
Save to ~/.claude/skills/sitemap-audit/preferences.md:
# /sitemap-audit preferences
Updated: <date>
## Defaults
- url: https://www.example.com
- repoPath: /Users/x/Dev/myproject
- gscMode: ask-per-run | always-skip | always-run
- saveReport: false | path
- framework: nextjs-app | nextjs-pages | astro | nuxt | sveltekit | generic
Learn silently:
- User corrects detected framework → save.
- User always skips GSC → switch to
always-skip. - User always requests PR at the end → save as default.
Content guidelines
- Every finding needs evidence (curl output, file:line, or DNS record). No vibes-based claims.
- Use three tiers: P0 / P1 / P2. Don't invent more.
- Cite the Next.js version when reporting framework-specific issues (read from package.json).
- When a finding is framework-specific, name the pattern (e.g., "Next.js App Router root layout canonical cascade").
- If a check can't run (tool unavailable, permission denied), note it in the report, don't silently skip.
Limits
- Does not fix Google Search Console state (GSC is shared; user must click).
- Does not modify production directly (only via a PR for review).
- Does not require API keys (everything is curl + read-only DOM).
- Will not auto-submit sitemaps or request indexing — GSC quotas and user intent.