seo-crawl-render
seo-crawl-render
Produces the PageSnapshot (v2) consumed by every module. The scripts fetch, parse, render, and persist; this skill decides which command to run and reads only its compact stdout summary. Claude Code's WebFetch returns a lossy model summary with no headers, status codes, or raw HTML and does not follow cross-host redirects — it is never the acquisition path.
Acquisition
- Single page or local path:
node "${CLAUDE_PLUGIN_ROOT}/scripts/snapshot.mjs" <url|path> --out "${CLAUDE_PLUGIN_DATA}/runs" [--render auto|static|js] [--ua default|googlebot|bingbot|gptbot|oai-searchbot|claude-searchbot] [--renderer auto|chrome|playwright|none] [--rendered-file <dom.html>] [--max-bytes 5000000] [--json]— a non-default--uawritespages/<slug>.ua-<preset>.json. - Multi-page:
node "${CLAUDE_PLUGIN_ROOT}/scripts/crawl.mjs" <url> [--pages 12] [--max 40] [--per-template 2] [--depth 3] --out "${CLAUDE_PLUGIN_DATA}/runs"— homepage + target always, then at most--per-templatepages per detected template, robots respected; every skip is logged incrawl.json.sampling. Also takes--concurrency,--delay,--include/--exclude,--seeds,--sitemap-sample,--link-statusand--no-robots. - Read the stdout summary only (run dir, slugs, counts, render verdict, warnings). Never paste HTML into the conversation — modules
Readpages/<slug>.jsonandGreppages/<slug>.html. - Local directories are read as built HTML (
status: null, empty headers). Framework source with no built output exits 2: build first or give the deployed URL.
Render decision (lives in the script)
--render auto marks a render as needed on word count <150, hydration markers (__NEXT_DATA__, __NUXT_DATA__, self.__next_f, empty #app/#__next root) on a still-thin page, no h1 with <3 anchors, or a <noscript> JS notice. --render static never renders; --render js always tries. The default differs by entry point: snapshot.mjs defaults to auto, while crawl.mjs and audit.mjs default to static — a headless or multi-page run never launches a browser unless it is asked to.
--renderer auto(the default) auto-detects headless Chrome/Chromium/Edge/Brave ($CLAUDE_SEO_AI_CHROME→$CHROME_PATH→$PUPPETEER_EXECUTABLE_PATH→ PATH → default app paths → Playwright caches);--renderer playwrightis opt-in and used only when already installed — never auto-installed;--renderer nonedisables rendering entirely;--rendered-file <html>accepts a DOM captured by a Playwright/Firecrawl MCP or by the user.- When
render.needed && render.used === "none": the snapshot carriesconfidence: reducedandrender.hint; emitM4.render.not_renderedasneeds_api(severity 3, axisboth,fixable: advisory) quoting the hint ("install Chrome, or pass--rendered-filefrom a render MCP"). Never pretend to have seen rendered content.