How the Extraction Phase Captures Multi-State Component Behavior in AI Website Cloner

The extraction phase captures multi-state component behavior by taking sequential CSS snapshots before and after programmatically triggering UI state changes, then diffing the computed styles to generate exact behavior specifications.

The AI Website Cloner Template (JCodesMore/ai-website-cloner-template) automates the replication of complex web interfaces by recording precise visual specifications from target sites. During the extraction phase, the system handles interactive components—like buttons, modals, and navigation items—by capturing how their styles transform across different states.

Understanding the Extraction Pipeline

According to the repository's README, the template follows an "extract → spec → dispatch" loop. While most extraction steps require only a single pass, multi-state component behavior capture is the only step that necessitates two passes of the same element. This ensures that builder agents receive exact styling data without guesswork, preserving hover effects, active states, and transitions in the final Next.js codebase.

The Five-Step Multi-State Capture Process

The extraction workflow defined in .windsurf/workflows/clone-website.md implements a rigorous five-step methodology to record stateful interactions.

Step 1: Initial CSS Snapshot

For a given CSS selector, the agent executes a JavaScript extraction script inside the browser via MCP (Model Context Protocol). This script walks the DOM, records each element’s computed style properties, and returns a JSON payload. The props array in the extraction script lists the specific CSS properties captured, including fontSize, backgroundColor, transform, transition, and boxShadow.

Step 2: Triggering State Changes

After capturing the default state (State A), the agent programmatically triggers the interaction that changes the component’s appearance. The documentation explicitly instructs: "State A… then trigger the state change… State B". This might involve dispatching a MouseEvent for hover states, click events for tabs, or scroll events for sticky headers.

Step 3: Secondary CSS Snapshot

The same extraction script is re-executed on the same element while the UI remains in the new state. This second snapshot captures the computed styles after the DOM has settled into the modified state.

Step 4: Generating the Diff

The two JSON payloads are compared property by property. Any CSS property whose value differs between State A and State B is recorded as a behavior specification. For example, a hover effect might generate a diff entry showing background-color: #fff → #f0f0f0. The "States & Behaviors" section of the workflow file defines the format for these specifications.

Step 5: Persisting to Specification Files

The resulting diff, along with the trigger description and any transition CSS, is written to a Markdown specification file at docs/research/components/<Component>.spec.md. This file serves as the contract for subsequent builder agents, ensuring they implement the exact multi-state styling logic.

The Extraction Script Implementation

The core extraction logic lives in .windsurf/workflows/clone-website.md. The script runs inside the target page and recursively walks the DOM tree up to a depth of four levels, filtering out default values like none, normal, auto, and 0px.

// run inside the page with the target selector substituted
(function (selector) {
  const el = document.querySelector(selector);
  if (!el) throw new Error('Element not found: ' + selector);

  const props = [
    'fontSize','fontWeight','fontFamily','lineHeight','letterSpacing','color',
    'textTransform','textDecoration','backgroundColor','background',
    'padding','paddingTop','paddingRight','paddingBottom','paddingLeft',
    'margin','marginTop','marginRight','marginBottom','marginLeft',
    'width','height','maxWidth','minWidth','maxHeight','minHeight',
    'display','flexDirection','justifyContent','alignItems','gap',
    'gridTemplateColumns','gridTemplateRows','borderRadius','border',
    'boxShadow','position','top','right','bottom','left','zIndex',
    'opacity','transform','transition','cursor','objectFit','filter'
  ];

  const extractStyles = el => {
    const cs = getComputedStyle(el);
    const out = {};
    props.forEach(p => {
      const v = cs[p];
      if (v && !['none','normal','auto','0px','rgba(0, 0, 0, 0)'].includes(v))
        out[p] = v;
    });
    return out;
  };

  const walk = (node, depth = 0) => {
    if (depth > 4) return null;
    const children = [...node.children];
    return {
      tag: node.tagName.toLowerCase(),
      classes: node.className?.split(' ').slice(0,5).join(' '),
      text: node.childNodes.length===1 && node.childNodes[0].nodeType===3 ?
            node.textContent.trim().slice(0,200) : null,
      styles: extractStyles(node),
      images: node.tagName==='IMG' ? {
        src: node.src, alt: node.alt,
        naturalWidth: node.naturalWidth, naturalHeight: node.naturalHeight
      } : null,
      childCount: children.length,
      children: children.slice(0,20).map(c=>walk(c,depth+1)).filter(Boolean)
    };
  };

  return JSON.stringify(walk(el,0),null,2);
})('SELECTOR');

Capturing Hover States in Practice

The following pattern demonstrates how the extraction phase handles a button hover state. The agent first captures the default state, triggers the hover interaction programmatically, captures the hover state, and computes the differential.

// 1️⃣ Capture state A (default)
let stateA = await extract('button.my-primary');

// 2️⃣ Trigger hover programmatically
document.querySelector('button.my-primary')
        .dispatchEvent(new MouseEvent('mouseover', {bubbles:true}));

// 3️⃣ Capture state B (hover)
let stateB = await extract('button.my-primary');

// 4️⃣ Produce diff (simplified)
const diff = {};
for (const prop in stateA.styles) {
  if (stateA.styles[prop] !== stateB.styles[prop]) {
    diff[prop] = {
      from: stateA.styles[prop],
      to:   stateB.styles[prop]
    };
  }
}
console.log('Hover diff', diff);

The resulting diff object is then written into the component spec under the "States & Behaviors" section, following the template format specified in the workflow file.

Key Files and Their Roles

File Purpose
.windsurf/workflows/clone-website.md Contains the full extraction script and multi-state capture instructions at lines 34-41 and 82-88.
README.md Describes the high-level extraction → spec → dispatch pipeline at lines 86-95.
docs/research/components/*.spec.md Storage location for captured multi-state data used by builder agents.
src/app/page.tsx Entry point where cloned pages are assembled from specification files.

Summary

  • Multi-state behavior is captured by taking two CSS snapshots: one before and one after triggering a state change.
  • The extraction script runs via browser MCP and filters out default CSS values to produce clean JSON representations.
  • Diff generation compares the two snapshots and records only changed properties, creating precise behavior specifications.
  • Specifications are stored in docs/research/components/<Component>.spec.md to serve as contracts for builder agents.
  • This approach ensures that interactive states (hover, active, focus) are faithfully reproduced in the generated Next.js codebase without approximation.

Frequently Asked Questions

How does the extraction phase handle complex interactions like scrolling or focus states?

The extraction phase treats any DOM mutation as a state change. For scroll-based states, the agent scrolls the container to the target position before taking the second snapshot. For focus states, it calls .focus() on the element. The same diff-generation logic applies regardless of the interaction type, capturing the exact computed styles after the DOM update settles.

What CSS properties are captured during the extraction phase?

The extraction script captures 48 specific properties including typography (fontSize, letterSpacing), layout (display, flexDirection, gridTemplateColumns), visual styling (backgroundColor, borderRadius, boxShadow), and interactive properties (transition, transform, cursor). The script filters out default values like none, auto, and rgba(0, 0, 0, 0) to keep the output concise.

Where is the captured multi-state data stored after extraction?

The diff data and trigger descriptions are written to Markdown specification files at docs/research/components/<Component>.spec.md. These files follow the "States & Behaviors" template defined in the workflow documentation and serve as the single source of truth for builder agents that generate the actual React components.

Why does the extraction phase require two passes for multi-state components?

Two passes are required because computed styles in the browser only reflect the current state of the DOM. After triggering an interaction (like hover), the element's CSS values change in real-time. By capturing State A and State B separately, the system can calculate the exact difference between states, ensuring that builder agents implement the correct transition values rather than inferring them from static inspection.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →