# Copycapy

> Clone any website into a production-grade, template-ready codebase. Give it a URL and CopyCapy reverse-engineers the entire site: browses every page, captures screenshots, extracts structure, then rebuilds it as a clean Next.js project with a single config file that lets you rebrand it for any business. The chill capybara of website cloning -- adapts to anything, panics about nothing.

- Skill: `ndpvt-web/copycapy` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add ndpvt-web/copycapy`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ndpvt-web/copycapy/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: ndpvt-web (https://skillmd.com/u/ndpvt-web)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ndpvt-web/copycapy

---


# 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:**
1. Deep-crawls the target site (every page, not just the homepage)
2. Captures screenshots and extracts DOM structure at every scroll position
3. Analyzes design patterns, color systems, typography, spacing, and component hierarchy
4. Rebuilds everything as a clean, template-ready Next.js codebase
5. Makes it configurable via a single `site-config.ts` so 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:

```javascript
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:

```javascript
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.

```javascript
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:

```javascript
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:

```javascript
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:
```bash
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:
```json
"type": "module"
```

**Pitfall 3: `output: "standalone"` in next.config.ts**
Do NOT use `output: "standalone"` unless deploying to Docker. It breaks `next start`.
```typescript
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:**
```json
{
  "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:
```bash
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:

1. Create a dedicated component file
2. Read all content from `site-config.ts`
3. Match the original's layout (flex/grid), spacing, and color scheme
4. Add Framer Motion scroll animations (`whileInView`)
5. 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:

```typescript
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:

```jsx
<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:
```javascript
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.

```bash
npx next build 2>&1 | tail -20
```

All routes should show as `(Static) prerendered as static content`.

### Route Verification

Check every route returns 200:

```bash
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:

```bash
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

```bash
/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.*

