Configuring shadcn/ui Components for Cloned Website Fidelity: A Complete Guide

The AI Website Cloner Template achieves pixel-perfect website replication by combining shadcn/ui primitives with class-variance-authority (cva) and a custom cn() utility to merge Tailwind classes, allowing exact computed CSS values from source sites to be encoded as reusable component variants.

The JCodesMore/ai-website-cloner-template repository provides a sophisticated approach to configuring shadcn/ui components for cloned website fidelity by leveraging Tailwind CSS v4 and type-safe variant definitions. This architecture enables AI agents to extract computed styles from target websites and translate them into precise, maintainable React components that match the original design down to individual pixels.

The Architecture of High-Fidelity Component Cloning

The template implements a three-layer architecture that separates utility functions, variant definitions, and component wrappers. This separation ensures that cloned websites maintain visual accuracy while remaining modular and extensible.

The Utility Layer for Class Merging

At the foundation of the styling system lies the cn() utility in [src/lib/utils.ts](https://github.com/JCodesMore/ai-website-cloner-template/blob/master/src/lib/utils.ts). This function wraps clsx and tailwind-merge to resolve conflicting Tailwind classes deterministically—critical when the cloning agent stitches together numerous style fragments that may overlap.

// src/lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

The cn() utility guarantees that overlapping Tailwind classes (e.g., bg-primary vs. bg-destructive) are merged correctly according to Tailwind's conflict-resolution rules. This ensures that the final rendered output respects the specificity hierarchy of the original website's computed styles.

Defining Variants with class-variance-authority

The fidelity mechanism centers on class-variance-authority (cva), which creates type-safe variant definitions in [src/components/ui/button.tsx](https://github.com/JCodesMore/ai-website-cloner-template/blob/master/src/components/ui/button.tsx). The buttonVariants object enumerates all possible visual states and sizes extracted from the target website:

// src/components/ui/button.tsx
const buttonVariants = cva(
  "group/button inline-flex shrink-0 items-center justify-center ...",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
        outline: "border-border bg-background hover:bg-muted ...",
        secondary: "bg-secondary text-secondary-foreground ...",
        ghost: "hover:bg-muted hover:text-foreground ...",
        destructive: "bg-destructive/10 text-destructive ...",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-8 gap-1.5 px-2.5 ...",
        xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] ...",
        sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] ...",
        lg: "h-9 gap-1.5 px-2.5 ...",
        icon: "size-8",
        "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] ...",
        "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] ...",
        "icon-lg": "size-9",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

Variants map directly to visual states the cloning agent extracts (e.g., outline appearances on hover), while sizes encode height, padding, and icon scaling from the original site. The defaultVariants provide fallbacks that mirror the source website's design token defaults.

The Component Wrapper Pattern

The exported Button component serves as a thin wrapper that forwards props to the underlying shadcn primitive (ButtonPrimitive) while applying the computed class list via cn():

function Button({
  className,
  variant = "default",
  size = "default",
  ...props
}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
  return (
    <ButtonPrimitive
      data-slot="button"
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  )
}

This wrapper performs three critical functions: prop forwarding passes native button attributes (onClick, type, etc.) through unchanged; class composition generates the appropriate Tailwind string for the requested variant and size; and slot annotation (data-slot="button") enables the cloning agent to locate the component in rendered markup for visual diffing and verification.

How the Clone Agent Achieves Pixel-Perfect Fidelity

The template automates the extraction and encoding of design specifications through a three-phase pipeline:

  1. Design Token Extraction – The agent executes getComputedStyle() on every element in the target site, capturing exact values for background-color, border-width, font-size, and responsive breakpoints.

  2. Specification File Creation – Extracted tokens are serialized to docs/research/components/ (e.g., Button.spec.json) as JSON specifications that enumerate exact token values for each variant and size observed in the source.

  3. Component Code Generation – The agent translates these specifications into cva configurations, ensuring the generated component reproduces the original pixel-perfect style while maintaining type safety.

Because the architecture uses cva, adding new visual states (such as a "loading" variant) requires only appending a new key to the variants.variant object. The existing logic for class merging and default handling remains unchanged, allowing the cloner to retain high fidelity while keeping the codebase maintainable.

Implementation Examples

Basic Component Usage

Import and use the configured components with exact fidelity to the cloned site's design system:

import { Button } from "@/components/ui/button"

export default function Example() {
  return (
    <>
      {/* Default button matches the primary style of the source site */}
      <Button onClick={() => alert("Clicked!")}>Primary</Button>

      {/* Outline variant, small size */}
      <Button variant="outline" size="sm">
        Outline Small
      </Button>

      {/* Destructive variant, large size */}
      <Button variant="destructive" size="lg">
        Delete
      </Button>

      {/* Link-style button */}
      <Button variant="link">Learn more</Button>
    </>
  )
}

Extending Variants for Custom States

To accommodate interactive states not present in the original clone (such as loading indicators), extend the cva configuration without modifying the wrapper logic:

// In src/components/ui/button.tsx – add to buttonVariants.variants.variant
loading: "relative bg-primary/50 text-primary-foreground after:content-[''] after:absolute after:inset-0 after:bg-white/30 after:animate-pulse",

// Use it:
<Button variant="loading">Saving…</Button>

The cn() utility handles merging automatically, ensuring that the spinner overlay class (after:animate-pulse) coexists with any user-provided classes without conflicts.

Key Configuration Files

The fidelity system relies on these specific files within the repository:

Summary

  • cn() utility – Ensures conflict-free merging of Tailwind classes extracted from computed styles, preventing specificity collisions when combining multiple style fragments.

  • class-variance-authority – Provides type-safe variant definitions that map directly to visual states found in the source website, enabling precise replication of interactive behaviors.

  • Component wrappers – Maintain full prop forwarding while applying computed class lists, preserving the original site's accessibility and interaction patterns.

  • Agent pipeline – Automates extraction of design tokens via getComputedStyle() and generates matching component specifications, eliminating manual translation errors.

Frequently Asked Questions

What is the role of the cn() utility in maintaining cloned website fidelity?

The cn() function in src/lib/utils.ts resolves conflicting Tailwind classes by wrapping clsx and tailwind-merge. When the cloning agent extracts multiple style fragments from a source site, this utility ensures that overlapping classes (such as competing background colors) are merged according to Tailwind's precedence rules, producing deterministic output that matches the original computed styles.

How does class-variance-authority improve component generation?

class-variance-authority (cva) creates type-safe variant definitions that enforce compile-time checking of component props. This prevents the cloning agent from generating invalid variant combinations while allowing the extracted design tokens (colors, sizes, spacing) to be organized into semantic categories (default, outline, destructive) that mirror the source website's design system.

Where are the design tokens from the cloned site stored?

Extracted design tokens are serialized to docs/research/components/ as JSON specification files (e.g., Button.spec.json). These files enumerate the exact CSS values for each variant and size observed during the extraction phase. Additionally, [AGENTS.md](https://github.com/JCodesMore/ai-website-cloner-template/blob/master/AGENTS.md) serves as the central repository for agent instructions and component definitions.

Can I add custom variants to cloned components without breaking the agent pipeline?

Yes. The architecture supports safe extension by adding new keys to the variants.variant object in the cva configuration. Since the component wrapper in src/components/ui/button.tsx dynamically consumes the variant definitions, custom states (such as loading or disabled appearances) integrate seamlessly without requiring changes to the prop-forwarding logic or the agent's code generation templates.

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 →