# How to Detect Interaction Models (Scroll vs Click) When Cloning Websites

> Learn how to detect scroll vs click interaction models when cloning websites. Discover the best method to identify UI behavior for accurate website replication.

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

---

**Always scroll first before clicking to determine if a UI section is scroll-driven or click-driven, documenting the exact trigger type and threshold in your component specification.**

The `ai-website-cloner-template` repository provides a systematic workflow for reverse-engineering websites, where identifying the correct interaction model is the critical first step before writing any component code. Treating a scroll-driven tab as click-driven forces a complete rewrite later, making this detection phase the single most important quality gate in the cloning process.

## The Scroll-First Detection Workflow

According to the workflow defined in [`.windsurf/workflows/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.windsurf/workflows/clone-website.md) (lines 80-86), the repository mandates a specific observation order to avoid what it calls "the #1 most expensive mistake."

### Step 1: Observe Scroll Behavior First

Open the target page with a browser-automation tool and scroll slowly from top to bottom. Watch for any element mutations such as headers shrinking, backgrounds changing, or tabs auto-switching. This step is documented in the workflow at lines 80-84.

### Step 2: Record Scroll Triggers

When visual changes occur on scroll, capture the specific mechanism:

- **Trigger type**: `IntersectionObserver`, `scroll-snap`, `position:sticky`, CSS `animation-timeline`, or custom JS listeners
- **Scroll offset or intersection ratio** that initiates the change
- **Before/after computed styles** using `getComputedStyle()`

This data capture guidance appears in [`.opencode/commands/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.opencode/commands/clone-website.md) at lines 100-108.

### Step 3: Test Click/Hover Only If Static

If the page remains static during scrolling, only then interact with clickable elements like buttons, tabs, or accordions. Record the same data points (trigger, before/after states) for these interactions. The click-first warning and subsequent testing steps are detailed in lines 86-88 of the same command file.

### Step 4: Document the Model

Add an `INTERACTION MODEL` entry to the component specification file (typically under `docs/research/<site>/`). The canonical format is:

```

INTERACTION MODEL: scroll-driven with IntersectionObserver
// or
INTERACTION MODEL: click-to-switch with opacity transition

```

This spec template is illustrated in the workflow at lines 86-89.

## Automating Detection with Code Examples

The repository provides patterns for automating this detection process using Playwright or Puppeteer.

### Detecting Scroll-Driven Headers

```typescript
// utils/interactionDetector.ts
export async function detectScrollHeader(page: any) {
  // `page` is a Playwright/Puppeteer page instance
  await page.evaluate(() => {
    const header = document.querySelector('header');
    if (!header) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        console.log('Header scroll trigger at:', entry.intersectionRatio);
      },
      { threshold: [0, 0.5, 1] }
    );

    observer.observe(header);
  });
}

```

This script logs the exact intersection ratio at which header changes occur, providing the precise threshold needed for your specification.

### Detecting Click-Driven Tab Switches

```typescript
// utils/interactionDetector.ts
export async function detectClickTabs(page: any) {
  const tabs = await page.$$('.tab-button');
  for (const tab of tabs) {
    const label = await tab.textContent();
    await tab.click();
    const panel = await page.$('.tab-panel.active');
    const content = await panel?.innerHTML();
    console.log(`Tab "${label}" shows content length ${content?.length}`);
  }
}

```

Run this only after confirming the page is static on scroll to capture the before/after states for click-driven UI components.

### Recording the Model in Your Spec

```yaml

# docs/research/example.com/homepage.yaml

components:
  - name: Header
    interactionModel: scroll-driven
    trigger:
      type: IntersectionObserver
      threshold: 0.4
    states:
      - name: default
        css: {...}
      - name: scrolled
        css: {...}

```

## Why Scroll-First Detection Matters

- **Scroll-driven UI** often relies on invisible observers or CSS tricks that a click-first approach would miss entirely.
- Building a click-based component where the original uses scroll leads to mismatched animations, missing sticky headers, and broken user experience.
- The template's documentation in [`.windsurf/workflows/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.windsurf/workflows/clone-website.md) explicitly identifies incorrect interaction model assumptions as the most expensive mistake in the cloning process.

## Summary

- Always scroll before clicking when analyzing a target website to detect interaction models accurately.
- Record specific trigger types (`IntersectionObserver`, `scroll-snap`, sticky positions) and thresholds from `getComputedStyle()` comparisons.
- Document findings using the canonical `INTERACTION MODEL` format in your component spec files under `docs/research/<site>/`.
- Verify your implementation against the checklist at lines 423-424 of the workflow to ensure the rebuilt page matches the recorded model.

## Frequently Asked Questions

### What happens if I detect a scroll-driven component but implement it as click-driven?

You will face a complete rewrite of the component logic. Scroll-driven interfaces often depend on precise scroll positions, IntersectionObserver thresholds, or CSS scroll-timeline animations that cannot be replicated with click event handlers without restructuring the entire component architecture.

### How do I detect CSS scroll-snap behavior programmatically?

Check the container's CSS properties using `getComputedStyle()` for `scroll-snap-type` and `scroll-snap-align` values. The repository recommends logging these properties alongside the scroll offset to determine if snapping occurs at specific intervals rather than smooth scrolling.

### Can a single component have both scroll and click interaction models?

Yes, hybrid components exist. The workflow in [`.opencode/commands/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.opencode/commands/clone-website.md) advises documenting both triggers in your spec file, noting which interaction takes precedence and whether they operate on the same or different state properties.

### Where should I store the interaction model documentation?

Store the `INTERACTION MODEL` entry in the component specification file located under `docs/research/<site>/` as shown in the workflow at lines 86-89 of [`.windsurf/workflows/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.windsurf/workflows/clone-website.md). This ensures the implementation team has precise technical requirements before writing code.