How Multi-State Components Are Handled During Website Extraction in the AI Website Cloner

The extraction process captures both default and alternate visual states by computing CSS style diffs after programmatically triggering interactions, storing the precise before-and-after values in component specification files.

The JCodesMore/ai-website-cloner-template treats interactive UI elements as first-class artifacts requiring exhaustive documentation. During the reconnaissance phase, the extraction engine follows a rigorous two-step process to ensure that multi-state components—such as hoverable cards, tabbed interfaces, and scroll-driven animations—are faithfully reproduced in the cloned Next.js codebase.

The Two-Step State Extraction Process

Step 1: Capturing the Default State

After loading the target page, the extraction script records the full computed style tree of the target element using getComputedStyle and saves the initial DOM snapshot. This establishes the baseline State A before any interaction occurs, capturing properties like fontSize, color, opacity, and transform.

Step 2: Triggering and Capturing Alternate States

The script then programmatically drives the component's interaction via the browser MCP, dispatching events such as mouseenter, click, or scroll. After triggering the event and allowing a brief moment for style application (typically 100ms), the script captures State B using the same extraction logic. The engine computes the diff between these snapshots to identify exactly which CSS properties change between states.

Generating Component Specifications from State Diffs

The extraction logic runs in the browser MCP environment and leverages vanilla JavaScript to inspect computed styles. The captureStyles function filters out default values like 'none' or '0px' to keep the output concise, while the diff function compares the before and after states to isolate changed properties.

// ----------------------------------------------------
// 1️⃣ Capture State A (default)
// ----------------------------------------------------
function captureStyles(selector) {
  const el = document.querySelector(selector);
  const cs = getComputedStyle(el);
  const props = [
    'fontSize','fontWeight','color','backgroundColor',
    'padding','margin','border','boxShadow','opacity',
    'transform','transition','zIndex','position'
  ];
  const styles = {};
  props.forEach(p => { const v = cs[p]; if (v && v !== 'none' && v !== '0px') styles[p] = v; });
  return { selector, styles };
}
const stateA = captureStyles('#myComponent');

// ----------------------------------------------------
// 2️⃣ Trigger the alternate state (example: hover)
// ----------------------------------------------------
const el = document.querySelector('#myComponent');
el.dispatchEvent(new Event('mouseenter'));   // hover‑enter
// give the browser a moment to apply styles
await new Promise(r => setTimeout(r, 100));

// ----------------------------------------------------
// 3️⃣ Capture State B (after hover)
// ----------------------------------------------------
const stateB = captureStyles('#myComponent');

// ----------------------------------------------------
// 4️⃣ Compute the diff
// ----------------------------------------------------
function diff(a, b) {
  const changes = {};
  Object.keys(b.styles).forEach(k => {
    if (a.styles[k] !== b.styles[k]) changes[k] = { from: a.styles[k], to: b.styles[k] };
  });
  return changes;
}
const stateDiff = diff(stateA, stateB);
console.log(JSON.stringify({ trigger: 'hover', diff: stateDiff }, null, 2));

The resulting diff is stored verbatim in the component specification file at docs/research/components/<Component>.spec.md. The spec explicitly lists the trigger, before/after values for each CSS property, and transition details.


## States & Behaviors

### Hover on #myComponent

- **Trigger:** hover (mouseenter)
- **State A (before):** opacity: 0.9, backgroundColor: rgba(255,255,255,0)
- **State B (after):**  opacity: 1,   backgroundColor: rgba(255,255,255,1)
- **Transition:** transition: opacity 0.2s ease, background-color 0.2s ease

From Specification to Implementation

According to the source code in .github/skills/clone-website/SKILL.md (lines 93-101), the workflow follows the "Extract Every State, Not Just the Default" policy. Only after this exhaustive state capture does the cloner hand the spec to a builder agent. The global style tokens extracted from the target site are received in src/app/layout.tsx, providing the foundation for stateful components, while src/lib/utils.ts supplies the cn() utility that builders use to apply the exact class strings derived from the multi-state spec. This guarantees that the generated component reproduces all interactive states, not just the initial view.

Summary

  • Dual-state capture: The extraction engine captures a default state (State A) and a triggered state (State B) for every interactive element.
  • Computed style diffing: Using getComputedStyle, the system records only the CSS properties that change between states, filtering out irrelevant defaults.
  • Structured documentation: State diffs, triggers, and transition details are stored in docs/research/components/<Component>.spec.md files.
  • Builder integration: The cn() utility in src/lib/utils.ts and global tokens in src/app/layout.tsx enable precise reconstruction of multi-state behaviors in the Next.js output.

Frequently Asked Questions

What types of interactions can trigger state extraction?

The extraction script supports any interaction that can be programmatically dispatched via the browser MCP, including hover (mouseenter), click, scroll position changes, and focus events. For each trigger, the engine captures the specific scroll position or selector that activates the alternate state.

How does the system handle CSS transitions and animations?

The extraction process records the transition property values from getComputedStyle as part of the state diff. The generated spec file explicitly lists the duration, easing function, and animation type (e.g., opacity 0.2s ease), ensuring the cloned component maintains the exact timing functions from the original site.

Where is the multi-state component data stored?

All state diff data is stored in component-specific markdown files located at docs/research/components/<Component>.spec.md. These files document the trigger conditions, before/after style values, and transition details for every captured state of the component.

How does the builder agent use the generated specifications?

The builder agent consumes the specification files to reconstruct components using the cn() utility from src/lib/utils.ts for conditional class merging and applies global style tokens from src/app/layout.tsx. This ensures the rebuilt component in the Next.js codebase replicates all documented interactive states defined in the SKILL.md extraction policy.

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 →