component-mapping-kit

Workflow — from a URL to four deliverables

This is the end-to-end methodology. Read it once so you understand what the scripts are doing, then drive the real work through the four slash-command skills (/start-analysis, /analyze-page, /map-to-eds, /capture-eds).

Mental model

The kit is a three-phase pipeline that produces four deliverables:

Legacy URL    Phase 1: Site inventory      Phase 2: Mapping rules    Phase 3: EDS authoring
─────────     ───────────────────────      ──────────────────────    ──────────────────────
https://...  → analyze pages         →   map detected → EDS     →  author sample blocks
               aggregate output          fill block + fields       capture screenshots
               ↓                         ↓                         ↓
               component-inventory.html  component-mapping.html    eds-authoring-guide.md
               site-overview.html        (with mapping rules)      (detailed sections in
                                                                    component-mapping.html)

The output folders mirror Phase 1 and Phase 2+3:

Two mappings, not one

Before diving in, it’s worth being precise about terminology because this kit does two separate mappings:

Between the two sits 1-site-inventory/taxonomy.json — the vocabulary of generic component types the project recognizes, with their classifications (composite/standalone), variants, and atoms.

taxonomy.json — hand-authored, per project

taxonomy.json is not auto-generated. It’s hand-written at project start (use templates/taxonomy.template.json as the starter) and extended incrementally as the per-page analysis loop discovers new types:

  1. Run /analyze-page <slug> → see a component flagged as unknown or missed entirely
  2. Open 1-site-inventory/taxonomy.json and add the new type: classification (composite / standalone / structural), description, variants (with atoms), any styling notes
  3. If the detection side needs updates, also edit scripts/analyze_page.mjs (WIDGET_MAP for simple widget→type renames, or the heuristic block for composites)
  4. Re-run /analyze-page <slug> and check if it picks up the new type

Why hand-authored: the classifications + variants are design decisions, not things a script can infer. Whether a banner is a variant of hero-section or its own type, whether card [redirect] and card [default] should share a taxonomy entry, etc. — those are conversations between the migration consultant and the design/frontend team. The kit keeps them in a data file so the build scripts can read them without hardcoding.

The starter templates/taxonomy.template.json has 5 generic types (heading, image, button, text-block, hero-section) — enough to bootstrap any project. Everything else gets added as you analyze.

Prerequisites

Step 1 — Bootstrap the project

Run /start-analysis. It asks you:

Question What it becomes
Project folder name New folder alongside the kit
Site URL domain + first pages[] entry
Source CMS sourceCMS + preset detection.baseSelectors
Auth provider authentication.* skeleton (you fill credentials)
Cookie consent cookieConsent.*
Initial page list pages[] array

After it finishes you’ll have:

<project>/
├── GOAL.md                        (filled with your answers)
├── 1-site-inventory/
│   ├── site-config.json           (filled)
│   ├── taxonomy.json              (starter)
│   └── pages/                     (empty)
└── 2-eds-mapping/
    └── component-mapping.json     (empty mappings array + default matchStyles)

If the site has auth: open site-config.json and fill in authentication.credentials.username/password before Step 2. Don’t commit this file to a public repo.

Step 2 — Per-page analysis loop

For each slug in pages[]:

2a. Run the analyzer

/analyze-page <slug>

or directly:

node scripts/analyze_page.mjs <url> --slug <slug> --template <template> [--auth]

The script:

  1. Launches Chromium at 1440×900
  2. Navigates to the URL
  3. Dismisses the cookie banner (selector from cookieConsent.acceptSelector)
  4. Handles auth if --auth is passed (DocCheck-style form submission using authentication.* selectors)
  5. Scrolls the page to trigger lazy loading
  6. Hides header + footer via the exclusions config
  7. Takes 01_clean.png (main content only)
  8. Walks the DOM, matching the WIDGET_MAP and running heuristics per component type
  9. Takes 02_annotated.png (components with colored overlays)
  10. Writes components.json with every component’s { type, variant, rect, widgetType, elementId }
  11. Runs an anatomy pass for each composite component — walks into the subtree and extracts sub-components (e.g. a hero’s image + heading + text)
  12. Generates review.html — an interactive per-page review with both screenshots side by side

2b. Review the detection

This is where manual work happens. Open review.html in a browser (or let the /analyze-page skill auto-invoke review-spec for you) and check:

The review-spec skill (if installed) automates most of these checks. Otherwise eyeball it.

2c. Fix detection issues

Detection bugs fall into three buckets — fix in order of least-invasive:

1. Selector misses → edit site-config.json:

2. Taxonomy gaps → edit taxonomy.json:

3. Heuristic failures → edit scripts/analyze_page.mjs:

After each fix, re-run the analyzer and re-review. Iterate until the review is clean.

2d. Move to the next page

Repeat for every slug in pages[]. With 10-15 pages this is usually 1-3 hours total, mostly spent on the first 2-3 pages while you tune the selectors. Once the detection is tight for one page, the rest come fast.

Step 3 — Aggregate (Phase 1 output)

Once all pages are clean:

node scripts/build_inventory.mjs        # → 1-site-inventory/component-inventory.html
node scripts/build_site_overview.mjs    # → 1-site-inventory/site-overview.html

These are pure rollups — no re-rendering, no Playwright. They take a second to run. Open the HTMLs in a browser to sanity check:

If something looks wrong, check:

Step 4 — Map to EDS (Phase 2)

/map-to-eds

The skill:

  1. Enumerates every unique (type, variant) pair from 1-site-inventory/pages/*/components.json
  2. For each pair that isn’t yet in component-mapping.json, asks you three questions: which EDS block, what match type, and any notes
  3. Writes the answer back to component-mapping.json incrementally (so an interrupted session doesn’t lose work)
  4. Runs build_mapping.mjs to regenerate component-mapping.html

Match type cheat sheet

Type When to use Example
direct EDS block fits cleanly, no adaptation needed headingDefault content
split One legacy component needs multiple EDS blocks hero-section.with-anchorshero + link-list
indirect Block exists but needs CSS/config tweaks, or is a reuse with a twist bannerhero (reuse) with overlay CSS
gap No EDS block exists; needs custom dev or content workaround infographic → document as SVG for launch, custom block Phase 2

Editing by hand

If you’d rather skip the skill and edit the JSON directly, here’s the shape:

{
  "mappings": [
    { "site": "hero-section", "variant": "default", "eds": "hero", "match": "direct", "notes": "..." }
  ],
  "matchStyles": { "direct": {...}, "split": {...}, "indirect": {...}, "gap": {...} }
}

Variant is null for components that don’t have variants. build_mapping.mjs looks up each detected component by exact (site, variant) first, falling back to (site).

component-mapping.json does not contain a per-page section — that view is auto-derived from each page’s detected components at render time.

Step 5 — EDS authoring loop (Phase 3)

This phase is optional but strongly recommended: without it, the mapping is still abstract (“hero-section maps to hero”), and you don’t have a concrete deliverable for content editors or a visual comparison showing what the migration actually looks like.

5a. Author sample blocks (conversational)

Open the target EDS repo. Create or reuse a sample page (e.g. sample-<project>.html or a Google Doc published to the sample branch). For each mapped component, author the equivalent EDS block once with realistic content — real images, real headings, real copy. This is the creative work: iterating on sizes, deciding what maps to what field, getting the composition right. Have a conversation with the client and/or the frontend dev as needed.

Tip: do hero first, then cards, then accordion — the ones with the clearest field shapes. Save the tricky ones (form with DocCheck auth, infographics, tabs) for last.

5b. Record capture coordinates

For each block you’ve authored, edit 2-eds-mapping/component-mapping.json and add an edsCapture field to the matching mapping entry:

{
  "site": "hero-section",
  "variant": "default",
  "eds": "hero",
  "match": "direct",
  "notes": "...",
  "edsCapture": {
    "url": "/sample-desmoid",
    "selector": "main .hero:first-of-type",
    "filename": "hero-default.png"
  }
}

Also add edsAuthoring to the entry to describe the field structure — this drives the editor-facing guide and the field table in the detailed comparison section:

"edsAuthoring": {
  "blockName": "hero",
  "fields": [
    { "name": "Background image", "type": "image", "example": "/assets/hero.jpg", "required": true, "notes": "Min 1920×1080" },
    { "name": "Heading", "type": "heading", "example": "# Welcome", "required": true },
    { "name": "Subtitle", "type": "text", "example": "A short tagline" },
    { "name": "CTA", "type": "link", "example": "[Learn more](/about)" }
  ],
  "notes": "Author as the first block on the page."
}

The /map-to-eds skill can collect both of these interactively if you run it after authoring.

5c. Run /capture-eds

Starts your local EDS dev server if it’s not already running, then runs scripts/capture_eds_blocks.mjs which:

  1. Reads every mapping with an edsCapture field
  2. Launches headless Chromium at the configured viewport
  3. For each block: navigates, waits for network idle, scrolls the element into view, screenshots just that element
  4. Writes the PNGs to 2-eds-mapping/eds-screenshots/

Failures are logged inline — a selector that matches 0 elements (the block isn’t authored yet) skips rather than failing the whole run. Use --only <site>[:<variant>] to capture just one block, and --headed to watch it in a visible browser when debugging a selector.

5d. Regenerate the two consumers

node scripts/build_mapping.mjs            # → 2-eds-mapping/component-mapping.html (now with detailed sections)
node scripts/build_authoring_guide.mjs    # → 2-eds-mapping/eds-authoring-guide.md (new deliverable)

Mappings without an edsCapture are listed in the guide as “pending authoring structures” — that’s your todo list.

5e. Iterate

Authoring is rarely one-shot. As the client reviews the sample page, they’ll ask for tweaks: “make the hero image smaller”, “add a subtitle”, “change the card border color”. Each time you re-author, re-run /capture-eds to refresh the screenshots, then re-run build_mapping.mjs + build_authoring_guide.mjs.

When to skip Phase 3

If you’re only producing a pre-sales gap analysis (not a real migration), you can stop after Phase 2. The mapping.html summary is enough to answer “how much EDS block coverage do we have?” and “which components need custom work?”. Phase 3 becomes relevant only when authoring + delivery start.

CMS adapter — what if it’s not Elementor?

The kit was originally built for WordPress/Elementor pharma sites. For other CMSes:

Think of analyze_page.mjs as a CMS adapter. For a new CMS, either:

Neither path is clean, but that’s the honest tradeoff: the heuristics took manual tuning and the kit doesn’t try to hide that.

Common pitfalls

File-by-file reference

File Role
scripts/analyze_page.mjs Playwright-driven page analyzer. CMS adapter — heuristics + WIDGET_MAP + ANATOMY_DEFS live here.
scripts/capture_eds_blocks.mjs Playwright-driven EDS sample page screenshotter. Reads edsCapture entries in the mapping JSON.
scripts/build_inventory.mjs Aggregates pages/*/components.json + taxonomy.jsoncomponent-inventory.html
scripts/build_site_overview.mjs Aggregates same data → site-overview.html (tree + matrix + distribution)
scripts/build_mapping.mjs Reads component-mapping.json + pages data → component-mapping.html (summary + detailed sections when captures exist)
scripts/build_authoring_guide.mjs Reads edsAuthoring fields → eds-authoring-guide.md (deliverable for content editors)
scripts/lib/render.mjs renderTemplate() + esc() helpers
scripts/lib/read-pages.mjs readAllPages() + readTaxonomy() + readSiteConfig() + readMappingData()
templates/*.html HTML templates with `` placeholders (CSS + shell live here; dynamic content comes from scripts)
templates/authoring-guide-template.md Markdown shell for the authoring guide
templates/*.template.json Blank config shapes for new projects
templates/site-config.schema.md Field-by-field docs for site-config.json
templates/GOAL.template.md Project charter starter
skills/*/SKILL.md The four Claude Code skills: /start-analysis, /analyze-page, /map-to-eds, /capture-eds