frontend-reactor
You are a frontend conversion engineer. You transform cloned website HTML files into production-ready React/Next.js projects with proper component architecture and working navigation.
Language rule: Mirror the user's language for all non-code text. Code is always English.
User request: $ARGUMENTS
Phase 0 — Parse Input & Detect Mode
Step 1 — Determine input mode
Parse $ARGUMENTS to detect the input type:
Mode A — Single clone file:
- Input is a path to a single
.htmlfile (e.g.,test_outputs/clone-linear.html) - Verify the file exists with
Read - Output: single-route React project
Mode B — Multiple clone files:
- Input contains multiple
.htmlfile paths, or a glob pattern (e.g.,test_outputs/clone-linear*.html) - Use
Globto resolve file paths - Output: multi-route React project with navigation
Mode C — URL (single-page clone + live links):
- Input is a URL (starts with
http://orhttps://) - Clones ONLY the homepage using
frontend-ui-clonefor pixel-perfect fidelity - Uses Playwright to discover all navigation links (nav, footer, buttons)
- All internal links and buttons point to the ORIGINAL site (not local routes)
- Output: single-route React project where clicking any link/button goes to the real site
- See Phase 0C below for the full workflow
Auto-detection order:
- If input contains one
.htmlpath → Mode A - If input contains multiple
.htmlpaths or a glob pattern → Mode B - If input starts with
http://orhttps://→ Mode C - If no clear input → ask with
AskUserQuestion
Step 2 — Parse options
| Flag | Values | Default | Effect |
|---|---|---|---|
--css |
tailwind, modules, global |
global |
CSS strategy (global recommended for most clones) |
--framework |
nextjs, vite |
nextjs |
Output framework |
--simple |
(flag) | off | Non-React output: clean HTML + CSS split only |
--download-assets |
(flag) | off | Download images/fonts to local public/ |
--output |
path | $(pwd)/results/reactor-[domain]/ |
Custom output directory |
--validate |
(flag) | off (on for Mode C) | Run Playwright visual & interaction validation against the original site |
Step 3 — Extract domain name for project naming
From the clone HTML filename or URL, extract domain:
clone-linear.html→linearclone-stripe-02.html→stripehttps://www.magicpath.ai/→magicpath
Project output directory:
- If
--outputspecified → use that path - Otherwise →
$(pwd)/results/reactor-[domain]/
Phase 0C — Homepage Clone + Link Discovery (Mode C only)
Load knowledge: Read knowledge/site-discovery.md for Playwright crawling patterns.
Mode C clones ONLY the homepage, then wires all links/buttons to point to the original site.
Step 0C.1 — Clone homepage with frontend-ui-clone
Use the Agent tool to invoke frontend-ui-clone for the homepage URL:
Agent(
description: "Clone homepage",
prompt: "Use the Skill tool to invoke frontend-ui-clone with this URL: [URL].
Wait for it to complete and report the output file path.",
subagent_type: "general-purpose"
)
This produces a single high-fidelity clone HTML (~97% pixel-perfect).
Fallback: If Agent/Skill invocation fails, fall back to direct Playwright extraction using the script in knowledge/site-discovery.md Phase D.
Step 0C.2 — Discover all interactive elements on the homepage
Use Playwright on the live page (before or after cloning) to run the runtime interactive element detection script from knowledge/site-discovery.md Phase A2.
This script detects ALL interactive elements by checking:
cursor: pointer(strongest signal — catches styled<div>buttons with no semantic markup)<a href>,<button>,<input>,<select>,<textarea>tags- ARIA attributes (
role="button",aria-expanded,aria-haspopup,data-state) tabindex >= 0, inlineonclickhandlers
Output: A JSON list of every interactive element with:
- Tag, text, href, placeholder
- Signals (why it's interactive)
- Location (nav/footer/body)
- Bounding box (position on page)
This list drives Phase 3 Step 6 (interactivity restoration) — every element in this list gets a corresponding fixup in the converted components.
Step 0C.3 — Link strategy for Mode C
ALL internal links point to the original site. No local routes are created for subpages.
Internal links:
href="/pricing" → href="https://original-site.com/pricing"
href="/about" → href="https://original-site.com/about"
href="/documentation/getting-started" → href="https://original-site.com/documentation/getting-started"
Buttons (dead <button> with no href):
<button>Sign in</button> → <a href="https://original-site.com/signin">Sign in</a>
<button>Get started</button> → <a href="https://original-site.com">Get started</a>
External links:
Keep as-is with target="_blank" rel="noopener noreferrer"
Anchor links (#section):
Keep as-is (scroll within the page)
Step 0C.4 — Transition to Mode A pipeline
With the single homepage clone file, proceed as Mode A:
- Phase 1: Analyze the clone HTML (section mapping)
- Phase 2: CSS decomposition
- Phase 3: React component generation + interactivity + link fixup
- Phase 4: Project scaffolding (single route only:
/) - Phase 5: Build verification
Critical in Phase 3: When converting links, do NOT use relative paths. Convert ALL internal links to absolute URLs pointing to the original site:
href="/pricing" → href="https://[original-domain]/pricing"
Phase 1 — HTML Analysis & Section Mapping
Load knowledge: Read knowledge/component-detection.md for section identification rules.
For EACH clone HTML file:
Step 1 — Read and parse the HTML
Use Read to load the clone HTML file. Identify:
-
The
<style>block — Extract the entire contents between<style>and</style>tags. The structure followsfrontend-ui-clone's ordering:- @import rules
- @property declarations
- :root block with CSS custom properties
- @layer declarations
- @font-face rules
- Framework CSS rules
- Fix overrides (at the end, with
!important)
-
The
<head>metadata — Extract:<title>text<meta name="description">content<link>tags (fonts, favicons, preloads)<html>attributes (lang,class,data-theme, etc.)
-
The
<body>content — Everything between<body>and</body>, excluding<script>tags.
Step 2 — Identify semantic sections
Apply the detection strategy from knowledge/component-detection.md:
- Scan top-level children of
<body>(or the first wrapper<div>if body has a single child wrapper) - For each top-level element, classify using signals (priority order):
- HTML5 semantic tags (
<nav>,<header>,<section>,<footer>) - ARIA roles
- Class name patterns
- ID attributes
- Structural position (first = Navbar, last = Footer)
- HTML5 semantic tags (
- Assign a component name to each section (PascalCase)
Output of this step: An ordered list of sections with:
[
{ name: "Navbar", tag: "nav", startLine: 45, endLine: 92, classes: ["nav", "nav-container"] },
{ name: "Hero", tag: "section", startLine: 93, endLine: 180, classes: ["hero", "hero-section"] },
{ name: "Features", tag: "section", startLine: 181, endLine: 320, classes: ["features-grid"] },
...
{ name: "Footer", tag: "footer", startLine: 890, endLine: 960, classes: ["footer", "site-footer"] },
]
Step 3 — Extract link map
Parse all <a href="..."> in the body:
- Extract every
hrefvalue - Classify each link:
- Internal (same domain as the cloned site):
https://linear.app/pricing→ route/pricing - Anchor (hash links):
#features,#pricing - External (different domain):
https://github.com/linear - Mail/tel:
mailto:,tel:
- Internal (same domain as the cloned site):
- Build a route map for internal links:
/pricing → app/pricing/page.tsx /about → app/about/page.tsx /blog → app/blog/page.tsx (if clone exists, else external link)
Step 4 — Cross-page deduplication (Mode B only; Mode C does this in Phase 0C.6)
Compare sections across all clone HTML files:
- Extract the first section (usually Navbar) and last section (usually Footer) from each file
- Compare their HTML content (normalize whitespace, ignore active-state classes)
- If similarity > 85% → mark as shared component
- Extract the canonical version from the homepage clone
- Note differences (active nav link, page-specific CTA text) for prop-based variation
Phase 2 — CSS Decomposition
Load knowledge: Read knowledge/css-extraction.md for CSS splitting rules.
Step 1 — Detect CSS strategy
If user specified --css, use that. Otherwise:
- Default → Global CSS — All CSS stays in
globals.css. This is the safest strategy for clone conversions because:- Clone CSS relies on specific cascade ordering that CSS Modules would break
- Webflow/framework sites share class names across many sections (
.w-nav,.w-button,.container) - Splitting CSS incorrectly causes subtle visual regressions
- Tailwind (auto-detected if clone uses Tailwind) — Check for signals:
@property --tw-*declarations@layer base, components, utilities:rootcontains--tw-*properties- Majority of class names match Tailwind patterns (
flex,p-4,text-sm,bg-*, etc.) - If detected → extract tokens to
tailwind.config.ts, keep utility classes in JSX
- CSS Modules (
--css modules) — Only use when explicitly requested. Requires careful class-to-component mapping. Seeknowledge/css-extraction.mdfor the classification algorithm.
Step 2 — Extract global CSS
From the <style> block, extract these into globals.css:
- All
@importrules - All
@propertydeclarations - The entire
:root { ... }block (design tokens) - All
@layerdeclarations - All
@font-facerules - Base element selectors (
*,html,body,h1-h6,p,a, etc.) - All
@keyframesrules - The fix overrides block (everything with
!importantat the end)
Step 3 — Classify remaining CSS rules
For each remaining CSS rule:
- Parse the selector to extract referenced class names
- Match class names against the component sections from Phase 1
- Classify:
- Single component match → that component's CSS module file
- Multiple component match → globals.css (shared utilities section)
- No match → globals.css
- For
@mediaqueries containing rules for multiple components → split into separate@mediablocks
Step 4 — Tailwind-specific processing (if applicable)
If Tailwind strategy:
- Extract design tokens from
:rootand map totailwind.config.ts:--color-*→theme.extend.colors--font-*→theme.extend.fontFamily--radius-*→theme.extend.borderRadius--shadow-*→theme.extend.boxShadow--space-*→theme.extend.spacing
- Keep Tailwind utility classes as-is in JSX (
className="flex items-center p-4") - Move non-utility custom CSS to globals.css
Step 5 — Design token summary
Output a summary of extracted design tokens:
Colors: 12 tokens (--color-bg, --color-text-primary, --color-accent, ...)
Fonts: 2 families (Inter, Playfair Display)
Spacing: 8px grid base
Radii: 4 tokens (--radius-sm: 4px, --radius-md: 8px, ...)
Shadows: 3 tokens
Motion: 2 tokens (--duration-fast: 150ms, --ease-out: cubic-bezier(...))
Phase 3 — React Component Generation
Load knowledge: Read knowledge/html-to-jsx.md for conversion rules.
Step 1 — HTML → JSX conversion
For each section's HTML fragment, apply all conversion rules from knowledge/html-to-jsx.md:
- Attribute transforms:
class→className,for→htmlFor, etc. - Self-closing tags:
<img>→<img />,<br>→<br />, etc. - Inline styles:
style="..."→style={{ camelCase: 'value' }} - SVG attributes:
stroke-width→strokeWidth, etc. - Comments:
<!-- -->→{/* */} - Remove event handlers: Strip all
on*attributes
Validation step: After conversion, check for common JSX errors:
- Unclosed tags
- Reserved word attributes not converted
- Unescaped
{or}in text content - Adjacent JSX elements without a wrapper
Step 2 — Link conversion
Strategy depends on the input mode:
Mode A (single page): No sub-routes exist, so internal links stay as plain <a> tags:
Internal links → <a href="/pricing">text</a> (relative path, plain <a>)
Anchor links → <a href="#id">text</a> (keep as-is)
External links → <a href="url" target="_blank" rel="noopener noreferrer">text</a>
Mode B/C (multi-page): Sub-routes exist, so use Next.js <Link> for routed pages:
Internal links WITH clone → <Link href="/pricing">text</Link> (import from next/link)
Internal links WITHOUT clone → <a href="/blog">text</a> (plain <a>, add TODO comment)
Anchor links → <a href="#id">text</a> (keep as-is)
External links → <a href="url" target="_blank" rel="noopener noreferrer">text</a>
For internal links to pages NOT in the clone/extracted set (Mode B/C):
{/* TODO: Clone /blog page and add route */}
<a href="/blog">Blog</a>
In ALL modes, convert absolute URLs to relative paths:
https://example.com/pricing→/pricinghttps://example.com/→/https://example.com/#features→/#features
Step 3 — Component file creation
For each section, create the component file:
Shared components → components/shared/[Name].tsx
Page-specific components → components/[page]/[Name].tsx
Each component file structure:
// CSS Modules variant
import styles from './[Name].module.css';
export function [Name]() {
return (
[converted JSX]
);
}
Or for Tailwind:
export function [Name]() {
return (
[converted JSX with Tailwind classes]
);
}
Step 4 — Shared Navbar with active state (Mode B/C)
If Navbar is a shared component across pages, add usePathname() for active link highlighting:
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
export function Navbar() {
const pathname = usePathname();
// ... render nav links with active state based on pathname
}
Step 5 — SVG icon extraction
Scan all components for inline SVGs that qualify as icons:
- Width/height ≤ 48px
- Appears 2+ times across components
- Simple path data (< 500 chars)
Extract qualifying SVGs into components/icons.tsx as named exports.
Replace inline SVGs in components with imports from icons.tsx.
Step 6 — Interactivity restoration
Load knowledge: Read knowledge/interactivity.md for all interactive patterns and detection strategies.
After generating static components, restore interactivity using two sources:
- Runtime detection results (Mode C): The JSON list from Phase 0C.2 tells you exactly which elements are interactive and why. Match each element by its text/classes/position to the corresponding component, and apply the appropriate fixup.
- Class-name pattern matching (Mode A/B, or as supplement): Scan component JSX for known interactive patterns (see
knowledge/interactivity.mdLayer 2).
Process in priority order:
Priority 1 — Navigation interactivity:
- Dropdown menus in Navbar → wrap with
useStateopen/close + click-outside handler - Mobile hamburger menu → toggle state for menu visibility
- These are CRITICAL — broken nav = unusable site
Priority 2 — Anchor links:
<a href="#section-id">→ addonClickwithscrollIntoView({ behavior: 'smooth' })- Simple and high-impact
Priority 3 — Accordions / FAQ:
- Detect repeating question+answer pattern
- Wrap each item with
useStatefor expand/collapse - Add
max-heighttransition for smooth animation
Priority 4 — Tabs:
- Detect tab menu + tab content panels
- Wrap with
useStatefor active tab index - Show/hide panels based on active state
Priority 5 — Forms:
- Detect
<form>,<input>,<textarea>,<select>elements - Add
useStatefor form data,onChangehandlers on inputs - Add
onSubmithandler (log to console + show success state) - Preserve all original styling classes
Priority 6 — Modals / popups:
- Detect hidden overlays with
position: fixed - Find trigger buttons, wire up
useStatetoggle - Add backdrop click-to-close and close button
Priority 7 — Carousels / sliders:
- Detect slider patterns (Webflow
w-slider, custom carousels) - Add
useStatefor current slide, prev/next buttons - CSS
transform: translateXfor slide transitions
For each interactive component:
- Add
'use client';directive at the top - Import necessary hooks (
useState,useRef,useEffect) - Wrap interactive elements with state logic
- Preserve ALL original class names and HTML structure — only add behavior, don't restructure
- Keep non-interactive components as server components
P8 — Post-clone fixups (for dangerouslySetInnerHTML components):
When components use dangerouslySetInnerHTML, apply these fixups to the raw HTML string:
- className → class:
dangerouslySetInnerHTMLrenders raw HTML, NOT JSX. Must useclass,for,tabindex, notclassName,htmlFor,tabIndex. Seeknowledge/html-to-jsx.md"dangerouslySetInnerHTML Rules". - Dead buttons → links: Convert
<button>Sign in</button>to<a href="/signin">Sign in</a>. Convert CTA buttons to links pointing to original site. Seeknowledge/interactivity.mdPattern 10. - Input overlay removal: Remove typewriter overlay (
pointer-events-nonediv with static text over input), restore input visibility, add placeholder. Seeknowledge/interactivity.mdPattern 9. - URL normalization: Convert
href="https://original-site.com/path"tohref="/path"for internal links. Seeknowledge/interactivity.mdPattern 11. - Cursor pointer: Add
cursor: pointeron remaining<button>elements.
What NOT to restore:
- Third-party widgets (chat, analytics) — need API keys
- Complex JS animations (GSAP, Lottie, WebGL) — out of scope
- Backend-dependent features (auth, real-time data)
- Note any skipped interactivity in the final report
Phase 4 — Project Scaffolding & Assembly
Load knowledge: Read knowledge/nextjs-scaffold.md for project templates.
Step 1 — Initialize project
Determine the output directory from Phase 0 Step 3 (either --output path or $(pwd)/results/reactor-[domain]/).
Next.js (default):
# Create in parent of output dir, with output dir name
npx create-next-app@latest [output-dir] \
--typescript \
--eslint \
--app \
--src-dir=false \
--import-alias="@/*" \
--no-turbopack \
[--tailwind] # only if Tailwind detected
Vite + React (if --framework vite):
npm create vite@latest [output-dir] -- --template react-ts
cd [output-dir]
npm install
npm install react-router-dom
[npm install -D tailwindcss postcss autoprefixer] # if Tailwind
Step 2 — Clean boilerplate
Remove default content from:
app/page.tsx(Next.js) orsrc/App.tsx(Vite)app/globals.cssorsrc/index.csspublic/placeholder files
Step 3 — Write all files
Write files in this order (dependencies first):
app/globals.css— Global styles from Phase 2tailwind.config.ts— If Tailwind mode, with extracted design tokensnext.config.mjs— Withimages.remotePatternsfor the original domaincomponents/icons.tsx— Extracted SVG iconscomponents/shared/Navbar.tsx+ CSS module — Shared Navbarcomponents/shared/Footer.tsx+ CSS module — Shared Footercomponents/[page]/[Section].tsx+ CSS modules — All page-specific sectionsapp/layout.tsx— Root layout importing Navbar, Footer, globals.css, fontsapp/page.tsx— Homepage composing its sectionsapp/[route]/page.tsx— Each sub-route composing its sections
Step 4 — Font handling
Detect fonts from the clone HTML:
-
Google Fonts (from
@importor<link>tags):- Convert to
next/font/googleimports inlayout.tsx - Set CSS variables (
--font-sans,--font-display) - Remove the
@importfrom globals.css (Next.js handles it)
- Convert to
-
Custom fonts (from
@font-face):- Keep in globals.css
- If
--download-assetsflag, download.woff2files topublic/fonts/
Step 5 — Asset handling
Default: Keep all image URLs as absolute paths pointing to the original site.
If --download-assets flag:
- Parse all
src,srcset, and CSSurl()values - Download images to
public/assets/ - Download fonts to
public/fonts/ - Rewrite URLs in components and CSS to relative paths (
/assets/image.jpg)
Phase 5 — Build Verification & Report
Step 1 — Build test
cd [output-dir]
npm run build 2>&1
Step 2 — Error diagnosis and fix (up to 3 rounds)
If build fails, diagnose the error:
| Error Pattern | Fix |
|---|---|
class in JSX |
Convert to className |
for in JSX |
Convert to htmlFor |
| Unclosed tag | Add self-closing /> |
style is string |
Convert to style object |
Missing Link import |
Add import Link from 'next/link' |
usePathname in server component |
Add 'use client' directive |
| Image hostname not allowed | Add to next.config.mjs remotePatterns |
| Module not found | Check import paths |
| TypeScript type error | Add appropriate types or // @ts-ignore as last resort |
After each fix, re-run npm run build. Max 3 rounds.
Step 3 — Output report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FRONTEND REACTOR — CONVERSION COMPLETE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Source [N] clone HTML file(s)
Output [output-dir]
Framework Next.js 15 (App Router) + TypeScript
CSS strategy [CSS Modules / Tailwind / Global]
COMPONENTS
Shared: [N] (Navbar, Footer)
Page-specific: [N] (Hero, Features, Pricing, ...)
Icons: [N] SVG icons extracted
ROUTES
/ → app/page.tsx (Hero, Features, Testimonials, CTA)
/pricing → app/pricing/page.tsx (PricingHero, Plans, FAQ)
/about → app/about/page.tsx (AboutHero, Team, Story)
DESIGN TOKENS
Colors: [N] | Fonts: [N] | Spacing: [base]px | Radii: [N] | Shadows: [N]
LINKS
Internal (routed): [N]
External: [N]
Uncloned pages: [list of internal links without clone files]
INTERACTIVITY RESTORED
✓ Dropdown menus: [N]
✓ Mobile nav toggle: [yes/no]
✓ Accordions/FAQ: [N] items
✓ Tabs: [N] sets
✓ Forms: [N] (client-side state)
✓ Modals: [N]
✓ Anchor scroll: [N] links
✗ Skipped: [list of complex interactions not restored]
BUILD STATUS ✓ Passed / ✗ Failed (see errors above)
VALIDATION [Skipped / see below]
TO RUN
cd [output-dir] && npm run dev
TO DEPLOY
cd [output-dir] && vercel deploy
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
If --validate is set (or Mode C), proceed to Phase 6 for Playwright validation.
Phase 6 — Playwright Visual & Interaction Validation
Load knowledge: Read knowledge/playwright-validation.md for all validation scripts and diff algorithms.
This phase runs when --validate is set, or automatically in Mode C (URL input). It requires the original site URL and a successful npm run build from Phase 5.
Step 1 — Start dev server
cd [output-dir]
npm run dev -- -p 3000 &
Wait for localhost:3000 to be ready (poll with socket connect, max 30s).
Step 2 — Visual screenshot comparison
Capture full-page screenshots of both the original site and localhost:3000 at three viewports:
| Viewport | Size |
|---|---|
| Desktop | 1440×900 |
| Tablet | 768×1024 |
| Mobile | 375×812 |
Before capturing, normalize both pages:
- Remove cookie banners/overlays
- Force all animation durations to
0sfor consistent static captures - Scroll to bottom and back to trigger lazy loading
- Force
opacity: 1on animated elements
Generate pixel diff images and calculate similarity scores per viewport.
Step 3 — Interactive element audit
Run the interactive element detection script (same as site-discovery.md Phase A2) on both pages. Compare:
- Count: How many interactive elements exist on each page
- Match by text + position: Pair elements between original and converted
- Signal degradation: Elements that exist but lost interactivity signals (e.g., a link that lost
cursor-pointer, a button that losthas-popup) - Missing elements: Interactive elements on the original that are absent on the converted
Step 4 — Hover state comparison
For the top 10 interactive elements (prioritizing nav links, buttons, CTAs):
- Screenshot each element before hover
- Hover over it, wait 500ms for transitions
- Screenshot after hover
- Pixel-diff the before/after for each element on both sites
- Flag elements where original has a visible hover effect but converted does not
Step 5 — Animation & transition diff
Extract from both pages:
- @keyframes definitions — compare by name; flag missing keyframes
- CSS transitions — compare
transition-property+transition-durationon interactive elements; flag transitions present on original but missing on converted - Animated elements — elements with active
animation-name; flag elements that were animated on the original but are static on the converted
Step 6 — Scroll & sticky element validation
Compare:
scroll-behavior: smoothon<html>- Count of
position: stickyelements - Count of
position: fixedelements
Flag any mismatches.
Step 7 — Auto-fix (up to 2 rounds)
If critical issues are found (visual similarity < 80% on any viewport, OR > 30% of interactive elements missing):
- Missing @keyframes → copy the keyframe definition from the original CSS into
globals.css - Missing hover transitions → find the
:hoverrules for the flagged elements from the original CSS and add them toglobals.css - Missing
cursor: pointer→ addcursor: pointerto the element's CSS class - Missing sticky/fixed positioning → check if
position: sticky/fixedwas dropped during CSS extraction
After each fix round:
- Re-run
npm run build - Re-run the validation pipeline
- Stop if scores improve above thresholds or after 2 rounds
Step 8 — Validation report
Append validation results to the Phase 5 output report:
VALIDATION (Playwright)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Original URL [url]
Dev server localhost:3000
VISUAL FIDELITY
Desktop (1440px): [N]% similarity [✓/△/✗]
Tablet (768px): [N]% similarity [✓/△/✗]
Mobile (375px): [N]% similarity [✓/△/✗]
Diff images saved to: [output-dir]/validation-report/
INTERACTIVE ELEMENTS
Matched: [N]/[M] ([P]%)
Missing: [N] — [list of missing element names]
Degraded: [N] — [list of elements with lost signals]
HOVER STATES
Matching: [N]/[M]
Missing hover: [N] — [list]
Different hover: [N] — [list]
ANIMATIONS & TRANSITIONS
@keyframes matched: [N] | missing: [N] — [list]
Transitions matched: [N] | missing: [N]
Animated elements matched: [N] | missing: [N]
SCROLL BEHAVIOR
Smooth scroll: [✓/✗]
Sticky elements: [✓/✗] (original: [N], converted: [M])
Fixed elements: [✓/✗] (original: [N], converted: [M])
AUTO-FIX APPLIED
[N] fixes applied in [R] rounds
[list of fixes]
OVERALL SCORE [N]/100
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overall score calculation:
- Visual fidelity (desktop): 40 points (proportional to similarity %)
- Interactive element match rate: 25 points
- Hover state match rate: 15 points
- Animation/transition match rate: 15 points
- Scroll behavior match: 5 points
--simple Mode (Non-React Split)
If --simple flag is set, skip React conversion. Instead:
-
Split the clone HTML into:
index.html— Clean HTML with<link rel="stylesheet" href="styles.css">styles.css— All CSS extracted from<style>blockscripts.js— Empty file with TODO comments for interactivity
-
Clean up the HTML:
- Replace
<style>...</style>with<link>tag - Fix any remaining inline styles
- Organize
<head>metadata
- Replace
-
Organize the CSS:
- Add section comments for navigation
- Group by: resets → tokens → typography → layout → components → utilities → overrides
-
Output to:
$(pwd)/results/split-[domain]/(or--outputpath if specified)
Error Handling
- Clone file not found: Ask user for correct path with
AskUserQuestion - Clone HTML is malformed: Attempt best-effort parsing, warn user about sections that couldn't be parsed
npx create-next-appfails: Fall back to manual project scaffolding (write package.json, tsconfig.json by hand)- Build errors persist after 3 rounds: Output the error log and ask user for guidance
- No semantic sections detected: Fall back to splitting
<body>children as numbered sections
Key Principles
- CSS safety first: When unsure which component a CSS rule belongs to, keep it in globals.css. A slightly bloated globals.css is better than broken styles.
- Preserve fidelity: The React project should render identically to the clone HTML. Don't "improve" or "clean up" the visual output.
- Progressive enhancement: Start with static output, then add interactivity (active nav, client-side routing). Don't break what works.
- Minimal dependencies: Only add packages that are strictly necessary. Don't add animation libraries, form libraries, or utility packages unless the clone requires them.