How to Avoid the Click-Based vs Scroll-Driven Mistake in Website Cloning

The "click-based vs scroll-driven" mistake occurs when reverse-engineering agents assume UI interactivity requires clicking when the original site actually uses scroll-based triggers like IntersectionObserver or sticky positioning, causing functional mismatches that require expensive rewrites.

When cloning modern websites, accurately identifying whether a component responds to clicks or scrolls determines the success of the entire replication pipeline. In the JCodesMore/ai-website-cloner-template repository, this distinction is critical because misidentifying the interaction model leads to dead components that look correct in screenshots but fail during user interaction. Understanding the root causes of this error—and implementing the scroll-first inspection protocol documented in the source code—ensures your Next.js clones capture both the pixel-perfect visuals and the intended behavior.

Why the Click-Based vs Scroll-Driven Mistake Happens

The error typically stems from inspection workflows that prioritize static analysis over dynamic behavioral observation.

Static CSS Inspection Traps

Cloning pipelines often begin by extracting computed CSS for each element in its initial state. When inspection stops after capturing the initial state, the agent misses visual changes that occur while the page scrolls. According to the docs/research/INSPECTION_GUIDE.md, this superficial analysis captures background: transparent but misses the transition to background: #fff that occurs after scrolling 80 pixels.

Overlooking Scroll-Trigger Mechanisms

Modern websites employ diverse scroll-based techniques that static inspectors frequently miss:

  • IntersectionObserver callbacks that toggle classes or lazy-load content
  • scroll-snap-type containers that lock the viewport to specific sections
  • position: sticky headers that change appearance after crossing a threshold
  • Custom smooth-scroll libraries such as Lenis or Locomotive Scroll (identified by .lenis or .locomotive-scroll CSS classes)

When these mechanisms go undetected, the builder agent cannot reproduce the scroll-linked behavior.

Misidentifying Interaction Patterns

The most costly error occurs when inspectors later "click" a tab or button to observe state changes, inadvertently reconstructing a click handler that never existed in the source. The resulting clone appears correct in screenshots but feels broken during actual use because the original logic used scroll-driven tab switching. Conversely, scrolling past click-driven sections without interacting causes the clone to miss crucial onClick handlers entirely.

How to Avoid the Click-Based vs Scroll-Driven Error

The JCodesMore/ai-website-cloner-template repository provides a six-step inspection protocol to eliminate these mismatches.

Scroll-First Inspection Protocol

Scroll before clicking. As documented in docs/research/INSPECTION_GUIDE.md, the "don't click first" rule requires slowly scrolling through each section and watching for visual changes without any mouse interaction. This reveals scroll-driven animations that click-based testing would obscure.

Identify the Interaction Model

Classify each component into one of six categories: static, click-driven, scroll-driven, hover-driven, time-driven, or combination. This classification appears in the component specification and dictates the entire generation strategy. The .opencode/commands/clone-website.md file reinforces that this decision must occur before writing any component code.

Capture Before and After States

Record computed styles at the initial scroll position (0px) and after the trigger threshold (e.g., 100px). Document the exact mechanism—whether an IntersectionObserver threshold, scroll-snap point, sticky offset, or library-specific listener—in the specification's trigger field.

Document in the Component Specification

The specification must include an INTERACTION MODEL block that explicitly states the type and trigger details. Here is the canonical structure from the repository:

// docs/research/<site>/components/header.spec.ts
export const HeaderSpec = {
  name: 'Header',
  interactionModel: 'scroll-driven',
  trigger: {
    type: 'scroll',
    thresholdPx: 80,
    mechanism: 'IntersectionObserver',
    rootMargin: '-30% 0px',
  },
  states: {
    before: {
      background: 'transparent',
      boxShadow: 'none',
      height: '100px',
    },
    after: {
      background: '#fff',
      boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
      height: '70px',
    },
  },
};

Generate UI from Specifications

Builder agents read the interactionModel and trigger fields to select the correct implementation template. A scroll-driven model generates an IntersectionObserver or window.addEventListener('scroll', …) implementation, while a click-driven model generates an onClick handler.

import { useEffect, useState } from 'react';
import { HeaderSpec } from './header.spec';

export default function Header() {
  const [scrolled, setScrolled] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => setScrolled(entry.intersectionRatio < 1),
      {
        rootMargin: HeaderSpec.trigger.rootMargin,
        threshold: 0,
      },
    );
    observer.observe(document.body);
    return () => observer.disconnect();
  }, []);

  return (
    <header
      className={scrolled ? 'bg-white shadow-md h-16' : 'bg-transparent h-24'}
    >
      {/* logo, nav, etc. */}
    </header>
  );
}

Detect Smooth-Scroll Libraries

When the inspection finds .lenis or .locomotive-scroll classes, the pipeline must add the library to package.json and inject initialization in src/app/layout.tsx:

// src/app/layout.tsx – global init
import Lenis from '@studio-freight/lenis';
import { useEffect } from 'react';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    const lenis = new Lenis({
      smooth: true,
    });
    const raf = () => {
      lenis.raf();
      requestAnimationFrame(raf);
    };
    raf();
  }, []);

  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

Architectural Impact of Correct Interaction Detection

Accurate interaction model identification affects three architectural layers:

  • Component generation – The spec drives template selection. Scroll-driven components import useEffect and observer logic; click-driven components use event handlers.
  • Global dependencies – Detecting smooth-scroll libraries prompts automatic injection into globals.css or layout components.
  • Testing – The test suite automatically toggles between scroll and click scenarios based on the documented model, catching mismatches before deployment.

Summary

  • Scroll first, click second – Always scroll through sections before clicking to reveal scroll-driven behaviors
  • Document the interaction model – Use the HeaderSpec pattern with explicit interactionModel and trigger fields in component specifications
  • Capture state transitions – Record computed styles at multiple scroll positions, not just the initial viewport
  • Check for smooth-scroll libraries – Look for .lenis or .locomotive-scroll classes to ensure proper global initialization
  • Generate from specs – Let builder agents read the interaction model to choose between IntersectionObserver and onClick implementations

Frequently Asked Questions

What exactly is the click-based vs scroll-driven mistake?

The click-based vs scroll-driven mistake occurs when a cloning agent incorrectly assumes a UI element requires a click to change state when the original website actually uses scroll position to trigger the same change. This results in clones that implement onClick handlers for effects that should activate via IntersectionObserver or scroll event listeners, causing the cloned site to feel unresponsive or broken during normal scrolling behavior.

How can I tell if a website uses scroll-driven animations?

Look for three specific indicators: CSS classes like .lenis or .locomotive-scroll that indicate smooth-scroll libraries, position: sticky elements that transform after scrolling past a threshold, and scroll-snap-type containers that lock the viewport to sections. Additionally, slowly scroll through the page while watching the Elements panel in DevTools—if classes toggle or styles change without clicking, the component is scroll-driven.

Why does the inspection guide emphasize "don't click first"?

The docs/research/INSPECTION_GUIDE.md emphasizes this rule because modern websites often hide scroll-driven logic behind components that also accept clicks. Clicking first risks implementing a redundant event handler while missing the actual scroll-trigger mechanism that controls the component's primary behavior. Scrolling first reveals the true interaction model before any manual interference occurs.

Which files in the repository control interaction model detection?

The primary documentation lives in docs/research/INSPECTION_GUIDE.md, which contains the "Don't click first" checklist and state capture procedures. The .opencode/commands/clone-website.md and .github/skills/clone-website/SKILL.md files propagate these rules to AI coding platforms. Finally, src/app/layout.tsx demonstrates where global scroll behaviors like Lenis initialization are wired into the application architecture.

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 →