How Multi-State Components Are Managed in the AI Website Cloner Template
The AI Website Cloner template dynamically generates tabs, accordions, and scroll-triggered elements by first detecting whether the source website uses click or scroll interactions, then scaffolding shadcn/ui components that preserve the exact behavior and visual states of the original.
The JCodesMore/ai-website-cloner-template provides a Next.js 16 and React 19 foundation that uses intelligent cloning agents to replicate complex UI patterns from any target website. Rather than hard-coding interaction logic, the template analyzes the source site's behavior to determine whether components rely on click events or scroll triggers before generating type-safe TypeScript implementations using shadcn/ui primitives.
Architectural Overview
Interaction Model Detection
Before emitting any component code, the cloning agent inspects the target page to classify widgets as either click-driven or scroll-driven. This decision follows a strict rule documented in .windsurf/workflows/clone-website.md:
"Don't build click-based tabs when the original is scroll-driven (or vice versa). Determine the interaction model FIRST by scrolling before clicking."
This guideline prevents semantic mismatches where scroll-based navigation might be incorrectly implemented as clickable tabs. The agent scrolls through the target page to observe sticky headers, parallax effects, and scroll-spy navigation before processing click handlers.
State Extraction
For each detected state variation—such as individual tab panes or accordion sections—the agent records the complete DOM subtree and computed styles. The workflow explicitly requires comprehensive state capture:
"For tabs/pills: click EACH ONE and record the content that appears for each state"
This ensures that hidden states (like inactive tab panels or collapsed accordion content) are fully preserved in the generated output rather than being omitted or placeholder-filled.
Component Implementation Patterns
Click-Driven Tabs
When the source website uses clickable navigation, the agent generates a standard shadcn/ui Tabs component. The implementation imports primitives from @/components/ui/tabs and uses the cn() utility from src/lib/utils.ts for conditional class merging.
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
import { cn } from '@/lib/utils';
export default function ProductTabs() {
return (
<Tabs defaultValue="featured" className="w-full">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="featured">Featured</TabsTrigger>
<TabsTrigger value="productivity">Productivity</TabsTrigger>
<TabsTrigger value="creative">Creative</TabsTrigger>
</TabsList>
<TabsContent value="featured" className={cn('p-4')}>
{/* Content harvested from the "Featured" pane */}
</TabsContent>
<TabsContent value="productivity" className={cn('p-4')}>
{/* Content harvested from the "Productivity" pane */}
</TabsContent>
<TabsContent value="creative" className={cn('p-4')}>
{/* Content harvested from the "Creative" pane */}
</TabsContent>
</Tabs>
);
}
Accordion Components
Accordions follow a similar pattern using the shadcn/ui Accordion primitive. The agent maps each discovered header-panel pair to AccordionItem components with preserved content from the source DOM.
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion';
import { cn } from '@/lib/utils';
export default function FAQAccordion() {
return (
<Accordion type="single" collapsible className="w-full space-y-2">
<AccordionItem value="item-1">
<AccordionTrigger className={cn('text-lg')}>What is AI Website Cloner?</AccordionTrigger>
<AccordionContent>
{/* Extracted answer body */}
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger className={cn('text-lg')}>How does cloning work?</AccordionTrigger>
<AccordionContent>
{/* Extracted answer body */}
</AccordionContent>
</AccordionItem>
</Accordion>
);
}
Scroll-Triggered Elements
For scroll-dependent behaviors—such as headers that transform after scrolling past a threshold—the agent generates React components that listen to window scroll events or use IntersectionObserver. These components mirror the original interaction model rather than converting them to click events.
import { useEffect, useState } from 'react';
import { cn } from '@/lib/utils';
export default function StickyHeader() {
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 100);
window.addEventListener('scroll', onScroll);
return () => window.removeEventListener('scroll', onScroll);
}, []);
return (
<header
className={cn(
'fixed top-0 w-full transition-all',
scrolled ? 'bg-primary-800 shadow-md' : 'bg-transparent'
)}
>
{/* Header content extracted from the original site */}
</header>
);
}
Styling and Design Token Integration
All extracted CSS variables and color tokens are written to src/app/globals.css, ensuring that generated multi-state components inherit the exact visual properties of the source website. The cn() utility function exported from src/lib/utils.ts handles conditional class composition throughout the component tree, allowing the agents to merge Tailwind utility classes with dynamic state classes safely.
The root layout in src/app/layout.tsx imports these global styles and provides the necessary React context for the shadcn/ui primitives to function correctly across the application.
Summary
- Interaction detection first: The cloning workflow in
.windsurf/workflows/clone-website.mdmandates determining whether elements are click-driven or scroll-driven before generating code. - Comprehensive state capture: Agents must click through every tab, accordion section, or toggle state to record all content variations, not just the default visible state.
- shadcn/ui foundation: Generated components leverage Radix UI primitives via shadcn/ui, providing accessible, keyboard-navigable multi-state elements.
- Utility-driven styling: The
cn()function fromsrc/lib/utils.tsenables safe class merging, whilesrc/app/globals.csshouses the extracted design tokens. - Behavioral fidelity: Scroll-triggered elements maintain their original interaction model through native scroll listeners rather than being converted to click events.
Frequently Asked Questions
How does the AI determine whether to use click or scroll interactions?
The agent follows a strict protocol defined in .windsurf/workflows/clone-website.md that requires scrolling through the target page before clicking any elements. This reveals whether navigation changes occur via scroll position (sticky headers, scroll-spy) or click events, ensuring the generated component matches the original interaction model exactly.
What happens to hidden content in tabs or accordions?
The cloning instructions explicitly require clicking each tab or accordion header to capture the content that appears in every state. This harvested content is then embedded directly into the corresponding TabsContent or AccordionContent components, preserving the full information architecture of the source site.
Where are the design tokens stored in the cloned template?
Extracted CSS variables, color values, and typography scales are written to src/app/globals.css. This file serves as the single source of truth for visual styling, ensuring that all generated multi-state components maintain pixel-perfect fidelity with the original website's aesthetic.
Can I modify the generated multi-state components after cloning?
Yes, the generated components are standard React TypeScript files using shadcn/ui primitives. They reside in src/components/ui/ and follow conventional patterns, allowing developers to extend functionality, add animation libraries like Framer Motion, or refactor the state logic while maintaining the initially harvested content and styling.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →