How Extracted SVG Icons Are Converted to React Components in the AI Website Cloner

The JCodesMore/ai-website-cloner-template pipeline extracts inline <svg> elements from target websites, deduplicates them by hashing their outerHTML, and uses SVGR to generate type-safe React components exported from src/components/icons.tsx.

This repository automates the cloning of existing websites into React-based codebases. A critical part of this workflow involves identifying vector graphics on the source page and transforming them into reusable, customizable React components that integrate with the shadcn/ui and Tailwind CSS stack.

The Six-Step Extraction Pipeline

The conversion process is orchestrated by a browser-automation script (typically using Playwright) that runs during the inspection phase. According to the clone-website workflow documented in .windsurf/workflows/clone-website.md, the system follows a strict six-step pipeline to handle SVG extraction.

Step 1: Collecting SVG Markup

The automation queries the target page for all vector graphics using standard DOM selectors. It executes document.querySelectorAll('svg') to capture every inline <svg> element present in the HTML.

Step 2: Deduplicating Icons

To prevent redundant components, each SVG's outerHTML string is hashed. Identical symbols are collapsed, ensuring that only one unique copy of each visual icon proceeds to the generation phase. This deduplication step keeps the final bundle size minimal and avoids naming conflicts.

Step 3: Generating Component Names

The script derives human-readable, semantic names based on the SVG's visual purpose or context. These names follow strict PascalCase conventions with an Icon suffix. For example, a magnifying glass becomes SearchIcon, while a right-pointing arrow becomes ArrowRightIcon.

Step 4: Converting SVG to React with SVGR

The raw SVG markup is fed into SVGR, the industry-standard tool for transforming SVG into JSX. SVGR strips unnecessary attributes, spreads remaining props onto the <svg> tag, and adds a TypeScript interface accepting props: React.SVGProps<SVGSVGElement>. This allows callers to override attributes like className, fill, or stroke at runtime.

Step 5: Writing to icons.tsx

All generated components are concatenated into a single module at src/components/icons.tsx. As noted in AGENTS.md, this file is explicitly designated in the project structure as the destination for "Extracted SVG icons as React components." Each icon is exported as a named export:

/* src/components/icons.tsx – auto-generated */
import React from 'react';

export const ArrowRightIcon = (
  props: React.SVGProps<SVGSVGElement>
) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    {...props}
  >
    <path d="M5 12h14M12 5l7 7-7 7" />
  </svg>
);

Step 6: Consuming the Components

Downstream UI components import icons directly from the generated module. Because the components accept standard React SVG props, they integrate seamlessly with Tailwind CSS utility classes:

import { ArrowRightIcon } from '@/components/icons';

export function CallToAction() {
  return (
    <a
      href="/pricing"
      className="inline-flex items-center gap-1 font-medium"
    >
      Get started
      <ArrowRightIcon className="size-4" />
    </a>
  );
}

Generated Component Structure

The output in src/components/icons.tsx follows a consistent pattern. Every component is a functional component accepting React.SVGProps<SVGSVGElement> as its sole parameter. The spread operator ({...props}) is placed after default attributes, allowing consumer-defined props to override the defaults. This pattern ensures type safety while maintaining flexibility for styling and accessibility attributes.

Integration with the Tech Stack

The generated components are designed specifically for the repository's preferred stack. By exporting from src/components/icons.tsx, the system aligns with the shadcn/ui component architecture, where icons are typically imported as discrete components rather than sprite sheets. The use of currentColor for strokes and fills ensures compatibility with Tailwind's text color utilities, allowing developers to change icon colors via className="text-blue-500" or similar utilities.

Summary

  • SVGR handles the heavy lifting of converting raw SVG strings into typed React JSX.
  • Icons are deduplicated via hashing of the outerHTML to ensure only unique graphics are converted.
  • Component naming follows PascalCase with an Icon suffix (e.g., SearchIcon, ArrowRightIcon).
  • All icons are centralized in src/components/icons.tsx as named exports for clean imports.
  • The React.SVGProps<SVGSVGElement> interface allows full customization of size, color, and accessibility attributes through standard React props.

Frequently Asked Questions

What tool converts the SVG markup into React JSX?

The pipeline uses SVGR (the standard SVG-to-React conversion tool). It parses the raw SVG string, removes redundant attributes, and wraps the markup in a React functional component that accepts standard SVG props.

How does the system prevent duplicate icons?

During extraction, each SVG element's outerHTML is hashed. Identical hashes trigger deduplication, so only one instance of each unique graphic is converted into a React component. This prevents bloating the icons.tsx file with redundant definitions.

Where are the generated React components stored?

All generated icon components are written to src/components/icons.tsx. This path is hardcoded in the clone-website workflow and referenced in AGENTS.md as the canonical location for extracted SVG assets.

Can I customize the size and color of the generated icons?

Yes. Every generated component accepts a props object of type React.SVGProps<SVGSVGElement>, which includes standard HTML SVG attributes. You can pass className to target Tailwind utilities like size-4 or text-red-500, or directly set width, height, fill, and stroke attributes.

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 →