CopyCapy -- The Chill Capybara of Website Cloning
Give me a URL. I'll give you back a production-grade, template-ready codebase that looks like the original but is yours to rebrand for any business.
Philosophy
Like a capybara sitting calmly among crocodiles, CopyCapy approaches website cloning with methodical calm. No panic. No shortcuts. Just a disciplined 5-phase pipeline that has been battle-tested against real production sites.
What CopyCapy does:
- Deep-crawls the target site (every page, not just the homepage)
- Captures screenshots and extracts DOM structure at every scroll position
- Analyzes design patterns, color systems, typography, spacing, and component hierarchy
- Rebuilds everything as a clean, template-ready Next.js codebase
- Makes it configurable via a single
site-config.tsso anyone can rebrand it
What CopyCapy does NOT do:
- Steal assets, images, or copyrighted content (we rebuild, not copy)
- Make pixel-perfect copies (we make inspired-by versions, often better)
- Cut corners on code quality (production-grade or nothing)
Phase 1: Reconnaissance (NEVER SKIP THIS)
This is the most important phase. Rushing past recon is the #1 cause of bad clones.
1a. Full-Site Crawl
browser navigate <target-url>
Extract ALL navigation links, headings, and page structure:
browser console exec "
const links = Array.from(document.querySelectorAll('nav a, header a, footer a'))
.map(a => ({text: a.textContent.trim(), href: a.href}))
.filter(l => l.href && l.text);
const headings = Array.from(document.querySelectorAll('h1, h2, h3'))
.map(h => ({tag: h.tagName, text: h.textContent.trim()}));
JSON.stringify({links, headings}, null, 2);
"
Get total page height to plan screenshot intervals:
browser console exec "document.body.scrollHeight"
1b. Systematic Screenshots
Scroll through the ENTIRE page at ~800-900px intervals. For a 16000px page, that's ~18 screenshots.
browser console exec "window.scrollTo(0, <position>)"
CRITICAL LESSON: Always visit EVERY page listed in the navigation, not just the homepage. The homepage is typically only 30-40% of the site's design system. Pricing pages, about pages, feature pages all have unique layouts.
1c. Dismiss Interference
Cookie banners, popups, and modals will block your screenshots. Dismiss them via JS:
browser console exec "
document.querySelectorAll('[class*=cookie], [class*=banner], [class*=popup], [class*=modal]')
.forEach(el => el.remove());
"
HARD-LEARNED LESSON: Do NOT click "Allow" or "Accept" buttons blindly -- they may trigger navigation (e.g., to a login page). Instead, remove the overlay element via DOM manipulation.
1d. Extract Design Tokens
Pull colors, fonts, spacing from computed styles:
browser console exec "
const body = getComputedStyle(document.body);
const h1 = document.querySelector('h1');
const h1Style = h1 ? getComputedStyle(h1) : {};
JSON.stringify({
bodyFont: body.fontFamily,
bodyColor: body.color,
bgColor: body.backgroundColor,
h1Font: h1Style.fontFamily,
h1Size: h1Style.fontSize,
h1Weight: h1Style.fontWeight,
h1Color: h1Style.color,
}, null, 2);
"
Phase 2: Architecture Design
2a. Template Config Pattern
ALWAYS create a single src/lib/site-config.ts that drives the entire site. This is CopyCapy's signature move -- it's what makes the clone reusable for any business.
The config file should contain:
- Brand: name, tagline, description, logo
- Navigation: full nav tree with dropdowns
- Hero: title, subtitle, CTAs, badges
- Stats: values, labels, icons
- Features: titles, descriptions, colors, CTAs, images
- Testimonials: name, school/company, country, text, highlight
- Pricing: plans, prices, features, badges
- FAQ: questions and answers
- Footer: column structure, legal links
- Theme: color palette mapping
Every component reads from this config. Zero hardcoded content in components.
2b. Tech Stack (Proven Stable)
Next.js 16 -- App Router, static prerendering
TypeScript -- Strict mode
Tailwind CSS 4 -- @tailwindcss/postcss
Framer Motion -- Scroll animations
Lucide React -- Icons
2c. Project Structure
src/
app/
layout.tsx # Root layout (navbar + footer)
page.tsx # Homepage (composes section components)
globals.css # Tailwind + custom animations
pricing/page.tsx # Pricing page
about/page.tsx # About page
features/page.tsx # Features page
contact/page.tsx # Contact page
components/
Navbar.tsx # Nav with dropdowns + mobile menu
Hero.tsx # Hero section
FeatureSection.tsx # Color-coded feature blocks
Testimonials.tsx # Review cards grid
FAQ.tsx # Accordion
Footer.tsx # Multi-column footer
[...] # One component per visual section
lib/
site-config.ts # THE config file (template engine)
Phase 3: Project Setup
CRITICAL: Avoid These Proven Pitfalls
Pitfall 1: create-next-app hangs in non-interactive environments
Manual setup is more reliable:
mkdir project && cd project
npm init -y
npm install next react react-dom typescript @types/react @types/node \
tailwindcss @tailwindcss/postcss postcss lucide-react framer-motion
Pitfall 2: "type": "commonjs" in package.json
npm init -y sets "type": "commonjs" which conflicts with ES module imports. Change to:
"type": "module"
Pitfall 3: output: "standalone" in next.config.ts
Do NOT use output: "standalone" unless deploying to Docker. It breaks next start.
const nextConfig: NextConfig = {};
Pitfall 4: Turbopack dev mode behind reverse proxies
Next.js 16 uses Turbopack by default for next dev. Turbopack's chunk-loading mechanism BREAKS when served through reverse proxies (Cloudflare, nginx, HappyCapy preview, etc.). Symptoms: ChunkLoadError, Failed to load chunk, client-side exceptions on page navigation.
THE FIX -- always use production build for preview:
{
"scripts": {
"dev": "next build && next start --port 3000",
"build": "next build",
"start": "next start --port 3000"
}
}
This builds static HTML + pre-bundled JS. No dynamic chunk loading = no proxy issues.
Pitfall 5: Port zombies When restarting servers, old processes often cling to the port. Always kill by PID:
kill -9 $(lsof -t -i:<port>) 2>/dev/null
sleep 2
# Verify it's dead
ss -tlnp | grep <port> || echo "Port free"
Setup Checklist
tsconfig.json -- jsx: "react-jsx", paths: {"@/*": ["./src/*"]}
postcss.config.mjs -- plugins: {"@tailwindcss/postcss": {}}
next.config.ts -- empty config (no standalone)
package.json -- "type": "module", build+start dev script
Phase 4: Building Components
Section-by-Section Reconstruction
For each visual section identified in recon:
- Create a dedicated component file
- Read all content from
site-config.ts - Match the original's layout (flex/grid), spacing, and color scheme
- Add Framer Motion scroll animations (
whileInView) - Include mock UI elements (don't use placeholder images -- code mock UIs as real components)
Mock UI Pattern
Instead of using placeholder images for app screenshots, BUILD the mock UIs as actual coded components. This:
- Looks better (crisp at any resolution)
- Is fully editable
- Eliminates image asset management
- Makes the template truly self-contained
Example: Instead of a screenshot of a "Question Bank" interface, code a mini Question Bank card with question text, difficulty badges, mark scheme buttons, and a grading result.
Color-Coded Sections
Most modern EdTech/SaaS sites use alternating background colors per feature section. Map these to a theme:
const bgColorMap = {
cyan: "bg-cyan-50",
orange: "bg-orange-50",
purple: "bg-purple-50",
green: "bg-green-50",
};
Dark Sections for AI/Premium Features
AI features and premium sections typically use dark backgrounds with gradient accents:
<section className="bg-gray-950">
<div className="bg-gradient-to-r from-purple-500 to-pink-500 ...">
Animation Considerations
Framer Motion's whileInView and initial={{ opacity: 0 }} work great in real browsers but cause invisible content in automated screenshots. This is fine for the final product -- just be aware when taking verification screenshots.
If you need to verify animations during development:
document.querySelectorAll('[style*=opacity]').forEach(el => el.style.opacity = '1');
document.querySelectorAll('[style*=transform]').forEach(el => el.style.transform = 'none');
Phase 5: Verification & Delivery
Build First, Browse Second
ALWAYS run next build before testing in the browser. Build errors are cheaper to fix than runtime errors.
npx next build 2>&1 | tail -20
All routes should show as (Static) prerendered as static content.
Route Verification
Check every route returns 200:
for route in "/" "/pricing" "/features" "/about" "/contact"; do
curl -s -o /dev/null -w "$route -> %{http_code}\n" http://localhost:3000$route
done
Console Error Check
Browse to each page and verify zero console errors:
browser navigate http://localhost:3000/<page>
browser console view error
Only [INFO] messages should appear. Any [ERROR] or [WARN] about hydration, chunks, or undefined variables must be fixed.
Port Export
/app/export-port.sh 3000
IMPORTANT: Never tell users to use localhost URLs. Always provide the exported public URL.
Reflection Log: Lessons from Battle
These are real failures encountered during the development of CopyCapy, preserved so no capybara makes the same mistake twice.
Lesson 1: The Cookie Banner Trap
What happened: Clicked "Allow" on a cookie banner. The button was actually a link to /auth/login. Lost context, had to re-navigate.
Fix: Never click buttons on overlay elements. Remove them via DOM manipulation instead.
Lesson 2: The Turbopack Proxy Disaster
What happened: Dev server worked perfectly on localhost. Every page returned 200. But through the proxy, all pages except the homepage threw ChunkLoadError. Spent significant time debugging.
Root cause: Turbopack serves JS chunks dynamically via WebSocket/fetch. Reverse proxies mangle the chunk URLs.
Fix: Use production build (next build && next start) which pre-bundles everything as static files.
Lesson 3: The Zombie Port
What happened: Tried to restart the server. EADDRINUSE error. lsof -t -i:3000 returned nothing. But ss -tlnp | grep 3000 showed a zombie next-server process.
Fix: Always kill by exact PID. Always verify with ss -tlnp. Wait 2 seconds between kill and restart.
Lesson 4: The CommonJS vs ESM War
What happened: npm init -y sets "type": "commonjs". All source files use import/export. Build showed warnings about module format mismatch.
Fix: Always change to "type": "module" in package.json immediately after npm init.
Lesson 5: The Invisible Hero
What happened: Hero section rendered as blank space. Text existed in DOM but was invisible.
Root cause: Framer Motion's initial={{ opacity: 0 }} combined with whileInView animations. The automated browser viewport didn't trigger the intersection observer.
Fix: This is normal behavior -- content appears when users scroll in real browsers. For verification screenshots, force visibility via JS.
Lesson 6: The Standalone Trap
What happened: Set output: "standalone" in next.config thinking it would help deployment. Production server returned 500 on all routes.
Root cause: Standalone output restructures the build for Docker-style deployments. next start expects the normal build layout.
Fix: Only use output: "standalone" for Docker deployments. Default to empty config.
Lesson 7: The Glob Copy Failure
What happened: Used cp /tmp/browser-session/screenshot-*.png dest/file.png to copy the latest screenshot. Glob expanded to multiple files, cp failed silently or copied the wrong one.
Fix: Always capture the explicit filename from the browser tool output, or use ls -t | head -1 to get the most recent file.
Quick Reference: The CopyCapy One-Liner
When the user says: "Clone [URL]" or "CopyCapy [URL]"
Execute this pipeline:
1. RECON Browse all pages, screenshot everything, extract structure
2. DESIGN Create site-config.ts with all content, plan components
3. SETUP Manual npm init, install deps, configure (avoid all pitfalls)
4. BUILD One component per section, mock UIs, color-coded themes
5. VERIFY Build, check routes, check console, export port
6. DELIVER <project> tag with framework="nextjs"
Estimated time: 10-15 minutes for a 5-page site.
Output: A complete Next.js project where changing ONE file (site-config.ts) rebrands the entire site for any business.
CopyCapy: Because capybaras get along with everyone... and so does your new template.