site-redesign — Coverage-First Redesign Pipeline
Given an existing site URL with explicit redesign intent, runs 9 ordered phases that produce a strategic brief for Claude Design plus four supporting analysis files.
Core principle: Render → verify coverage → infer. Never infer purpose from an empty shell.
Output structure
docs/sites/{site-slug}/redesign/
├── INDEX.md ← summary, assumptions, coverage manifest, how-to-use
├── brief.md ← paste-ready Claude Design onboarding brief (headline deliverable)
├── run-sheet.md ← sequential canvas prompts (validate → key screen → remaining)
├── content-inventory.md ← evaluative audit (keep/revise/consolidate/remove + ROT flags)
├── ia-map.md ← nav hierarchy, per-page intent triplets, journeys, conversion path
├── current-critique.md ← severity-rated findings vs category best-practice + screenshots
└── .crawl/ ← raw per-page markdown + screenshots (git-ignored)
Slug: canonical rule — see docs/SLUG_RULES.md.
Session brief
Running markdown doc in context. Append after each phase; never overwrite. Sections: Tool Availability ([AVAILABLE]/[TOOL-UNAVAILABLE:{name}] per tool + [CHROME-NAMESPACE:plugin|project]), Structure (URL/cluster count, signals), Coverage Manifest, Category Detection ([PACK-LOADED:{name}]), Intent, Phase Markers ([P1✓]–[P9✓]).
The 9 phases — always in this order
| # | Phase | Writes |
|---|---|---|
| 1 | Scaffold + tool check | — |
| 2 | Structure discovery | ia-map.md (skeleton) |
| 3 | Render + coverage gate | session brief |
| 4 | Content crawl + screenshots | .crawl/ |
| 5 | Content audit | content-inventory.md |
| 6 | IA / journey map | ia-map.md |
| 7 | Intent inference + category detect (+ strategic question) | session brief |
| 8 | Current-design critique | current-critique.md |
| 9 | Synthesize | brief.md, run-sheet.md, INDEX.md |
Ordering note (the one allowed flex): the strategic question (P7 step 4) may be asked any time after Phase 4 (crawl) and must be asked before writing the deliverable files (P5/P6/P8) — its answer reframes them. Category detection (P7 step 2) is never skipped or deferred: it must run and emit
[PACK-LOADED:<cat>]before Phase 8's pack-cited critique. Asking the question early does NOT license skipping detection.
Phase 1 — Scaffold and tool check
Input: URL (with explicit redesign intent).
Actions:
- Derive slug (mirrors the canonical rule in
docs/SLUG_RULES.md— that doc is authoritative; keep this one-liner in sync with it):SLUG=$(printf '%s' "$URL" | tr 'A-Z' 'a-z' | sed -E 's#^https?://##; s/^www\.//; s#/.*$##; s/:[0-9]+$//; s/\./-/g'). Examples:www.example.com/→example-com,Example.COM→example-com. - Create output folder + empty output files (Write, not touch — create each file with the Write tool, never
touch/Bash heredoc/>-redirect. Bash-created files are untracked by the harness and force a redundant Read before every later Write (observed cost: 6 wasted Reads in a prior run)):INDEX.md,brief.md,run-sheet.md,content-inventory.md,ia-map.md,current-critique.md— all underdocs/sites/{slug}/redesign/. - Write
docs/sites/{slug}/redesign/.gitignorecontaining.crawl/. - Detect tools — log each as
[AVAILABLE]or[TOOL-UNAVAILABLE:{name}]. Seereferences/tool-availability.md(Jina Reader, Firecrawl, Crawl4AI, WebFetch, Chrome DevTools MCP — test both namespaces; record active one as[CHROME-NAMESPACE:plugin|project]). - Check for prior beacon recon: if
docs/sites/{slug}/research/(or legacydocs/research/{slug}/) exists, log[RECON-REUSE]and read every file in it (not justsite-map.md/tech-stack.md— includeosint.md,INDEX.md, anyclaude-design-inputs/competitive/performance files). The recon corpus becomes a content source for Phases 3–5; still live-re-verify the homepage (render gate) and spot-check 1–2 key routes. Never treat recon as a substitute for the render gate.
Output: Session brief initialized with tool availability block. Phase marker [P1✓].
Phase 2 — Structure discovery
Input: Site URL, session brief.
Actions:
- Fetch
robots.txt— parse forSitemap:directives. - Fetch
sitemap.xml(follow sitemap-index children to enumerate leaf URLs). - If no sitemap: parse homepage
<nav>and<a href>links. - Enumerate ALL discovered URLs.
- Cluster by path template (e.g.
/,/blog/*,/services/*,/about,/contact, legal) and any recurring prefixes. - Write the URL list + cluster map to
ia-map.mdas a skeleton.
Signals to emit:
[NO-SITEMAP]— nositemap.xmland noSitemap:inrobots.txt; nav-crawl used.[SINGLE-PAGE]— ≤2 enumerated URLs; section-anchor map replaces page table in Phase 6.[MULTI-LOCALE:canonical=x]—hreflangalternates or locale paths (/en,de.) detected; brief ONLY the canonical localex.
Output: ia-map.md (skeleton), URL count + cluster table in session brief. Phase marker [P2✓].
Phase 3 — Render gate and coverage gate
Input: Site URL, session brief. Load skills/site-redesign/references/crawl-and-coverage.md.
Actions:
- Fetch homepage (WebFetch; WAF fallback: Firecrawl → Jina → browser-fetch if 403).
- Render gate + content-sufficiency gate: Run
python3 ${CLAUDE_PLUGIN_ROOT}/skills/site-redesign/scripts/coverage-metrics.py <fetched-markdown-file>(or--stdin). Readbody_text_chars,nav_link_count,unique_headings,non_nav_prose_words, andsignalsfrom the JSON output. Fallback if python3 or the script is unavailable: estimate the four metrics by inspection against the same thresholds below.[RENDER-ESCALATED]—body_text_chars < 200ORnav_link_count == 0→ re-fetch via Jina → Firecrawl → Crawl4AI (Chrome MCP: auth/interactive walls only).[GREENFIELD-MODE]— after render:unique_headings < 2ANDnon_nav_prose_words < 150→ writeINDEX.mdwith{{PHASE_MARKERS}}set to[GREENFIELD-MODE]and{{SIGNALS_FIRED}}set to[GREENFIELD-MODE](so no token is left unresolved and the gate detects the halt correctly), delete the five unfilled output files (every Phase-1 file exceptINDEX.md), halt pipeline.
- Coverage manifest: each URL → Reachable (200) or Gated/Blocked (401/403/challenge). Emit
[COVERAGE-PARTIAL:gated]if any URL gated.- Per-route render check: for each sampled route, record whether it renders real content or only an app shell (a client-side 404 returns a 200 shell). Flag shell-only routes as findings. See
references/crawl-and-coverage.md→ "Per-route render check".
- Per-route render check: for each sampled route, record whether it renders real content or only an app shell (a client-side 404 returns a 200 shell). Flag shell-only routes as findings. See
- Emit
[WAF-BLOCKED]only if all three fallback fetchers fail; do not hard-stop.
Output: Coverage manifest in session brief. Phase marker [P3✓].
Phase 4 — Content crawl and screenshots
Input: URL cluster map from Phase 2, session brief. Load skills/site-redesign/references/crawl-and-coverage.md.
Actions:
- Sample 1–2 pages per template cluster; floor = homepage + primary nav targets.
- Apply a 60,000-character clean-markdown budget — stop when exhausted.
- Log
[SAMPLED:n-templates]wheren= clusters actually sampled. - Save per-page markdown to
.crawl/{slug-path}.md. - Take one screenshot per sampled template (Jina pageshot → Firecrawl → Crawl4AI → Chrome MCP → local Playwright fallback; sequences in references/crawl-and-coverage.md).
- Homepage: two screenshots (above-fold and full-page).
- No screenshot source available: log
[TOOL-UNAVAILABLE:chrome-mcp]; text-only; visual-gap note in all output files.
- Save screenshots to
.crawl/screenshots/. - Sample brand colours (best-effort): extract the dominant brand hex values from the homepage — grep the page CSS/inline styles for
#rrggbb/rgb()on the logo/header/primary-CTA, or sample the homepage screenshot. Record the measured values for the §7 seed's KEEP palette. If unsampleable, mark the seed palette "(approximate — sample on capture)" so it is not presented as measured.
Output: .crawl/ populated. Phase marker [P4✓].
Phase 5 — Content audit
Input: .crawl/ page markdown files, session brief.
Actions:
For each crawled page, record:
- URL, template cluster, page type (homepage / service / about / blog-post / contact / legal / …)
- Purpose — what the page is trying to accomplish
- Value props, CTAs, forms, media present
- Verdict:
keep/revise/consolidate/remove— each verdict tied to the inferred primary goal - ROT flags: redundant (same job as another page), outdated (dated claims/events), trivial (thin/low-value), orphan (no inbound nav link), off-message (content misaligned with purpose)
Write rows to content-inventory.md using the template in templates/content-inventory.md.template.
Output: content-inventory.md written. Phase marker [P5✓].
Phase 6 — IA and journey map
Input: content-inventory.md, session brief.
Actions:
- Build the navigation hierarchy — top-nav items, any sub-nav, footer links.
- Build the page-purpose table — one row per page with its intent triplet (
concrete subject · target audience · page's single job). Format as defined inreferences/brief-format.md. For[SINGLE-PAGE]sites, use section-anchor map instead. - Define 1 primary + 2–3 secondary journeys keyed to entry intent. Each journey step names the decisive objection it must resolve.
- Trace the primary conversion path — the exact sequence of steps from cold visit to the primary goal, naming each page/step.
Write to ia-map.md using templates/ia-map.md.template (replacing the skeleton from Phase 2).
Output: ia-map.md completed. Phase marker [P6✓].
Phase 7 — Intent inference and category detection
Input: All crawled content, ia-map.md, content-inventory.md, session brief.
Actions:
- Infer: purpose, audience, primary goal — with per-field confidence (high / medium / low).
- Detect category: Run
python3 ${CLAUDE_PLUGIN_ROOT}/skills/site-redesign/scripts/detect-category.py --categories ${CLAUDE_PLUGIN_ROOT}/categories --corpus <.crawl-dir-or-file>. Readwinnerfrom JSON; loadcategories/{winner}.md. Fallback if the script is unavailable: score each pack'sdetect_signalsagainst the corpus by inspection and pick the dominant; ties and zero-match →generic.- If the top-scoring category's confidence is low, load
categories/generic.mdand note the assumption explicitly in the brief. - If a site scores across multiple categories, pick the single dominant pack, note secondaries inline (e.g. "primarily ecommerce; secondary: local-service"). Never merge packs.
- If the top-scoring category's confidence is low, load
- Emit
[PACK-LOADED:{winner}]once the pack is selected. - Ask the one question (may be asked any time after Phase 4; MUST precede writing
content-inventory.md/ia-map.md/current-critique.md): "Redesigning for the same purpose or a new one?" — record ascurrent purpose (inferred)vstarget purpose (declared). Only human question in the pipeline. Asking this early does not permit skipping steps 1–3 above — category detection and[PACK-LOADED:<cat>]are mandatory and gate-enforced (see Phase 9). - Record all inferences (purpose, audience, goal, category, confidence) in the session brief.
Output: Session brief updated with intent block. Phase marker [P7✓].
Phase 8 — Current-design critique
Input: Category pack loaded in Phase 7, .crawl/screenshots/, ia-map.md, content-inventory.md, session brief.
Actions:
- Load
categories/{detected}.md(already loaded in Phase 7; re-read if needed). - For each finding (visual, IA, content, voice, SEO/a11y), record:
- Finding — specific observation, referenced to a page or screenshot
- Severity — 0 (note) / 1 (minor) / 2 (moderate) / 3 (major) / 4 (critical)
- Best-practice violated — cite the named principle from the category pack
- Concrete fix — one actionable sentence; no design theory
- Evidence — screenshot filename or quoted text excerpt
[INFER-GUARD]: do NOT record a "section empty / content missing / link broken" finding unless it is verified against a JS render or raw HTML — not markdown alone (markdown crawlers drop JS-revealed content). Seereferences/crawl-and-coverage.md→ "Render fidelity".
- Voice/messaging pass — flag vague adjectives ("innovative", "world-class"); identify three vaguest claims, propose replacements.
- SEO/a11y pass — heading structure, metadata completeness, schema/NAP presence, alt-text coverage.
- Write
current-critique.mdusingtemplates/current-critique.md.template.
If [TOOL-UNAVAILABLE:chrome-mcp]: no screenshots — add [VISUAL-GAP: visual-hierarchy critique not possible without screenshots] to current-critique.md.
Output: current-critique.md written. Phase marker [P8✓].
Phase 9 — Synthesize
Input: All prior phase outputs and the session brief. Load references/brief-format.md.
Actions:
Resolve all 38
{{TOKEN}}s (listed below) from the session brief and phase outputs.Write
brief.mdviatemplates/brief.md.template. Section order is a contract — do not reorder; seereferences/brief-format.mdfor the full contract including the per-page intent triplet format and design-system seed block format.- §9 web-capture instruction must include verbatim: "Capture the live URL for content, structure, and brand assets to KEEP (logo, brand color, product photography) only. The design direction above OVERRIDES all captured visual styling."
Write
run-sheet.mdviatemplates/run-sheet.md.template. Order: validate → key screen → remaining screens (severity order, not nav order) → components.Finalize
content-inventory.md,ia-map.md,current-critique.md(written in phases 5/6/8; resolve any remaining tokens).- If
[RECON-REUSE]fired:{{SAMPLING_NOTE}}must state plainly that the audit reused a prior beacon recon and live-re-verified only the homepage + key routes (e.g. "re-verified recon synthesis, not a fresh crawl of all N URLs");{{AUDITED_COUNT}}counts only pages actually (re-)read this run. Do not imply a full fresh crawl.
- If
Write
INDEX.mdviatemplates/INDEX.md.template. Populate{{PHASE_MARKERS}}with the emitted markers (or[GREENFIELD-MODE]): list each one explicitly —[P1✓] [P2✓] [P3✓] [P4✓] [P5✓] [P6✓] [P7✓] [P8✓] [P9✓]— a literal range/ellipsis like[P1✓]–[P9✓]will fail the gate's per-marker check. Populate{{SIGNALS_FIRED}}with every degradation signal that fired this run, including the[PACK-LOADED:<cat>]from Phase 7.Resolve
{{TECH_EXPORT_HANDOFF}}: readdocs/sites/{slug}/research/tech-stack.md; if absent, readdocs/research/{slug}/tech-stack.md(legacy); if neither exists, log[TECH-STACK-ABSENT]and add tobrief.md§10: "No beacon tech-stack found — specify the target stack manually, or run beacon first".Completeness check: Run
bash ${CLAUDE_PLUGIN_ROOT}/skills/site-redesign/scripts/check-output-complete.sh docs/sites/{slug}/redesign. A non-zero exit means the run is not complete — resolve the named files/tokens and re-run. Fallback if unavailable: grep each output file for{{manually; no{{remaining = complete run. The gate now also fails ifINDEX.mdis missing any phase marker or the[PACK-LOADED:<cat>]token; resolve by recording the genuine run log (do not fabricate markers for phases you skipped — run them).
Output: All six output files written. Phase marker [P9✓].
Phase-9 token contract
Phase 9 MUST resolve every one of these 38 tokens — the deduplicated union across all six templates. Do not add or rename tokens.
{{SITE_NAME}} {{DATE}} {{URL}} {{CATEGORY}} {{CATEGORY_CONFIDENCE}} {{INFERRED_PURPOSE}} {{TARGET_PURPOSE}} {{AUDIENCE}} {{PRIMARY_GOAL}} {{COVERAGE_MANIFEST}} {{ASSUMPTIONS}} {{WHAT_IT_IS}} {{GOALS_SUCCESS}} {{KEEP_CHANGE_ADD}} {{IA_PROPOSED}} {{DESIGN_DIRECTION_SEED}} {{REFERENCES_ANTI}} {{WEB_CAPTURE_OVERRIDE}} {{TECH_EXPORT_HANDOFF}} {{VALIDATE_PROMPT}} {{KEY_SCREEN_PROMPT}} {{REMAINING_SCREEN_PROMPTS}} {{COMPONENT_PROMPTS}} {{URL_COUNT}} {{AUDITED_COUNT}} {{SAMPLING_NOTE}} {{INVENTORY_ROWS}} {{UNAUDITED_LIST}} {{NAV_HIERARCHY}} {{PAGE_PURPOSE_TABLE}} {{JOURNEYS}} {{PRIMARY_CONVERSION_PATH}} {{VISUAL_TRACK_NOTE}} {{CRITIQUE_ROWS}} {{VOICE_FINDINGS}} {{SEO_A11Y_FINDINGS}} {{PHASE_MARKERS}} {{SIGNALS_FIRED}}
Graceful degradation signals
Log these in the session brief. Surface any that fired in INDEX.md.
| Signal | Meaning |
|---|---|
[RENDER-ESCALATED] |
Homepage < 200 chars or 0 nav links; re-fetched via Jina → Firecrawl → Crawl4AI; Chrome MCP only if all crawlers unavailable or auth-gated |
[GREENFIELD-MODE] |
After render: < 2 unique headings and < 150 non-nav words; pipeline halted — not a redesign target |
[NO-SITEMAP] |
No sitemap.xml and no Sitemap: in robots.txt; fell back to homepage-nav crawl |
[COVERAGE-PARTIAL:gated] |
One or more URLs returned 401/403/challenge; only public pages briefed |
[WAF-BLOCKED] |
Homepage blocked by Firecrawl, Jina, AND browser-fetch; proceeded with partial content |
[SAMPLED:n-templates] |
Crawl budget exhausted; n template clusters sampled, not all |
[SINGLE-PAGE] |
≤2 URLs discovered; section-anchor map used instead of page table |
[MULTI-LOCALE:canonical=x] |
Locale branching detected; briefed canonical locale x only |
[TOOL-UNAVAILABLE:chrome-mcp] |
No screenshot source available (Jina/Firecrawl/Crawl4AI/Chrome MCP all unavailable); text-only output; visual gap noted |
[PACK-LOADED:x] |
Category pack x loaded for Phase 8 critique and design-system seed |
[TECH-STACK-ABSENT] |
No beacon tech-stack found at new or legacy path; §10 note added — specify stack manually or run beacon first |
[RECON-REUSE] |
A prior beacon recon exists at docs/sites/{slug}/research/ (or legacy docs/research/{slug}/); its files were read as a content source and the homepage live-re-verified. Provenance recorded in {{SAMPLING_NOTE}}. |
Reference files
Load on demand:
references/tool-availability.md— detection commands; crawl preference order; WAF escalation chainreferences/crawl-and-coverage.md— render-gate thresholds; screenshot sequences; coverage manifest; crawl budgetreferences/brief-format.md—brief.mdsection order; intent triplet format; seed block format; run-sheet orderingcategories/{detected}.md— matched category pack;categories/generic.mdis the low-confidence fallbacktemplates/— the six*.templatefiles resolved in Phase 9
Path note:
categories/andtemplates/are at the plugin root (plugins/reframe/).references/is inplugins/reframe/skills/site-redesign/references/.