website-clone-skill
v1.0.4
Published
Install the website-clone skill for Claude Code, Codex CLI, opencode, Cursor, and Antigravity
Maintainers
Readme
Website Clone Skill
A skill for Claude Code, Codex CLI, opencode, Cursor, and Antigravity that enables cloning any website into a Next.js App Router project.
Packages
| Package | Version | Description |
|---------|---------|-------------|
| website-clone-skill | 1.0.3 ✅ | Recommended - CLI installer with latest fixes |
| create-website-clone | 1.3.1 ⚠️ | Legacy CLI installer (outdated) |
| website-clone-plugin | 1.0.2 | Core plugin with Playwright/Firecrawl utilities |
Note:
website-clone-skillis the actively maintained package with the latest fixes including:
- Node.js 21+ localStorage error fix
- Automatic CSS
url()path rewriting for fonts/assets
Quick Install (Recommended)
# Recommended (latest fixes)
npx website-clone-skill
# Legacy (may have issues on Node.js 21+)
npx create-website-cloneThis will:
- Ask which editor to install for (Claude Code, Codex CLI, opencode, Cursor, Antigravity)
- Copy skill files to the correct location
- Run
npm installfor dependencies - Install Playwright Chromium browser
- Prompt for your Firecrawl API key and save it to your config file (and shell config when possible)
That's it! Restart your editor and ask: "Clone https://example.com"
Architecture
User: "Clone https://example.com"
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Claude (You) │
│ │
│ 0. scaffoldProject() ─► Next.js + shadcn boilerplate │
│ 1. renderPageWithExtraction() ─► Playwright renders HTML │
│ 2. scrapePage() ──────► Firecrawl + download assets │
│ 3. Analyze HTML + screenshot ─► Identify sections │
│ 4. Generate TSX ──────► Write React components │
│ 5. Write files ───────► Save to output directory │
│ │
└─────────────────────────────────────────────────────────────┘Key insight: Claude IS the LLM. The skill provides:
- Playwright for rendering (handles SPAs, JavaScript)
- Firecrawl for clean HTML extraction
- Asset downloading utilities
- File writing utilities
Claude handles:
- Analyzing the DOM structure
- Identifying visual sections
- Generating TSX components
- Writing Tailwind CSS
Manual Installation
Claude Code
git clone https://github.com/improdead/website-cloning-skills.git
cp -r website-cloning-skills/skill ~/.claude/skills/website-clone
cd ~/.claude/skills/website-clone && npm install && npx playwright install chromiumopencode
git clone https://github.com/improdead/website-cloning-skills.git
cp -r website-cloning-skills/skill ~/.config/opencode/skills/website-clone
cd ~/.config/opencode/skills/website-clone && npm install && npx playwright install chromiumCodex CLI
git clone https://github.com/improdead/website-cloning-skills.git
cp -r website-cloning-skills/skill ~/.codex/skills/website-clone
cd ~/.codex/skills/website-clone && npm install && npx playwright install chromiumCursor
git clone https://github.com/improdead/website-cloning-skills.git
mkdir -p .cursor/rules
cp website-cloning-skills/skill/SKILL.md .cursor/rules/website-clone.md
cp -r website-cloning-skills/skill ./website-clone-skill
cd website-clone-skill && npm install && npx playwright install chromiumAntigravity (workspace)
git clone https://github.com/improdead/website-cloning-skills.git
cp -r website-cloning-skills/skill .agent/skills/website-clone
cd .agent/skills/website-clone && npm install && npx playwright install chromiumAntigravity (global)
git clone https://github.com/improdead/website-cloning-skills.git
mkdir -p ~/.gemini/antigravity/global_skills
cp -r website-cloning-skills/skill ~/.gemini/antigravity/global_skills/website-clone
cd ~/.gemini/antigravity/global_skills/website-clone && npm install && npx playwright install chromiumUninstall
# Claude Code
rm -rf ~/.claude/skills/website-clone
# opencode
rm -rf ~/.config/opencode/skills/website-clone
# Codex CLI
rm -rf ~/.codex/skills/website-clone
# Cursor
rm -f .cursor/rules/website-clone.md
rm -rf ./website-clone-skill
# Antigravity (workspace)
rm -rf .agent/skills/website-clone
# Antigravity (global)
rm -rf ~/.gemini/antigravity/global_skills/website-cloneFirecrawl API Key
If you skipped the API key prompt during install, set it manually:
# macOS/Linux
export FIRECRAWL_API_KEY="fc_your_key"
# Save to config file used by the skill
mkdir -p ~/.config/website-clone-skill
echo 'FIRECRAWL_API_KEY="fc_your_key"' >> ~/.config/website-clone-skill/.env
# Add to shell config for persistence
echo 'export FIRECRAWL_API_KEY="fc_your_key"' >> ~/.zshrc
# Windows
setx FIRECRAWL_API_KEY "fc_your_key"
# Or add to: %APPDATA%\website-clone-skill\.envGet your key at https://firecrawl.dev
Quickstart
- Run
npx website-clone-skilland follow the prompts - Restart your editor
- Ask: "Clone https://example.com"
- Run the clone:
cd output
npm install
npm run devUsage
Claude Code / opencode
- Trigger the skill with
/website-cloneor “Clone https://example.com”. - Follow the step-by-step guides in
workflow/(start atstep0-scaffold.md). - The skill writes a Next.js project to your chosen output directory.
Cursor
- Paste
SKILL.mdinto.cursor/rules/website-clone.md(see Installation). - Ask: “Clone https://example.com” or “Use website-clone skill”.
- If Cursor doesn’t auto-open linked files, open the referenced
workflow/orrules/file manually.
Antigravity
- Start a conversation and mention the skill: “Use the website-clone skill to clone https://example.com”.
- Antigravity will load
SKILL.mdand follow linked files inworkflow/andrules/.
Programmatic usage
See the Example Usage section below for a full script.
How It Works
When a user asks to clone a website, Claude:
- Scaffolds a Next.js 15 + Tailwind 4 + shadcn/ui project
- Renders the page using Playwright (captures JavaScript-rendered content)
- Scrapes assets and HTML using Firecrawl
- Analyzes the HTML + screenshot to identify sections
- Generates TSX components for each section
- Writes files to the output directory
Plugin API
renderPage(options)
Renders a page with Playwright and captures HTML, screenshot, and network requests.
import {renderPage} from './plugin';
const result = await renderPage({
url: 'https://example.com',
viewport: {width: 1440, height: 900},
waitUntil: 'networkidle',
extraWaitMs: 2000,
});
// result.html - Full rendered HTML
// result.screenshot - Buffer with PNG screenshot
// result.requests - Array of network requestsscrapePage(options)
Scrapes assets using Firecrawl and downloads images/fonts.
import FirecrawlApp from '@mendable/firecrawl-js';
import {scrapePage, createProjectStructure, getFirecrawlApiKey} from './plugin';
const firecrawl = new FirecrawlApp({apiKey: getFirecrawlApiKey()});
await createProjectStructure('./output');
const result = await scrapePage({
url: 'https://example.com',
renderResult: renderResult,
firecrawlClient: firecrawl,
outputDir: './output',
});
// result.assets - Downloaded assets with local paths
// result.html - Playwright HTML
// result.firecrawlHtml - Firecrawl clean HTMLgetFirecrawlApiKey()
Loads the Firecrawl API key from the environment or the skill config file.
import {getFirecrawlApiKey} from './plugin';
const apiKey = getFirecrawlApiKey();writeFile(path, content)
Writes a file to disk, creating directories as needed.
import {writeFile} from './plugin';
await writeFile('./output/src/components/hero.tsx', heroTsxCode);saveScreenshot(buffer, path)
Saves a screenshot buffer to a file.
import {saveScreenshot} from './plugin';
await saveScreenshot(result.screenshot, './output/screenshot.png');renderPageWithExtraction(options)
Enhanced render that automatically extracts fonts and colors.
import {renderPageWithExtraction} from './plugin';
const result = await renderPageWithExtraction({
url: 'https://example.com',
viewport: {width: 1440, height: 900},
});
// All standard render results plus:
// result.fonts.googleFontsImports - Google Fonts URLs found
// result.fonts.fontFamilies - Font family names used
// result.colors.hex - All hex colors found
// result.colors.rgb - All RGB colors found
// result.colors.cssVariables - CSS custom properties for colors
// result.stylesheets - All CSS content capturedextractComputedStyles(options)
Extract exact computed CSS values from rendered elements.
import {extractComputedStyles} from './plugin';
const styles = await extractComputedStyles({
url: 'https://example.com',
selectors: ['h1', '.hero-button', 'nav a'],
properties: ['color', 'background-color', 'font-family', 'font-size'],
});
// Returns: [{ selector: 'h1', styles: { 'font-size': '160px', 'color': 'rgb(60, 47, 18)' } }]extractFonts(html, css?)
Extract font information from HTML/CSS content.
import {extractFonts} from './plugin';
const fonts = extractFonts(htmlContent, cssContent);
// fonts.googleFontsImports - Google Fonts import URLs
// fonts.fontFamilies - Font family names (filtered)
// fonts.fontFaceDeclarations - @font-face rulesextractColors(content)
Extract all color values from content.
import {extractColors} from './plugin';
const colors = extractColors(htmlContent + cssContent);
// colors.hex - Hex colors like #F5F3ED
// colors.rgb - RGB/RGBA colors
// colors.hsl - HSL/HSLA colors
// colors.cssVariables - CSS custom properties that contain colorscompareScreenshots(original, clone, diffPath?)
Compare two screenshots for visual similarity.
import {compareScreenshots} from './plugin';
const comparison = await compareScreenshots(
originalBuffer,
cloneBuffer,
'./screenshots/diff.png'
);
// comparison.similarity - 0 to 1, where 1 is identical
// comparison.diffPixels - Number of different pixels
// comparison.totalPixels - Total pixels compared
// comparison.diffImagePath - Path to diff image (if generated)Note: Requires optional pixelmatch and pngjs packages.
generateThemeBlock(options)
Generate Tailwind v4 @theme block from extracted design tokens.
import {generateThemeBlock} from './plugin';
const themeBlock = generateThemeBlock({
fonts: extractedFonts,
colors: extractedColors,
});
// Returns CSS @theme block for globals.cssgenerateGoogleFontsUrl(fonts)
Generate a Google Fonts import URL.
import {generateGoogleFontsUrl} from './plugin';
const url = generateGoogleFontsUrl([
{name: 'Inter', weights: [400, 500, 600, 700]},
{name: 'Caveat', weights: [400, 700]},
]);
// Returns: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Caveat:wght@400;700&display=swap'scaffoldProject(outputDir, templateDir)
Copy boilerplate files to create a complete Next.js 15 + shadcn/ui project.
import {scaffoldProject, createProjectStructure} from './plugin';
await createProjectStructure('./output');
await scaffoldProject('./output', './templates');
// Copies: package.json, next.config.ts, tsconfig.json, components.json, etc.installShadcnComponents(projectDir, components)
Install additional shadcn/ui components using the CLI.
import {installShadcnComponents} from './plugin';
await installShadcnComponents('./output', [
'button', 'card', 'dialog', 'dropdown-menu', 'input'
]);generateAgentsMd(options)
Generate an AGENTS.md file documenting the cloned project.
import {generateAgentsMd, writeFile} from './plugin';
const agentsMd = generateAgentsMd({
sourceUrl: 'https://example.com',
siteName: 'Example Site',
sections: ['Navigation', 'Hero', 'Features', 'Footer'],
});
await writeFile('./output/AGENTS.md', agentsMd);Example Usage
import FirecrawlApp from '@mendable/firecrawl-js';
import {
createProjectStructure,
scaffoldProject,
renderPageWithExtraction,
scrapePage,
saveScreenshot,
generateAgentsMd,
writeFile,
getFirecrawlApiKey,
} from './plugin';
const outputDir = './output';
const templateDir = './templates'; // Use absolute path if running elsewhere
const sourceUrl = 'https://example.com';
// 0. Scaffold Next.js + shadcn/ui
await createProjectStructure(outputDir);
await scaffoldProject(outputDir, templateDir);
// 1. Render with extraction
const render = await renderPageWithExtraction({url: sourceUrl});
await saveScreenshot(render.screenshot, `${outputDir}/screenshots/original.png`);
// 2. Scrape assets
const firecrawl = new FirecrawlApp({apiKey: getFirecrawlApiKey()});
const scrape = await scrapePage({
url: sourceUrl,
renderResult: render,
firecrawlClient: firecrawl,
outputDir,
});
// 3. Analyze HTML + screenshot (Claude does this)
// ... analyze scrape.html to find sections ...
// ... generate TSX for each section ...
// 4. Write project files
await writeFile(`${outputDir}/src/app/page.tsx`, pageTsx);
await writeFile(`${outputDir}/src/app/globals.css`, globalsCss);
await writeFile(`${outputDir}/src/components/sections/hero.tsx`, heroTsx);
// 5. Generate AGENTS.md
const agentsMd = generateAgentsMd({
sourceUrl,
siteName: 'Example Site',
sections: ['Navigation', 'Hero', 'Footer'],
});
await writeFile(`${outputDir}/AGENTS.md`, agentsMd);Output Structure
output/
├── package.json
├── next.config.ts
├── tsconfig.json
├── components.json
├── postcss.config.mjs
├── eslint.config.mjs
├── .gitignore
├── public/
│ ├── assets/
│ └── fonts/
├── src/
│ ├── app/
│ │ ├── layout.tsx
│ │ ├── globals.css
│ │ └── page.tsx
│ ├── components/
│ │ ├── ui/
│ │ │ └── button.tsx
│ │ └── sections/
│ │ ├── navigation.tsx
│ │ ├── hero.tsx
│ │ └── footer.tsx
│ └── lib/
│ └── utils.ts
├── screenshots/
│ └── original.png
└── AGENTS.mdRunning the Clone
cd output
npm install
npm run devOpen http://localhost:3000 to view the clone.
No Anthropic API Key Needed
This skill runs inside Claude Code/opencode, so Claude IS the AI. The skill provides utilities for:
- Rendering pages (Playwright)
- Scraping content (Firecrawl)
- Downloading assets
- Writing files
Claude uses its own intelligence to:
- Analyze the HTML structure
- Identify visual sections
- Generate clean TSX components
- Apply appropriate Tailwind classes
