# Clone Website

> 网站克隆技能。输入任意 URL，自动逆向工程为目标网站的像素级克隆。 触发方式：用户说 "clone <url>"、"逆向这个网站"、"仿制 <url>"、"把这个网站做成代码" 等。 工作流程：截图分析 → 设计 token 提取 → 组件规范生成 → 并行构建 → Next.js 项目输出。 适用于：网站迁移、源码恢复、学习现代网站实现方式。 前置要求：需要浏览器自动化工具（Playwright CLI 或 browser 工具）。

- Skill: `gszyboy/clone-website` (Agent Skill)
- Install (CLI): `npx skillmds@latest add gszyboy/clone-website`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gszyboy/clone-website/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: gszyboy (https://skillmd.com/u/gszyboy)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/gszyboy/clone-website

---


# Clone Website Skill

逆向工程并重建任意网站为像素级克隆。

## 概述

给定一个目标 URL，自动完成：
1. 截图分析 + 设计 token 提取
2. 交互行为探测（滚动、点击、悬停）
3. 组件规范文档生成
4. 并行 AI 构建
5. 视觉 QA 对比

**输出**：Next.js + TypeScript + Tailwind CSS + shadcn/ui 项目

## ⚠️ 前置要求

**必须先检查浏览器自动化工具**。按以下优先级检查：

1. **Playwright CLI** - `playwright-cli open <url>`
2. **Browser MCP** - `skill_mcp(mcp_name="browser", tool_name="...")`
3. **其他浏览器工具**

如果没有任何浏览器工具可用，**立即告知用户**：
```
"网站克隆需要浏览器自动化工具。请先安装/配置以下之一：
- Playwright CLI: npm install -g playwright-cli
- Browserbase MCP
- 或确认你已配置的浏览器 MCP 工具"
```

## Step 1: 预检（Pre-Flight）

### 1.1 URL 验证
解析 `$ARGUMENTS` 为一个或多个 URL，验证格式有效。

### 1.2 环境检查
```
npm run build
```
确保 Next.js + shadcn/ui + Tailwind v4 脚手架已就绪。

### 1.3 目录准备
创建必要目录：
```
docs/research/
docs/research/components/
docs/design-references/
public/images/
public/videos/
public/seo/
scripts/
```

### 1.4 项目设置
如果项目未初始化，告知用户先执行：
```bash
git clone https://github.com/JCodesMore/ai-website-cloner-template.git my-clone
cd my-clone
npm install
```

## Step 2: 侦察阶段（Reconnaissance）

**必须用 Playwright CLI 访问目标 URL**。

### 2.1 截图
- **桌面端**：1440px 整页截图
- **移动端**：390px 整页截图
- 保存到 `docs/design-references/`

```bash
playwright-cli open <url>
playwright-cli resize 1440 900
playwright-cli screenshot --filename=desktop.png
playwright-cli resize 390 844
playwright-cli screenshot --filename=mobile.png
playwright-cli close
```

### 2.2 全局信息提取

**字体**：
- 检查 `<link>` 标签中的 Google Fonts
- 用 `playwright-cli eval` 提取关键元素的 font-family
- 记录：family, weight, style

**颜色**：
- 提取页面 CSS 变量中的颜色
- 更新 `src/app/globals.css` 的 `:root` 和 `.dark`

**Favicon & Meta**：
- 下载 favicons, apple-touch-icons, OG images 到 `public/seo/`
- 更新 `layout.tsx` metadata

**全局交互模式**：
- 检查自定义滚动条
- 检查 scroll-snap
- 检查 smooth scroll 库（Lenis: `.lenis` class）
- 检查全局 keyframe 动画

### 2.3 强制交互探测

**滚动扫描**：
```bash
playwright-cli mousewheel 0 100  # 慢速滚动，记录 header 变化
```

**点击扫描**：
```bash
playwright-cli click <element-ref>
playwright-cli snapshot  # 记录行为
```

**悬停扫描**：
```bash
playwright-cli hover <element-ref>
# 记录 hover 状态的颜色/阴影/缩放变化
```

**响应式扫描**：
```bash
playwright-cli resize 1440 900
playwright-cli snapshot
playwright-cli resize 768 1024
playwright-cli snapshot
playwright-cli resize 390 844
playwright-cli snapshot
```

### 2.4 页面拓扑
映射页面每个区块：
- 视觉顺序
- fixed/sticky vs flow content
- z-index 层
- 区块间的交互模式

## Step 3: 基础构建（Foundation Build）

**按顺序执行，自己完成不分派**：

### 3.1 更新字体
在 `layout.tsx` 配置目标站点的实际字体

### 3.2 更新全局 CSS
在 `globals.css` 配置：
- 颜色 tokens
- 间距值
- 关键帧动画
- 全局滚动行为

### 3.3 创建类型定义
在 `src/types/` 创建 TypeScript interfaces

### 3.4 提取 SVG 图标
查找所有 inline `<svg>`，去重后保存为 React 组件到 `src/components/icons.tsx`

### 3.5 下载资源
写 Node.js 脚本 `scripts/download-assets.mjs`：
```javascript
// 发现所有资源
const assets = {
  images: [...document.querySelectorAll('img')].map(img => ({
    src: img.src,
    alt: img.alt,
    width: img.naturalWidth,
    height: img.naturalHeight
  })),
  videos: [...document.querySelectorAll('video')].map(v => ({
    src: v.src,
    poster: v.poster
  })),
  backgroundImages: [...document.querySelectorAll('*')].filter(el => {
    const bg = getComputedStyle(el).backgroundImage;
    return bg && bg !== 'none';
  })
};
```
并行下载到 `public/`（最多 4 个并发）

### 3.6 验证
```bash
npm run build
```

## Step 4: 组件规范与构建

**核心循环**：提取 → 写规范 → 分派 builder

### 4.1 提取

每个区块需要：
1. **截图**：滚动到区块，截取视口截图
2. **CSS 提取**：用 `playwright-cli eval` 获取精确值
3. **多状态提取**：hover/active/scroll 状态都记录
4. **实际内容**：textContent 提取所有文本
5. **资源识别**：该区块使用的图片/图标

**提取脚本**：
```bash
playwright-cli eval "
(function(selector) {
  const el = document.querySelector(selector);
  if (!el) return JSON.stringify({ error: 'Element not found: ' + selector });
  const props = [
    'fontSize','fontWeight','fontFamily','lineHeight','letterSpacing','color',
    'backgroundColor','background','padding','margin','width','height',
    'display','flexDirection','justifyContent','alignItems','gap',
    'borderRadius','border','boxShadow','position','top','right','bottom','left','zIndex',
    'opacity','transform','transition','cursor'
  ];
  function extractStyles(element) {
    const cs = getComputedStyle(element);
    const styles = {};
    props.forEach(p => {
      const v = cs[p];
      if (v && v !== 'none' && v !== 'normal' && v !== 'auto' && v !== '0px')
        styles[p] = v;
    });
    return styles;
  }
  function walk(element, depth) {
    if (depth > 4) return null;
    const children = [...element.children];
    return {
      tag: element.tagName.toLowerCase(),
      classes: element.className?.toString().split(' ').slice(0, 5).join(' '),
      text: element.childNodes.length === 1 && element.childNodes[0].nodeType === 3
        ? element.textContent.trim().slice(0, 200) : null,
      styles: extractStyles(element),
      images: element.tagName === 'IMG' ? { src: element.src, alt: element.alt } : null,
      childCount: children.length,
      children: children.slice(0, 20).map(c => walk(c, depth + 1)).filter(Boolean)
    };
  }
  return JSON.stringify(walk(el, 0), null, 2);
})('SELECTOR')
"
```

### 4.2 识别交互模型

**在写规范前必须回答**：这个区块是点击驱动还是滚动驱动？

判断方法：
1. **先滚动**：观察内容是否自动变化
2. **如有变化**：是 scroll-driven，记录 IntersectionObserver 或 scroll 监听
3. **如无变化**：再测试点击/悬停

### 4.3 写规范文件

**路径**：`docs/research/components/<component-name>.spec.md`

**模板**：
```markdown
# <ComponentName> 规范

## 概述
- **目标文件**：`src/components/<ComponentName>.tsx`
- **截图**：`docs/design-references/<screenshot-name>.png`
- **交互模型**：<static | click-driven | scroll-driven | hover-driven>

## DOM 结构
<描述元素层级关系>

## 精确 CSS 值（来自 getComputedStyle）

### 容器
- display: ...
- padding: ...
- maxWidth: ...

### 子元素
...

## 状态与行为

### <状态名称，如 "滚动后">
- **触发**：<精确机制>
- **状态 A（触发前）**：...
- **状态 B（触发后）**：...
- **过渡**：transition: ...

### Hover 状态
- **元素**：<property>: <before> → <after>

## 内容（逐字复制）
<所有文本内容>

## 响应式行为
- **桌面 (1440px)**：...
- **平板 (768px)**：...
- **移动 (390px)**：...

## 资源
- 背景图：`public/images/<file>.webp`
- 图标：`<IconName>` from icons.tsx
```

### 4.4 分派 Builder

**简单区块**（1-2 个子组件）：一个 builder

**复杂区块**（3+ 个子组件）：拆分，每个子组件一个 builder

**每个 builder 收到**：
- 规范文件完整内容（内联在 prompt 中）
- 区块截图路径
- 共享组件信息（icons.tsx, cn(), shadcn primitives）
- 目标文件路径
- 验证指令：`npx tsc --noEmit`

### 4.5 合并

builder 完成后：
- 合并到 main
- 验证：`npm run build`
- 如有类型错误立即修复

## Step 5: 页面组装

在 `src/app/page.tsx`：
- 导入所有 section 组件
- 实现页面级布局（scroll containers, sticky positioning, z-index）
- 连接实际内容到组件 props
- 实现页面级行为（scroll snap, 动画, 过渡）

## Step 6: 视觉 QA

**必须执行**：
1. 并排对比原站和克隆站
2. 桌面端 (1440px) 和移动端 (390px) 各检查一遍
3. 测试所有交互：滚动、点击、悬停
4. 如有差异：
   - 规范文件错了 → 重新提取，修复组件
   - builder 错了 → 直接修复组件

## 输出格式

克隆完成后报告：
```
✅ 克隆完成
- 总区块数：X
- 组件数：X
- 规范文件：X
- 下载资源：X 张图片, X 个视频
- 构建状态：✅/❌
- 视觉 QA：通过/有 X 处差异
```

## ⚠️ 禁忌事项

- **不要猜测 CSS 值**：使用 `getComputedStyle()` 精确提取
- **不要遗漏 overlay 图片**：检查每个容器的完整 DOM 树
- **不要用点击驱动实现滚动驱动的交互**
- **不要跳过规范文件**：每个组件必须有规范
- **不要让 builder 做太多**：规范超过 ~150 行说明需要拆分
- **不要近似**：16px 和 15.8px 不一样！
- **不要跳过响应式测试**：必须在 1440px, 768px, 390px 都测试

## 适用场景

✅ **适合**：
- 从 WordPress/Webflow/Squarespace 迁移到你自己的站点
- 源码丢失的站点重建
- 学习现代网站的布局/动画/响应式实现

❌ **不适合**：
- 钓鱼或冒充
- 侵犯商标/版权
- 违反服务条款的站点

