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

> Discover how the AI Website Cloner extracts multi-state components by analyzing CSS style diffs after programmatic interaction triggers. Learn how default and alternate states are captured.

- Repository: [JCodesMore/ai-website-cloner-template](https://github.com/JCodesMore/ai-website-cloner-template)
- Tags: internals
- Published: 2026-07-10

---

**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.

```javascript
// ----------------------------------------------------
// 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.

```markdown

## 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`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.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`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/src/app/layout.tsx), providing the foundation for stateful components, while [`src/lib/utils.ts`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/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`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/src/lib/utils.ts) and global tokens in [`src/app/layout.tsx`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/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`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/src/lib/utils.ts) for conditional class merging and applies global style tokens from [`src/app/layout.tsx`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/src/app/layout.tsx). This ensures the rebuilt component in the Next.js codebase replicates all documented interactive states defined in the [`SKILL.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/SKILL.md) extraction policy.