How to Extract and Replicate Smooth Scroll Libraries Like Lenis or Locomotive Scroll

The AI Website Cloner template detects smooth-scroll implementations on target sites by scanning for library-specific CSS classes, then installs and initializes the corresponding library through custom React hooks in the Next.js root layout.

The JCodesMore/ai-website-cloner-template takes an agnostic approach to scrolling behavior, delegating detection and replication to the cloning agent rather than embedding scroll logic directly. According to the workflow instructions in .windsurf/workflows/clone-website.md, the agent checks for .lenis or .locomotive-scroll classes to identify which library powers the target site. This extraction workflow ensures that the cloned Next.js project preserves the original site's scrolling physics and interaction patterns.

Step 1: Detect the Smooth Scroll Library

Before writing any code, the cloning agent scans the target website's DOM for telltale signatures of smooth-scroll implementations. According to the template's inspection guide, the agent looks for:

  1. The .lenis class (Lenis) or .locomotive-scroll class (Locomotive Scroll) applied to container elements
  2. Scroll-container wrappers such as <div class="lenis">...</div> or elements with [data-scroll-container] attributes

This detection step is documented in the .windsurf/workflows/clone-website.md file under the smooth-scroll check section, which explicitly instructs the agent to identify these libraries before proceeding with installation.

Step 2: Install the Required Dependency

Once identified, the cloning agent adds the appropriate npm package to the project's package.json. For Lenis, use:

npm install @studio-freight/lenis

For Locomotive Scroll, use:

npm install locomotive-scroll

These dependencies are installed alongside other detected libraries, ensuring the cloned project matches the target site's entire scroll stack.

Step 3: Create Initialization Hooks

The template relies on client-side React hooks to instantiate smooth-scroll libraries after hydration. Create a new file in src/lib/ to encapsulate the initialization logic for each library.

Initializing Lenis

Create src/lib/lenis.ts with the following implementation:

'use client';
import { useEffect } from 'react';
import Lenis from '@studio-freight/lenis';

export function useLenis() {
  useEffect(() => {
    const lenis = new Lenis({
      duration: 1.2,
      easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
    });
    
    function raf(time: number) {
      lenis.raf(time);
      requestAnimationFrame(raf);
    }
    
    requestAnimationFrame(raf);
    return () => lenis.destroy();
  }, []);
}

Initializing Locomotive Scroll

Create src/lib/locomotive.ts for Locomotive Scroll integration:

'use client';
import { useEffect } from 'react';
import LocomotiveScroll from 'locomotive-scroll';
import 'locomotive-scroll/dist/locomotive-scroll.css';

export function useLocomotive() {
  useEffect(() => {
    const scroll = new LocomotiveScroll({
      el: document.querySelector('[data-scroll-container]')!,
      smooth: true,
    });
    
    return () => scroll.destroy();
  }, []);
}

Both hooks follow the same pattern: they instantiate the library inside a useEffect to avoid server-side execution, configure specific easing curves and container selectors, and return a cleanup function that destroys the instance on unmount.

Step 4: Wire the Hook into the Root Layout

To activate smooth scrolling across all pages, import and invoke the appropriate hook in the root layout file at src/app/layout.tsx:

import './globals.css';
import { useLenis } from '@/lib/lenis';        // Lenis implementation
// import { useLocomotive } from '@/lib/locomotive'; // Locomotive Scroll alternative

export default function RootLayout({ children }: { children: React.ReactNode }) {
  useLenis();            // Activates Lenis smooth scrolling
  // useLocomotive();   // Alternative: Activates Locomotive Scroll

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

Because layout.tsx wraps every route in the Next.js application, initializing the library here ensures consistent scroll behavior throughout the cloned site.

Step 5: Configure Global CSS Support

Some smooth-scroll libraries require specific CSS resets or container styles. Update src/app/globals.css to include any library-specific rules:

For Locomotive Scroll, ensure the scroll container has proper height and overflow properties:

html, body {
  height: 100%;
  overflow: hidden;
}

[data-scroll-container] {
  min-height: 100vh;
}

The globals.css file already exists in the scaffold, making it the appropriate location for these global style overrides that support the smooth-scroll implementation.

Summary

Extracting and replicating smooth scroll libraries in the AI Website Cloner template follows a standardized workflow:

  • Detection: Scan target sites for .lenis or .locomotive-scroll CSS classes and container attributes as defined in .windsurf/workflows/clone-website.md
  • Installation: Add @studio-freight/lenis or locomotive-scroll via npm based on detection results
  • Initialization: Create TypeScript hooks in src/lib/ that instantiate libraries client-side with proper RAF loops and cleanup functions
  • Integration: Import hooks into src/app/layout.tsx to enable site-wide smooth scrolling
  • Styling: Update src/app/globals.css with required container CSS for full compatibility

Frequently Asked Questions

How does the AI Website Cloner template detect which smooth scroll library a target site uses?

The template instructs the cloning agent to inspect the target site's DOM for specific CSS classes. The agent searches for elements with the .lenis class to identify Lenis implementations, or .locomotive-scroll and [data-scroll-container] attributes to detect Locomotive Scroll. This detection happens before any code generation, ensuring the correct dependency is installed in the cloned project's package.json.

Can I use both Lenis and Locomotive Scroll simultaneously in the same project?

No, you should not initialize both libraries simultaneously as they compete for control of the scroll thread and window object. The template is designed to detect and install only the library found on the target site. If you need to switch between them for testing, comment out one hook and uncomment the other in src/app/layout.tsx, but never call both useLenis() and useLocomotive() in the same component.

Why must the initialization hooks be marked as 'use client' in Next.js?

Smooth-scroll libraries like Lenis and Locomotive Scroll access browser-only APIs such as document.querySelector, window.requestAnimationFrame, and DOM mutation methods. The 'use client' directive ensures these hooks execute only on the client side after React hydration, preventing server-side rendering errors that would occur if the code ran in Node.js during the initial page build.

Where should I configure custom easing curves or scroll durations?

For Lenis, modify the duration and easing parameters directly in the Lenis constructor within src/lib/lenis.ts. The default implementation uses a custom exponential easing function: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)). For Locomotive Scroll, configuration options are passed to the constructor in src/lib/locomotive.ts, though many behavioral adjustments are handled through CSS and data attributes on individual elements rather than the global instance.

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 →