Extract and recreate React components from any website
npm install clone-react-skillReverse engineer and extract React components from any production website using Electron-powered visual selection.
Traditional component extraction from HTML alone requires multiple iterations:
1. Parse HTML structure
2. Generate component
3. View in browser
4. Notice layout issues
5. Fix and repeat
This tool combines BOTH data sources upfront:
- HTML provides exact structure (classes, nesting, props)
- Screenshot provides visual verification (spacing, colors, alignment)
Result: Accurate extraction on first try.
```
/clonereact https://example.com
↓
Electron browser opens (Chromium)
↓
Injection: selector-ui.html + extractor.js
↓
User Interface:
- Hover → Blue outline highlights element
- Click → Purple outline selects element
- Click "Extract Component" button
↓
Extraction Process:
1. Access React Fiber tree (__reactFiber$)
2. Walk component tree (props, state, children)
3. Capture element screenshot (canvas → base64)
4. Get computed CSS styles
5. Extract raw HTML as fallback
↓
Send via IPC (preload.js bridge)
↓
main.js writes /tmp/clonereact-output.json
↓
Electron closes, handler.sh continues
↓
generate-component.js processes JSON
↓
Output files:
- ComponentName.tsx (React code)
- ComponentName.css (Styles)
- ComponentName.json (Full data)
- README.md (Usage docs)
1. Launch Electron browser - Opens target URL in a chromium window
2. Visual element picker - Hover and click to select elements
3. Extract both HTML + screenshot - Captures structure AND visual appearance
4. Access React Fiber tree - If React detected, extracts component internals
5. Generate React components - Creates standalone .tsx/.jsx files with styles
`bashClone to skills folder
git clone https://github.com/jasonkneen/clone-react-skill ~/.claude/skills/clonereact
$3
`bash
Global install
npm install -g clone-react-skill
clonereact https://stripe.comOr via npx (no install)
npx clone-react-skill https://stripe.com
`$3
- Node.js 18+
- macOS, Linux, or Windows
First run downloads Electron (~200MB) via
cluso-inspector dependency.Usage
$3
`bash
/clonereact https://stripe.com
/clonereact https://airbnb.com --typescript
/clonereact https://github.com --output ./my-components --depth 10
`What happens:
1. Electron browser opens to the URL
2. Black toolbar appears at top with instructions
3. Hover over elements → blue highlight appears
4. Click element → purple outline marks selection
5. Click "Extract Component" → closes and generates files
6. Click "Cancel" → aborts
$3
-
--output - Output directory (default: ./cluso-inspect/cloned)
- --depth - Component tree depth (default: 5)
- --typescript - Generate .tsx instead of .jsxOutput
Each extraction creates a timestamped subfolder with meaningful names:
`
./cluso-inspect/cloned/
└── StripePricingTable_20260111_151030/
├── StripePricingTable.tsx
├── StripePricingTable.css
├── StripePricingTable.json
├── StripePricingTable-screenshot.png
└── README.md
`For each extracted element:
ComponentName.tsx
`tsx
import React from 'react';
import './ComponentName.css';export function ComponentName() {
return (
// Reconstructed JSX from Fiber tree
);
}
`ComponentName.css
`css
.componentname {
/ Extracted computed styles /
}
`ComponentName.json
`json
{
"selector": ".original-class",
"isReact": true,
"reactVersion": "18.2.0",
"component": { / Fiber tree / },
"screenshot": "data:image/png;base64,...",
"html": "...",
"styles": { / computed CSS / }
}
`README.md - Usage instructions and metadata
Visual Selection UI
Toolbar (top center):
- Shows selection count
- "Clear" button - deselect all
- "Extract Component" button - process and generate
- "Cancel" button - abort
Hover state:
- Blue outline highlights element under cursor
- Label shows tag name + class
Selected state:
- Purple outline marks selected elements
- Click again to deselect
What Gets Extracted
$3
- Component tree structure
- Props (names, values, types)
- State (initial values, hooks)
- Computed CSS styles
- Element screenshot
- Raw HTML fallback$3
- Computed CSS styles
- Element screenshot
- Raw HTML structure
- No component tree (obviously)Advantages Over Manual Extraction
| Manual | With Electron |
|--------|---------------|
| Guess CSS selector | Visual click selection |
| Copy/paste HTML | Auto-extracted |
| No screenshot | Screenshot included |
| Iterate blindly | See it as you extract |
File Structure
`
~/.claude/skills/clonereact/
├── SKILL.md # Skill definition
├── handler.sh # CLI entry point (calls cluso-inspector)
├── README.md # This file
├── generate-component.js # JSON → React component generator
└── package.json # Dependenciescluso-inspector (separate package)
Live: npx cluso-inspector
Dev: ~/Documents/GitHub/flows/cluso/cluso-inspector/
`Technical Details
$3
main.js - Electron Main Process
- Creates BrowserWindow (1440x900)
- Loads target URL
- Injects selector UI after page load
- Handles IPC from renderer
- Writes extraction data to /tmp/
- Exits when complete
preload.js - Secure IPC Bridge
- Uses contextBridge for security
- Exposes only safe methods:
-
window.clonereact.sendExtraction(data)
- window.clonereact.cancel()
- window.clonereact.getConfig()selector-ui.html - Visual Picker Overlay
- Injected into target page DOM
- Black toolbar at top (fixed position, z-index 999999)
- Blue highlight on hover
- Purple outline on selection
- Buttons: Clear, Extract, Cancel
- Calls
window.__REACT_COMPONENT_EXTRACTOR__ when extractingextractor.js - React Fiber Extractor
-
findFiberNode(element) - Locates __reactFiber$ key
- walkFiberTree(fiber, depth) - Recursively builds component tree
- extractProps(fiber) - Serializes props (functions → stubs)
- extractState(fiber) - Extracts hooks/state
- extractStyles(element) - Gets computed CSS
- captureElementScreenshot(element) - Canvas-based screenshot
- getSelector(element) - Generates CSS selector
- Returns complete extraction object$3
- Context isolation enabled
- No nodeIntegration
- Preload script for safe IPC
- Web security maintained
$3
`
User clicks element
↓
extractor.js accesses React Fiber
↓
Captures screenshot + styles
↓
Sends via IPC to main process
↓
Writes JSON to /tmp/
↓
handler.sh reads JSON
↓
generate-component.js creates files
`$3
The Electron app sends this JSON structure via IPC:
`json
{
"success": true,
"url": "https://example.com",
"timestamp": "2026-01-11T08:00:00.000Z",
"extractions": [
{
"selector": "div.chat-input > form",
"isReact": true,
"reactVersion": "18.2.0",
"component": {
"name": "ChatInput",
"type": "component",
"props": {
"className": "input-wrapper",
"onSubmit": "[Function: handleSubmit]"
},
"state": {
"hooks": [
{ "value": "", "queue": "[Queue]" }
]
},
"children": [ / nested components / ],
"depth": 0
},
"html": "...",
"styles": {
"display": "flex",
"padding": "16px",
"borderRadius": "12px",
"backgroundColor": "rgb(24, 24, 27)"
},
"screenshot": "data:image/png;base64,iVBORw0KG...",
"dimensions": {
"width": 600,
"height": 120,
"top": 800,
"left": 100
},
"meta": {
"tagName": "div",
"id": "chat-input-container",
"classes": ["chat-input", "rounded-lg"]
}
}
]
}
`$3
For each extracted component, generates:
ComponentName.tsx (or .jsx)
`tsx
import React from 'react';
import './ComponentName.css';interface ComponentNameProps {
className?: string;
onSubmit?: () => void;
}
export function ComponentName({ }: ComponentNameProps) {
return (
{/ Reconstructed JSX from Fiber tree /}
);
}
`ComponentName.css
`css
.componentname {
display: flex;
padding: 16px;
border-radius: 12px;
background-color: rgb(24, 24, 27);
}
`ComponentName.json - Full extraction metadata (for debugging/reference)
README.md - Usage instructions, source URL, extraction timestamp
Troubleshooting
$3
"Electron not found"
`bash
cd ~/.claude/skills/clonereact/electron-app
npm install
`"npx: command not found"
- Install Node.js 18+ from nodejs.org
- Verify:
node --version and npm --version"Permission denied" on handler.sh
`bash
chmod +x ~/.claude/skills/clonereact/handler.sh
`$3
"No React Fiber found"
- Site doesn't use React (check console for framework)
- React DevTools may be disabled in production
- Try a different page/route
- Still extracts HTML + styles + screenshot
Electron window blank/white screen
- Wait 2-3 seconds for page to load
- Check console for errors
- Some sites block Electron user-agent
- Try adding User-Agent override in main.js
Screenshot is blank or black
- Element may use canvas/WebGL rendering
- Try extracting parent container instead
- Some elements render async (wait longer)
- Check if element is actually visible on screen
Styles don't match original
- Some styles from CSS-in-JS (styled-components, emotion)
- Hover/active states not captured
- Media queries not evaluated
- Screenshot shows actual rendered appearance (trust it)
Component won't render after extraction
- Event handlers are stubs (implement manually)
- Missing data/state from parent
- Check props interface - may need data passed in
- Review .json file for full Fiber tree structure
$3
Can't select element (clicking does nothing)
- Element may be covered by another (z-index)
- Try clicking parent container
- Check browser console for errors
Selected wrong element
- Click "Clear" in toolbar to deselect
- Select again more precisely
- Use browser DevTools to find exact selector first
Multiple elements selected accidentally
- Click "Clear" to start over
- Currently single-select only (multi-select coming)
$3
"Error generating component"
- Check /tmp/clonereact-output-*.json for raw data
- Verify JSON is valid
- May have non-serializable objects in Fiber tree
Generated code has TypeScript errors
- Run with
--typescript flag for proper types
- Check that react/react-dom are in dependencies
- Some props may be typed as any (refine manually)CSS classes not applying
- Ensure Tailwind is configured if using Tailwind classes
- Check for CSS-in-JS dependencies (styled-components)
- Computed styles are extracted as vanilla CSS
Examples
$3
Extract Stripe navigation:
`bash
/clonereact https://stripe.com
Opens browser, click nav bar, extract
`Extract with TypeScript:
`bash
/clonereact https://linear.app --typescript
Click form, generates .tsx files
`Custom output:
`bash
/clonereact https://vercel.com --output ~/Desktop/components
`$3
Extract Airbnb search bar:
`bash
/clonereact https://airbnb.com --typescript --depth 8
Wait for page load
Click the search input component
Extract generates full search bar with calendar picker structure
`Extract GitHub repo card:
`bash
/clonereact https://github.com/trending --output ./github-components
Click on a repository card
Gets card layout, avatar, stats, description
`Extract Notion page element:
`bash
/clonereact https://notion.so --typescript --depth 10
Click on a block (heading, list, etc)
Extracts Notion's component structure
`Best Practices
$3
DO:
- ✅ Click the outermost container of the component you want
- ✅ Wait for page to fully load before selecting
- ✅ Select parent containers (not individual text/icons)
- ✅ Use browser DevTools to inspect first if unsure
DON'T:
- ❌ Select individual text nodes or icons
- ❌ Select nested children when you want the parent
- ❌ Click immediately after page load (wait 2-3s)
$3
| Depth | Use Case |
|-------|----------|
| 3-5 | Simple components (buttons, cards) |
| 5-8 | Medium complexity (forms, modals) |
| 8-12 | Complex components (data tables, dashboards) |
| 12+ | Full page sections (may generate huge files) |
Rule of thumb: Start with 5, increase if nested components are missing.
$3
Single component:
`bash
/clonereact https://example.com --output ./components/Button
`Multiple components from same site:
`bash
Extract nav
/clonereact https://example.com --output ./components/NavExtract footer (opens new Electron instance)
/clonereact https://example.com --output ./components/Footer
`$3
Generated components are 85-95% complete. You'll need to:
1. Implement event handlers
- Replace
[Function: handleClick] stubs
- Add actual onClick/onSubmit logic2. Add data/state management
- Hook up real API calls
- Connect to Redux/Context if needed
3. Refine TypeScript types
- Generated interfaces use
any for complex props
- Add proper types for functions and objects4. Test responsive behavior
- Extracted styles are from desktop viewport
- Add mobile breakpoints if needed
5. Review dependencies
- Check package.json for missing deps
- May need framer-motion, styled-components, etc.
Limitations
Cannot extract:
- Server-side logic
- Event handler implementations (extracted as stubs)
- Dynamic imports
- Redux/Zustand store logic (only initial values)
May not work on:
- Sites that disable DevTools
- Heavily obfuscated builds
- React Native (different Fiber structure)
- Shadow DOM components
Legal & Ethics
✅ Use for:
- Your own sites
- Open source projects (learning)
- With explicit permission
- Educational purposes
❌ Don't use for:
- Stealing proprietary code
- Violating ToS
- Commercial use without permission
Advanced Usage
$3
Check raw extraction data:
`bash
Extraction data is written to /tmp/clonereact-output-.json
Before it's deleted, you can inspect it:
/clonereact https://example.com --output ./test
In another terminal while Electron is open:
ls -lt /tmp/clonereact-output-* | head -1
cat /tmp/clonereact-output-12345.json | jq '.extractions[0].component'
`$3
The extractor accesses these Fiber node properties:
`javascript
element.__reactFiber$abc123 = {
type: ComponentFunction, // Component constructor
memoizedProps: { / props / }, // Current props
memoizedState: { / state / }, // Current state/hooks
child: FiberNode, // First child
sibling: FiberNode, // Next sibling
stateNode: HTMLElement, // DOM node
key: "unique-key", // React key
elementType: { name: "Button" } // Component name
}
`$3
Uses HTML5 Canvas API:
`javascript
canvas.width = rect.width * devicePixelRatio
canvas.height = rect.height * devicePixelRatio
// Returns base64 PNG
`Limitations:
- Canvas/WebGL content may not capture
- Cross-origin images blocked (CORS)
- Some CSS effects lost (filters, blend modes)
$3
Extracts these computed style properties:
- Layout: display, position, width, height, flex, grid
- Spacing: margin, padding, gap
- Visual: background, border, borderRadius, color
- Typography: fontSize, fontFamily, fontWeight
Not extracted:
- Pseudo-elements (::before, ::after)
- Pseudo-classes (:hover, :active)
- CSS animations/transitions
- Media queries
Use the screenshot to verify visual accuracy.
Performance
Typical extraction times:
- Simple component: 2-3 seconds
- Complex component: 5-8 seconds
- Full page section: 10-15 seconds
Bottlenecks:
- Page load time (network)
- Screenshot capture (rendering)
- Fiber tree walk (depth × children)
Optimization:
- Use lower --depth for faster extraction
- Select smaller containers
- Close DevTools in Electron window
Security Notes
What the Electron app does:
- Loads target URL in isolated window
- Injects JavaScript into page DOM
- Reads React internals and DOM structure
- Captures screenshot using Canvas API
- Sends data via IPC (no network requests)
What it does NOT do:
- Execute code on your behalf
- Send data to external servers
- Persist cookies/sessions
- Modify the target website
- Run with elevated permissions
Safe for:
- Public websites
- Development/testing environments
- Your own applications
Use caution with:
- Sites with sensitive data (logged in accounts)
- Banking/financial sites
- Sites with restrictive ToS
Contributing
Ideas for improvements:
- [ ] Multi-select with Cmd/Ctrl
- [ ] Export as Storybook stories
- [ ] Auto-detect lazy-loaded components
- [ ] Convert to Tailwind classes option
- [ ] Extract animations/transitions
- [ ] Support for Shadow DOM
- [ ] Better screenshot capture (use Electron's native API)
- [ ] CSS-in-JS detection and extraction
- [ ] Generate unit tests from component structure
Credits
Inspired by: David Fant's "How to Steal Any React Component" (fant.io/react/)
Built for: Claude Code
Key innovation: Combines HTML structure + screenshot for one-shot accurate extraction
Architecture pattern: Electron + Visual Selection + React Fiber Access
Documentation
- README.md (this file) - User guide and quick start
- ARCHITECTURE.md - Complete technical documentation
- System overview and architecture layers
- Data flow diagrams
- React Fiber internals explained
- Security model details
- Performance characteristics
- Code generation process
- Future improvements and known limitations
Key Files Reference
| File | Lines | Purpose |
|------|-------|---------|
| handler.sh | 110 | CLI entry point, Electron launcher |
| electron-app/main.js | 115 | Electron window + IPC management |
| electron-app/preload.js | 16 | Secure IPC bridge |
| electron-app/selector-ui.html | 200+ | Visual picker overlay UI |
| electron-app/extractor.js | 244 | React Fiber + screenshot extraction |
| generate-component.js | 270+ | JSON → React component generator |
License
MIT - Use responsibly and ethically.
Changelog
$3
- Separated cluso-inspector into standalone npm package
- Added dev/live mode switching
- Improved component naming (domain + content based)
- Each component now gets unique timestamped folder
- Updated default output to ./cluso-inspect/cloned`