# Yxz Game Site Builder

> 游戏攻略站搭建与部署。基于已收集的素材，复刻竞品站结构、填充真实内容、提交 GitHub 部署。当需要把调研成果变成真实网站、复刻对标站、部署上线时调用。

- Skill: `byte886/yxz-game-site-builder` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add byte886/yxz-game-site-builder`
- Raw SKILL.md: https://api.skillmd.com/api/skills/byte886/yxz-game-site-builder/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: byte886 (https://skillmd.com/u/byte886)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/byte886/yxz-game-site-builder

---


# 游戏站搭建器 (Game Site Builder)

## 核心原则

**先上线，再打磨。** 一个花两天匆忙上线但抢占了先机的"垃圾"站，很可能比一个花两周精心打磨但姗姗来迟的完美网站，能带来多得多的流量。

新词竞争窗口很短，你越早上线，越容易获得优势。首版再烂，能访问就是胜利。

**不要从零搭前端。** 新手从空白项目开始写前端，耗时耗 token，而且 SEO 和页面结构容易不专业。更推荐的做法：找一个同类型的竞对游戏攻略站 → 参考它的前端效果和页面结构 → 打磨成自己的模板。

**一句话原则：抄结构，不抄内容。**
- ✅ 能参照：页面结构（首页放哪几块）、导航方式、内容组织、配色风格
- ❌ 必须改：所有文字内容、游戏名、具体数据——这些必须是你自己调研的真实内容

**本技能由 AI 直接执行，不需要用户复制提示词给外部工具。** AI 自主完成：浏览器分析对标站 → 生成项目代码 → 填充真实内容 → 提交 GitHub。

---

## 前置条件

用户需提供：
- **游戏主词**（已确定的游戏名称，由 yxz-hot-word-miner 输出）
- **关键词清单 + 页面矩阵**（由 yxz-keyword-miner 输出）
- **首页信息文档 + 内页素材文档**（由 yxz-game-info-collector 输出）
- **对标站 URL**（可选，若用户已找到参考对象；否则由本技能第一阶段辅助查找）
- **GitHub 用户名 + 仓库名**（用于提交代码）

### 账号与工具准备清单（用户需提前准备）

| 工具 | 用途 | 注册地址 |
|------|------|----------|
| 域名账号 | 购买域名 | spaceship.com |
| GitHub 账号 | 存储代码 | github.com |
| Vercel 账号 | 部署网站 | vercel.com |
| Cloudflare 账号 | DNS 解析 | cloudflare.com |

> 注：本技能聚焦**代码生成、内容填充、GitHub 提交**，由 AI 直接自动完成。域名购买、Vercel 部署、Cloudflare DNS 配置等后续环节由用户手动完成。

---

## 工具与数据获取方式

**浏览器操作**：使用 `mcp_playwright-extension` MCP 服务（server_name = `mcp_playwright-extension`）。下文 `run_mcp(server_name=..., tool_name=..., args=...)` 均为**伪代码**；真实调用用 `mcp__playwright-extension__browser_*` 工具（如 `browser_navigate` / `browser_snapshot` / `browser_take_screenshot` / `browser_console_messages` / `browser_run_code_unsafe`）。用于访问对标站、截图分析页面结构、本地预览验证。**全量自动验证优先用 `browser_run_code_unsafe`**（一次脚本循环所有页，见踩坑 26）。

```
# 导航到 URL
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_navigate",
        args={"url": "https://..."})

# 等待页面加载
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_wait_for",
        args={"time": 3})

# 截图（分析页面结构、配色、布局）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_take_screenshot",
        args={"type": "png", "scale": "css", "fullPage": false})

# 提取页面结构（DOM 分析，用于复刻布局）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_evaluate",
        args={"function": "() => { /* 提取页面结构 */ return data; }"})

# 提取页面可访问性快照（用于交互/识别元素）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_snapshot",
        args={})
```

**文件操作**：使用 `Write` 工具创建项目文件，`Edit` 工具修改内容，`Read` 工具读取素材文档，`Grep` 工具全项目搜索旧游戏名残留。

**命令执行**：使用 `RunCommand` 工具执行 git 命令、npm 命令。

**抓取流程通用模式**：`navigate → wait_for → screenshot/evaluate → 分析结构 → Write 生成代码`

---

## 执行流程

### 第一阶段：找到参考对象 & 分析结构

#### 步骤 1.1：查找参考对象（如用户未提供对标站）

如果用户已提供对标站 URL，直接跳到步骤 1.2。否则，AI 辅助查找：

**查找策略**：优先挑选**新站、DR（域名评级）接近 0、排名靠前**的网站。DR=0 说明没怎么发外链，单靠网页结构就能把排名顶上去，更值得参考。

**所有查找均通过 `mcp_playwright-extension` 浏览器抓取**，禁止用 WebSearch/WebSearch 替代（Google 搜索结果依赖 JS 渲染，WebSearch 拿不到真实排名和域名列表）。

```
# 1. 用浏览器访问 Google 搜索：游戏词 + wiki
#    目标：找到 DR 接近 0 的新游戏 wiki 站
run_mcp("mcp_playwright-extension", "browser_navigate",
        args={"url": "https://www.google.com/search?q={游戏词URL编码}+wiki&hl=en"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => document.body.innerText.substring(0, 4000)"})
# 从结果文本中找排名靠前的 wiki 站域名

# 2. 搜索同类游戏 wiki 站（如 Big Walk 是合作冒险类，搜同类游戏的 wiki 站）
run_mcp("mcp_playwright-extension", "browser_navigate",
        args={"url": "https://www.google.com/search?q=co-op+adventure+game+wiki+guide&hl=en"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => document.body.innerText.substring(0, 4000)"})

# 3. 访问候选 wiki 站，评估页面结构
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{候选站URL}"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_take_screenshot",
        args={"type": "png", "scale": "css", "fullPage": false})
# 截图评估：导航栏、Hero 区、Tab 按钮、大标题等 UI 元素是否齐全
```

**优秀参考站的共性特征**：
- 导航栏：清晰的主导航结构
- Hero 区：大标题 + 游戏核心信息展示
- Tab 按钮：分类信息组织
- UI 美观：视觉风格统一
- 首页承接高搜索量需求：板块布局合理

**值得借鉴的站**（示例参考）：
- https://vvultimatum.net
- https://farevergame.wiki
- https://gamblewithyourfriends.net
- https://miniwars.art

**输出**：收集 5-10 个候选站，挑选出最值得复刻的 1 个，记录其首页 URL、列表页 URL、详情页 URL。

#### 步骤 1.2：深度分析对标站结构（AI 自动执行）

确定对标站后，AI 用浏览器逐页深度分析，提取页面结构、配色、布局信息，为代码生成提供依据。

```
# 1. 访问对标站首页，截图 + 提取结构
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{对标站首页URL}"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})

# 截图（用于配色、布局参考）
run_mcp("mcp_playwright-extension", "browser_take_screenshot",
        args={"type": "png", "scale": "css", "fullPage": true})

# 提取页面结构信息（导航栏、Hero 区、内容板块、侧边栏、页脚）
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => { const nav = document.querySelector('nav, header'); const hero = document.querySelector('section, .hero, [class*=hero]'); const sidebar = document.querySelector('aside, .sidebar, [class*=sidebar]'); const footer = document.querySelector('footer'); const main = document.querySelector('main, .main, .content'); return { nav: nav ? nav.innerText.substring(0, 500) : null, hero: hero ? hero.innerText.substring(0, 500) : null, sidebar: sidebar ? sidebar.innerText.substring(0, 500) : null, main: main ? main.innerText.substring(0, 2000) : null, footer: footer ? footer.innerText.substring(0, 500) : null, bgColor: getComputedStyle(document.body).backgroundColor, textColor: getComputedStyle(document.body).color }; }"})

# 2. 访问列表/导航页（如 /classes），提取列表结构
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{对标站列表页URL}"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_take_screenshot",
        args={"type": "png", "scale": "css", "fullPage": false})
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => { const items = document.querySelectorAll('a, .card, .item, .list-item, article'); return Array.from(items).slice(0, 20).map(el => ({ tag: el.tagName, text: el.innerText.substring(0, 100), href: el.href || '' })); }"})

# 3. 访问详情页，提取文章结构
run_mcp("mcp_playwright-extension", "browser_navigate", args={"url": "{对标站详情页URL}"})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})
run_mcp("mcp_playwright-extension", "browser_take_screenshot",
        args={"type": "png", "scale": "css", "fullPage": false})
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => { const article = document.querySelector('article, main, .content, .post-body'); const headings = document.querySelectorAll('h1, h2, h3'); return { structure: article ? article.innerText.substring(0, 3000) : null, headings: Array.from(headings).map(h => ({ level: h.tagName, text: h.innerText })) }; }"})

# 4. 提取 CSS 主题色
run_mcp("mcp_playwright-extension", "browser_evaluate",
        args={"function": "() => { const root = document.documentElement; const styles = getComputedStyle(root); return { primary: styles.getPropertyValue('--primary') || styles.getPropertyValue('--theme') || styles.getPropertyValue('--color-primary'), bg: styles.getPropertyValue('--bg') || styles.getPropertyValue('--background'), text: styles.getPropertyValue('--text') || styles.getPropertyValue('--color-text') }; }"})
```

**AI 分析要点**（从截图和 DOM 数据中提取）：
- **页面板块**：首页有哪些区块（Hero / 新手引导 / 游戏介绍 / 兑换码 / 底部号召），各区块的布局方式
- **导航结构**：主导航有哪些分类（Guide / Classes / Codes / Tier List 等）
- **配色方案**：主色、背景色、文字色（提取 CSS 变量或从截图判断）
- **列表页结构**：卡片式 / 表格式 / 列表式，每项展示哪些信息
- **详情页结构**：文章布局（标题 / 正文 / H2 小节 / 侧边栏 / 相关推荐）
- **响应式设计**：移动端适配方式

#### 步骤 1.3：生成项目骨架（AI 直接生成代码）

AI 基于步骤 1.2 提取的结构信息，直接用 `Write` 工具生成完整项目代码。

**技术栈（推荐稳健栈）**：Next.js (App Router) + **手写 CSS（`app/globals.css` 定义全套设计 token）** + **静态导出 `output: "export"`**。

> **实战首选，为什么不默认 Tailwind/MDX/i18n**：受限环境（npm 安装脆弱、构建易挂）下，Tailwind 构建步骤 + MDX 编译 + 动态 `[lang]/[slug]` 路由会显著放大不确定性。已验证最稳组合是：**手写 CSS + 固定 `app/<page>.jsx` 页面（每关键词一页）+ 静态导出**，产物 `out/` 可直接拖到 GitHub Pages。若确需多语言/内容驱动再上 MDX + next-i18n。

**项目结构**（AI 直接生成；实战首选**简化版**：去掉 `[lang]/[slug]` 动态路由与 `content/*.mdx`，改为 `app/<slug>.jsx` 固定页面 + `components/Sections.jsx` 共享区块 + 手写 `globals.css`，见下方说明）：

```
{游戏名}-wiki/
├── app/
│   ├── layout.tsx              # 全局布局（含导航栏、页脚）
│   ├── page.tsx                # 首页
│   ├── about/page.tsx          # 关于页（定位/团队/联系方式）
│   ├── contact/page.tsx         # 联系页（mailto:contact@域名）
│   ├── privacy/page.tsx         # 隐私政策页（≥300字，含 cookies/数据/广告）
│   ├── [lang]/
│   │   ├── page.tsx            # 多语言首页
│   │   └── [slug]/
│   │       └── page.tsx        # 内页动态路由
│   └── globals.css             # 全局样式（含主题色 CSS 变量）
├── components/
│   ├── Navbar.tsx              # 导航栏（参照对标站结构）
│   ├── Hero.tsx                # Hero 区
│   ├── Sidebar.tsx             # 侧边栏（兑换码等）
│   ├── Footer.tsx              # 页脚
│   ├── GameCard.tsx            # 游戏卡片（列表页用）
│   └── ArticleLayout.tsx       # 文章布局（详情页用）
├── content/
│   ├── en/                     # 英语 MDX 内容
│   │   ├── guide.mdx           # 新手引导
│   │   ├── tips.mdx            # 技巧
│   │   └── ...                 # 其他内页
│   └── i18n.json               # 多语言配置
├── lib/
│   ├── seo.ts                  # SEO 元数据配置
│   └── content.ts              # 内容加载工具
├── public/
│   └── favicon/                # 网站图标（来自 yxz-game-info-collector）
├── next.config.js
├── tailwind.config.js
├── package.json
└── README.md
```

**AI 生成顺序**：
1. `package.json` + `next.config.js` + `tailwind.config.js`（项目配置）
2. `app/globals.css`（主题色 CSS 变量，用调研的 HSL 色值）
3. `components/` 下所有组件（参照对标站截图和 DOM 结构）
4. `app/layout.tsx`（全局布局，组合导航栏 + 页脚）
5. `app/page.tsx`（首页，组合 Hero + 各内容板块）
6. `app/[lang]/[slug]/page.tsx`（内页动态路由，读取 MDX 内容）
7. `lib/seo.ts`（SEO 元数据配置工具）
8. `content/en/` 下占位 MDX 文件（下一步填充真实内容）
9. `app/about/page.tsx`、`app/contact/page.tsx`、`app/privacy/page.tsx`：建站即生成三个必备页面（AdSense 审核底线，详见下方说明）

**建站即生成「必备三页面」（AdSense 审核底线，不要等审核前才补）**：
- `app/about/page.tsx`：关于页——网站定位、编辑团队、联系方式。
- `app/contact/page.tsx`：联系页——提供 `mailto:contact@<你的域名>`（域名邮箱的转发配置由 `yxz-site-data-monetizer` 步骤 3.2.1 检查/确认）。
- `app/privacy/page.tsx`：隐私政策页——≥300 字，覆盖 cookies / 数据收集 / 第三方广告（AdSense 必查）。
这三者与首页、内页一并作为骨架生成；`yxz-site-data-monetizer` 阶段只做"是否齐全 + 邮箱转发是否配好"的检查确认，不重复创建。

**关键**：组件结构和布局完全参照对标站，但所有文字内容先用占位符（如 `{GAME_NAME}`、`{TODO_CONTENT}`），下一步再填充真实内容。

---

### 第二阶段：填充真实内容

AI 读取 yxz-game-info-collector 输出的素材文档，直接编辑项目文件填充真实内容。

#### 步骤 2.1：读取素材文档

```
# 读取首页信息文档
Read(file_path="{工作目录}/{日期}-{游戏主词}-首页信息.md")

# 读取关键词清单
Read(file_path="{工作目录}/{日期}-{游戏主词}-关键词清单.md")

# 读取页面矩阵
Read(file_path="{工作目录}/{日期}-{游戏主词}-页面矩阵.md")

# 逐个读取内页素材文档
Read(file_path="{工作目录}/{日期}-{游戏主词}-{内页关键词}-素材.md")
```

#### 步骤 2.2：填充首页内容

AI 根据首页信息文档，直接 `Edit` 项目文件填充内容：

**填充清单**：

| 文件 | 填充内容 | 数据来源 |
|------|----------|----------|
| `app/layout.tsx` | 游戏名（全站替换）、导航栏分类 | 首页信息文档 |
| `components/Hero.tsx` | Hero 标题、副标题、stats 数据 | 首页 JSON 的 hero 字段 |
| `app/page.tsx` | 新手引导卡片、游戏介绍 stats、底部号召 | 首页 JSON 的 start/aboutGame 字段 |
| `components/Sidebar.tsx` | 兑换码列表（真实码或"暂无"） | 首页 JSON 的 sidebarCodes 字段 |
| `components/Footer.tsx` | 官方链接（官网/Discord/YouTube）、关于文字 | 首页 JSON 的 footer 字段 |
| `lib/seo.ts` | SEO title/description/keywords | 首页 JSON 的 metadata 字段 |
| `app/globals.css` | 主题色 HSL 值 | 首页信息文档的主题色 |
| `content/i18n.json` | 多语言配置 | 首页信息文档的多语言优先级 |

**AI 填充规则**：
1. **全站游戏名替换**：将所有占位符 `{GAME_NAME}` 替换为真实游戏名，检查 header、footer、sidebar、法律页无残留
2. **Hero stats**：选 5 个最贴近玩家直觉的真实数据（发行日期、Metacritic、Steam 评测、玩家数、成就数），纯字符串数组
3. **新手引导卡片**：4 张卡片，第 1 张固定 Beginner Guide，后 3 张根据游戏特点选玩家前 2 小时最常搜的内容
4. **兑换码**：买断制游戏填"暂无"，有兑换码系统的游戏填真实码，**绝不编造**
5. **官方链接**：全部用真实链接，AI 用浏览器抽检 1-2 个确认非 404
6. **SEO 元数据**：title ≤ 60 字符，description 140-160 字符，keywords ≤ 100 字符
7. **不确定的标"待确认"**：不要编造数值、角色名、兑换码

#### 步骤 2.3：填充内页内容

AI 逐个读取内页素材文档，为每个关键词创建一个 MDX 内容文件。

**填充顺序**（按优先级）：
1. P0 级：首页（已在 2.2 完成）
2. P1 级：Guide（新手引导）、Tips（技巧）、Best Tower Order（最佳顺序）
3. P2 级：Codes（兑换码）、Crossplay（联机）、Review（评测）
4. 其他内页：按关键词清单逐个填充

**每个内页的 AI 执行步骤**：

```
# 1. 读取该关键词的素材文档
Read(file_path="{工作目录}/{日期}-{游戏主词}-{内页关键词}-素材.md")

# 2. AI 整合素材，过滤无效信息，交叉验证多源数据

# 3. 生成 MDX 内容文件
Write(file_path="{项目目录}/content/en/{slug}.mdx", content="""
---
title: "{含关键词的标题，40-60字符}"
description: "{含关键词的描述，140-160字符}"
keywords: "{关键词}"
---

# {开头直接回答玩家的搜索问题，不绕弯}

## {H2 小节 1}
{3-4 句，适合扫读}

## {H2 小节 2}
{3-4 句，适合扫读}

...
""")

# 4. 确保内页路由可访问（检查 app/[lang]/[slug]/page.tsx 能正确加载该 MDX）
```

**AI 内页内容要求**：
1. 页面 title 含关键词，40-60 字符
2. meta description 含关键词，140-160 字符
3. 开头直接回答玩家的搜索问题，不绕弯
4. 全文 1200 字左右；分 H2 小节，每段 3-4 句，适合扫读
5. 只写素材文档中的真实信息，不确定的标"待确认"
6. 不要编造数值、角色名、兑换码

#### 步骤 2.4：全站残留检查（游戏名 / 参考站名 / 占位符 / CJK）

AI 用 `Grep` 工具全项目搜索，确保零残留。**重点三类**：

1. **旧游戏名 / 对标站游戏名**：不仅替换自己的旧占位符，还要确认**对标站游戏名**（如 farever）零残留——它常藏在 CSS 注释、`globals.css` 的 `Structure mirrored from ...` 注释、JS 字符串里，肉眼易漏。
2. **占位符**：`{GAME_NAME}`、`{TODO_CONTENT}`、`{TODO}`，以及内容里含糊的 `WIP` / `待补充` token（正文诚实标注改用 `to be documented` / `still being confirmed`）。
3. **CJK 字符泄漏**：英文站正文误混入中文词（往返 / 默契 / 入门 等）。**必须源码 + 产物 `out/*.html` 双重扫描**（build 后产物才是最终交付）。

```
# 1. 旧游戏名 + 对标站游戏名（大小写不敏感）
Grep(pattern="旧游戏名|对标站游戏名(如 farever)", path="{项目目录}", output_mode="content")

# 2. 占位符 / WIP token（正文诚实标注用 to be documented）
Grep(pattern="\{GAME_NAME\}|\{TODO_CONTENT\}|\{TODO\}|WIP|待补充|Lorem|placeholder", path="{项目目录}", output_mode="content")

# 3. CJK 泄漏（源码）
Grep(pattern="[\u4e00-\u9fff]", path="{项目目录}/app", output_mode="content")
```

> **build 后务必再扫一次产物**：用 Python 脚本扫描 `out/*.html` 的 旧游戏名/对标站名/CJK/占位符 + SEO 长度（title≤60, desc 140–160, kw≤100），见踩坑 27。发现残留后用 Edit 逐个替换。

---

### 第三阶段：构建 + 本地验证（静态导出优先）

AI 本地构建静态导出产物，并用浏览器验证所有页面可访问、无报错、无残留。

#### 步骤 3.1：构建（绕过 WorkBuddy 构建挂死）

```bash
# 安装依赖
npm install

# ⚠️ WorkBuddy 的 genie-safe-delete shim 会在 build 收尾清理阶段挂死。
#    绕过：清空 NODE_OPTIONS 再 build（最稳）
NODE_OPTIONS="" npm run build

# 若 out/404.html 被文件监视器锁住，rm/fs.rmSync 删不动（EPERM）：
#   重建到新目录（如 {游戏名}_build2/），用 junction 软链 node_modules，
#   完整复制源码后重新 build：
#   PowerShell: New-Item -ItemType Junction -Path <new>/node_modules -Target <src>/node_modules
```

产物写入 `out/`，可直接用于 GitHub Pages（见第四阶段）。

#### 步骤 3.2：本地静态服务

```bash
# 静态服务验证（不触发 build 挂死，且贴近真实部署形态）
python -m http.server 4321 --bind 127.0.0.1 --directory out
```

#### 步骤 3.3：Playwright 全量自动扫描（替代逐页肉眼截图）

用 `mcp__playwright-extension__browser_run_code_unsafe`（真实工具名；SKILL 中 `run_mcp(...)` 为伪代码），一次脚本循环所有页，断言：

- `console error` / `pageerror` == 0
- 失败 / 404 请求 == 0
- `body` 背景色 == 主题色（CSS 已生效）
- `title` / `h1` 正确、`main` 文本长度 > 阈值（内容已渲染）
- 全量截图存 MCP runtime 目录后抽查关键页

> 比逐页 `browser_navigate` + 肉眼看截图**更快更可靠**（自动捕获 console/404）。脚本模板见踩坑 23、26。

**本地检查清单**：

| 检查项 | 要求 | AI 验证方式 |
|--------|------|------------|
| 构建成功 | `out/` 生成、无挂死 | `NODE_OPTIONS="" npm run build` |
| 首页可访问 | 浏览器打开正常渲染 | 静态服务 + 全量扫描 |
| 所有内页可访问 | 内容完整、无 404 | 全量扫描断言 |
| 全站游戏名/参考站名无残留 | 无旧游戏名/对标站名/占位符/CJK | Grep + 产物 HTML 扫描（见 2.4、27） |
| 链接有效 | 内部链接可达 | 全量扫描 goto 目标 URL |
| 官方链接有效 | 官网/Discord/YouTube 非 404 | 浏览器抽检 1-2 个 |
| 兑换码真实 | 无编造数据 | 对照素材文档 |

---

### 第四阶段：提交到 GitHub

代码在本地验证通过后，AI 直接执行 git 命令提交到 GitHub。

#### 步骤 4.1：确认 GitHub 仓库已创建

```
⏸️ 暂停等待人工处理

需要你手动完成以下操作：
1. 打开 https://github.com/new
2. 填写仓库名（建议：{游戏名}-wiki）
3. 类型选 Private（外人不可见）
4. 不要勾选自动生成 README
5. 点击 Create repository
6. 把仓库地址（https://github.com/{用户名}/{仓库名}.git）告诉我

我会等你处理完后继续执行 git 提交。
```

> 若用户已提供仓库地址，跳过此暂停。

#### 步骤 4.2：AI 直接执行 git 提交

```
# 1. 初始化 git 仓库
RunCommand(command="git init", cwd="{项目目录}", blocking=true, requires_approval=false)

# 2. 添加所有文件
RunCommand(command="git add .", cwd="{项目目录}", blocking=true, requires_approval=false)

# 3. 首次提交
RunCommand(command='git commit -m "first version"', cwd="{项目目录}", blocking=true, requires_approval=false)

# 4. 添加远程仓库
RunCommand(command="git remote add origin https://github.com/{用户名}/{仓库名}.git",
           cwd="{项目目录}", blocking=true, requires_approval=false)

# 5. 推送到远程
RunCommand(command="git push -u origin main", cwd="{项目目录}", blocking=true, requires_approval=false)
```

**认证问题处理**：
- 若 git push 需要认证，暂停提示用户配置 GitHub Personal Access Token 或 SSH key
- 认证配置完成后，AI 重新执行 push 命令

#### 步骤 4.3：验证推送成功

```
# 检查远程仓库状态
RunCommand(command="git remote -v", cwd="{项目目录}", blocking=true, requires_approval=false)
RunCommand(command="git log --oneline -1", cwd="{项目目录}", blocking=true, requires_approval=false)
```

AI 确认推送成功后，告知用户刷新 GitHub 仓库页面查看代码。

---

## 模式二：本地克隆镜像（设计稿 + 全量素材按 URL 结构保存）

适用场景：用户要求"克隆网站设计 / 镜像参考站 / 把素材按结构保存"，目标是把参考站原样存到本地目录作为**复刻前的模板**，不是立即从零搭 Next.js 项目（那是模式一）。典型命令：`/yxz-game-site-builder 帮我克隆网站设计：<URL> 所有素材按结构保存，根目录是：<path>`。

### 工作流

#### 步骤 M.1：侦察（recon）

- `GET /robots.txt`：确认是否允许抓取。Next.js 站常见 **content-signals** 格式：`Allow: /`、`ai-train=no`、`use=reference`。`ai-train=no` 只禁止用于**训练模型**，一次性设计结构镜像允许；`Allow: /` 表示标准爬虫可抓。
- `GET /sitemap.xml`：用正则 `<loc>(.*?)</loc>` 提取全部页面 URL（Next.js 静态站通常有完整 sitemap，含多语言 `/de/ /es/ /fr/`）。
- `GET /` 首页：识别技术栈。Next.js App Router 表现为唯一的 `_next/static/css/*.css` + 多个 `_next/static/chunks/*.js` + 内联 `self.__next_f.push(...)` flight payload。

#### 步骤 M.2：下载镜像（保存为 `<path>/<url-path>/index.html`）

- 用 Python `requests`（managed venv）逐 URL 抓取；Git Bash 通常**无 wget/curl**，优先用 managed runtime 路径。
- URL→本地路径映射：`/x/y` → `<out>/x/y/index.html`；`/` → `<out>/index.html`；去掉 query/fragment。
- 共享资源（`/_next/...`、`/icon.png`、`/favicon*`）单独抓取一次，落到对应目录；可顺带解析各页 `<script src>`/`<link href>` 收集 `_next` 资源去重下载。
- 多语言页与深链页一并落盘。

#### 步骤 M.3：重写内部链接（**href + src 都要**）

> 本步是最大坑：只改 `src`（CSS/JS/图片）会漏掉全部 `href` 页面链接，导致点击无法跳转。

- 把所有**根绝对**链接 `/x/y/` 改为**相对路径**并补 `index.html`：
  - 首页层：`` `/classes/` `` → `classes/index.html`
  - 嵌套页：按当前页面目录层级自动算 `../../weapons/index.html`
- `http(s)://` 同源链接同样转为相对路径；`#` 锚点、`mailto:`、外链保持不动。
- 若站点含 `mailto:contact@你的域名` 这类域名邮箱，记得在 Cloudflare 配好 Email Routing 免费转发（把 `contact@域名` 转发到真实邮箱），否则该邮箱收不到信。配置步骤见 `yxz-site-data-monetizer` 的「步骤 3.2.1：联系邮箱的 Cloudflare 免费转发配置」。
- 用**纯 Python 的 posix 相对路径算法**（见 `scripts/mirror_site.py` 的 `posix_relpath`），**不要**用 `os.path.relpath`——Windows 下混用正斜杠/反斜杠的相对路径会抛 `ValueError: ... on mount`。

#### 步骤 M.4：剥离 hydration 脚本（用于 `file://` 离线查看）

> 不剥离会出现"内容闪一下就消失"：SSR 的 HTML 先渲染，Next.js 路由脚本发现 `file:///.../index.html` 与预渲染路由 `/` 不匹配 → 卸载 DOM 成空白。

- 删除：`<script src="_next/...">` 的 chunk/main-app/polyfill、内联 `<script>self.__next_f.push(...)</script>` flight payload、Cloudflare beacon 等外部脚本。
- 删除：`<link rel="preload/modulepreload" href="_next/...">` 预加载（避免离线 console 404 噪声）。
- **保留**：CSS `<link>`、`<img>`、JSON-LD（SEO 数据，不操作 DOM）、所有 `_next/` 原始资源文件。
- BeautifulSoup 改写 `<style>` 内联内容时**不要**用 `.string.replace_with`（复杂 style 会抛异常），用正则或整体字符串处理。

#### 步骤 M.5：静态校验（无浏览器也能确认）

扫描全部 HTML 的 `(?:href|src)`，计算本地目标路径，判定：
- `root_abs`：是否还有根绝对 `/...` 链接（应为 0）
- `broken`：目标文件是否真实存在、或目录是否含 `index.html`（应为 0）

#### 步骤 M.6：（可选）Playwright MCP 验证

见"浏览器抓取要点"里的 MCP 注意事项。**优先用 MCP**（`playwright-extension` 复用系统 Chrome），不要另装 Python playwright 触发 Chromium 下载。

### 复用脚本

- `scripts/mirror_site.py <base_url> <out_dir> [--keep-js]`：下载 + 链接重写 + 剥离 hydration，一步到位。`--keep-js` 保留脚本（仅当目标站要当真站点跑时）。
- `scripts/verify_links.py <out_dir>`：静态扫描输出 `root_abs / broken` 统计，并列出断链样例。
- `scripts/validate_site.py <out_dir> [--ref-name farever] [--old-name X] [--no-seo] [--no-placeholder]`：build 后闸门，扫产物 HTML 的对标站名/旧游戏名/CJK/占位符残留 + SEO 长度，提交前零残留校验（模式一静态站用）。

---

## 执行要点

1. **先上线，再打磨**：首版只要能访问就是胜利，不要追求完美再上线
2. **抄结构，不抄内容**：页面布局/导航方式/配色可以参照对标站，但所有文字、数据、游戏名必须是自己调研的真实内容
3. **不要编造任何数据**：不确定的标"待确认"，绝不编造数值、角色名、兑换码
4. **旧内容必须彻底替换**：从对标站复刻的代码，旧游戏名必须全替换，用 Grep 检查零残留
5. **一个关键词一个内页**：每个内页只承接一个关键词的搜索需求，精准匹配
6. **AI 直接执行全流程**：分析对标站 → 生成代码 → 填充内容 → 本地验证 → git 提交，不需要用户复制提示词给外部工具
7. **人工环节仅限**：创建 GitHub 仓库（需要用户登录）、git 认证配置、域名/部署等后续步骤

> **需要一次铺几十个内页时**：单篇跑顺后，交给 `yxz-bulk-page-factory` 批量生产——它固化一套内页生成提示词 + 脚本挂载 + 防灌水闸门，本技能的"内页生成流程"（步骤 2.3）是它的单篇基线。本技能负责"做一个站"，`yxz-bulk-page-factory` 负责"把站内页铺满"。

---

## 浏览器抓取要点

1. **统一用 `mcp_playwright-extension`**：分析对标站、本地验证页面时用 `run_mcp` 调用本地浏览器
2. **DR 值无法自动化获取**：SiteData 插件等扩展数据在 popup 渲染，playwright 读不到。让用户在自己的浏览器中安装 SiteData 插件查看 DR 值
3. **截图是结构分析的核心**：对标站的页面结构、配色、布局主要通过截图 + DOM 提取综合判断
4. **等待加载**：每次 `browser_navigate` 后必须 `browser_wait_for`，避免抓到空页面
5. **URL 编码**：游戏名拼到 URL 时必须 `encodeURIComponent`
6. **Google 搜索 IP 被标记**：若出现 429 + /sorry/ 重定向，让用户切换网络环境，不降级 Bing
7. **全页截图用于配色分析**：`fullPage: true` 截取整页，用于判断整体配色和布局节奏

#### Playwright MCP 注意事项（已配 `playwright-extension`）

8. **MCP 禁止 `file://` 协议**：`browser_navigate` 不接受 `file://`。验证本地镜像改用 `python -m http.server 8765 --directory <out> --bind 127.0.0.1` 起静态服务，再 navigate `http://127.0.0.1:8765/index.html`。
9. **截图只能存 MCP 工作目录**：`browser_take_screenshot` 的 `filename` 受 allowed roots 限制（通常只能写进 MCP runtime 目录，如 `~/.workbuddy/logs/mcp-runtime/.../`）。想落项目目录，先截到 MCP 目录再 `cp` 出来。
10. **不要重新下载 Chromium**：已配 `playwright-extension`（extension 模式）复用你已装的 Chrome，**不要** `pip install playwright` 后另跑——那会触发独立 Chromium 下载（约 150MB），纯属多此一举。验证时直接调 `mcp__playwright-extension__browser_*` 工具。
11. **合成点击在该环境有导航跟踪竞态**：`locator.click()` / DOM `a.click()` 不跟导航（测伪影）。验证链接可达性最可靠的方式：直接 `goto` 链接解析出的目标 URL，确认 `status==200` 且标题正确；或用 `browser_run_code_unsafe` 执行 `window.location.assign(targetUrl)`。也可先用 `elementFromPoint` 确认 `<a>` 是顶层可点元素（无透明遮罩、pointer-events 正常）。

---

### GitHub Pages 部署（静态导出首选，免费）

若用 `output:"export"`，`out/` 即为完整静态站，直接推到 GitHub Pages：

1. 仓库 Settings → Pages → Source 选 `gh-pages` 分支（root）。
2. `next.config.mjs` 设 `basePath: "/{仓库名}"` + `assetPrefix: "/{仓库名}/"`（仓库名即 `{游戏名}-wiki`）。
3. 把 `out/` 内容推到 `gh-pages` 分支（可用 `gh-pages` 包或手动 commit）。
4. 访问 `https://{用户名}.github.io/{仓库名}/`。

> Vercel 仍可选（连 GitHub 仓库自动部署），但静态导出站用 Pages 更省事、零配置。

## 输出文件

执行完成后产出：

1. **完整的 Next.js 项目**（本地目录 `{游戏名}-wiki/`）
   - 包含首页 + 导航页 + 详情页的完整代码
   - 已填充真实内容，无旧游戏名残留
   - SEO 元数据、主题色、多语言已配置
   - 本地验证通过（所有页面可访问）

2. **GitHub 仓库**（远程）
   - 仓库地址：`https://github.com/{用户名}/{仓库名}`
   - 已推送首次提交（commit message: "first version"）

3. **参考对象分析文档**（可选）
   - `{日期}-参考对象分析.md`：记录 5-10 个候选站的评估结果，及最终选择理由

### 参考对象分析文档结构

```markdown
# 参考对象分析 - {游戏主词}

> 分析日期：{日期}
> 游戏主词：{游戏主词}

## 候选站评估

| 序号 | 站点 URL | 页面结构 | UI 美观度 | 内容组织 | DR 值 | 综合评分 |
|------|----------|----------|----------|----------|-------|----------|
| 1 | ... | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | 0 | ★★★★★ |
| 2 | ... | ... | ... | ... | ... | ... |

## 最终选择

- **选中站点**：{URL}
- **选择理由**：{为什么选这个站，结构好在哪里}
- **复刻范围**：首页 + 列表页 + 详情页
- **提取的结构信息**：{导航栏结构、Hero 区布局、内容板块、侧边栏、页脚、配色方案}
```

---

## 实战踩坑教训

1. **DR 值无法通过 playwright 自动获取**：Chrome 安全模型禁止扩展数据跨扩展读取（SiteData 插件的 DR 数据在 popup 渲染，不在网页 DOM）。**对策**：让用户在自己的浏览器装 SiteData 插件手动查看 DR，或直接看 Google 搜索结果——排名靠前且页面结构好的就是值得参考的。
2. **对标站结构提取要全面**：只截图不够，必须同时用 `browser_evaluate` 提取 DOM 结构（导航栏文本、Hero 区内容、板块顺序、侧边栏内容、页脚链接），才能准确复刻布局。
3. **复刻后旧游戏名残留**：最容易出问题的是 footer、sidebar、法律页（About/Legal）。**对策**：AI 用 `Grep` 全项目搜索旧游戏名和占位符，确保零残留。
4. **AI 编造兑换码**：侧边栏兑换码是 AI 幻觉高发区。**对策**：填充时严格对照素材文档，没有就写"暂无"，并在本地验证阶段核验。
5. **内页内容质量不达标**：AI 填充可能内容过短或结构混乱。**对策**：设定 1200 字下限、H2 小节、每段 3-4 句等硬性要求，确保可读性。
6. **Next.js 项目首次编译慢**：首次 `npm run dev` 可能需要 30-60 秒。**对策**：启动后等待 `Ready` 信号再进行浏览器验证，不要中断进程。
7. **MDX 内容路径必须正确**：MDX 文件的存储路径必须匹配 Next.js 的路由结构，否则页面会 404。**对策**：AI 检查 `content/` 目录结构与 `app/[lang]/[slug]/page.tsx` 的路由配置是否一致。
8. **多语言配置遗漏**：复刻时可能遗漏 i18n 配置。**对策**：AI 检查 `i18n.ts` 或 `locales/` 目录，确保至少有 `en` 语言包。
9. **GitHub 首次推送认证问题**：HTTPS 方式推送可能需要 token。**对策**：AI 暂停提示用户配置 Personal Access Token 或改用 SSH 方式，配置完成后重新执行 push。
10. **Vercel 部署前不要改太多**：代码推到 GitHub 后直接连 Vercel 部署，不要在部署前做太多改动——先跑通再优化。
11. **占位符必须全部替换**：AI 生成代码时用的 `{GAME_NAME}`、`{TODO_CONTENT}` 等占位符，在内容填充阶段必须全部替换为真实内容。**对策**：填充完成后用 `Grep` 搜索占位符模式，确认零残留。
12. **浏览器截图是复刻的核心依据**：文字描述对标站结构容易遗漏细节，截图 + DOM 提取双管齐下最可靠。AI 生成组件代码时，应参照截图判断间距、字号、配色等视觉细节。

#### 克隆镜像专项踩坑教训（模式二）

13. **克隆镜像必须同时重写 href 与 src**：只改 `src` 会漏掉全部 `/x/y/` 页面链接（一次约 1.1 万个），file:// 下变成 `file:///x/y/`（文件系统根），HTTP 下变 404。两个属性都要改写。
14. **目录链接要补 index.html**：`/classes/` 在 file:// 和简单 HTTP 服务下不会自动解析成 `classes/index.html`。必须显式补 `/index.html`，否则点击无反应。
15. **Next.js 镜像在 file:// 下会闪退**：hydration 脚本与路由不匹配导致卸载 DOM。剥离 `_next` 脚本即可当静态设计稿查看（CSS/图片照常保留）。
16. **Windows os.path.relpath 对混斜杠相对路径报 "on mount"**：用纯 Python 实现 posix 相对路径（见 `scripts/mirror_site.py` 的 `posix_relpath`），并 `os.path.normpath(OUT)` 统一分隔符（walk 给反斜杠、硬编码常是正斜杠）。
17. **BeautifulSoup 改 `<style>` 不能用 `.string.replace_with`**：复杂 style 会抛异常，用正则或整体字符串处理。
18. **Playwright MCP 已可复用系统 Chrome，勿再下载**：配了 `playwright-extension` 就直接调其工具；否则会误触发独立 Chromium 下载（浪费 ~150MB 与数分钟）。
19. **MCP 禁 file://、截图限工作目录、合成点击不跟导航**：验证本地镜像改用 `http.server` + 直接 `goto` 目标 URL，截图先存 MCP 目录再 `cp`。
20. **robots.txt content-signals 格式**：`ai-train=no` 仅禁止用于训练模型，一次性设计结构镜像允许；`Allow: /` 表示标准爬虫可抓；仅特定 AI 训练 bot（GPTBot/ClaudeBot 等）被 `Disallow`。
21. **Git Bash 无 wget/curl**：克隆用 Python `requests`（managed venv，路径 `C:/Users/Brahma/.workbuddy/binaries/python/envs/default/`）；优先用 managed runtime 而非系统 Python。
22. **死链兜底**：源站已软删除的隐藏页（如 `release/farever-online` 被 `server-status` 引用）抓回 404，把该死链回退到最近存在的父目录页（如 `release/index.html`）。
23. **WorkBuddy 构建挂死（genie-safe-delete shim）**：`NODE_OPTIONS=--require=...genie-safe-delete.cjs` 拦截 `fs.unlink`/`rm`，导致 `next build` 收尾清理卡死（日志停在 `Creating an optimized production build`）。**绕过**：`NODE_OPTIONS="" npm run build`（最稳）；或 `GENIE_TRASH_DIR=/tmp/genietrash` 让 shim 把文件移到临时目录（偶发不可靠）。
24. **`out/404.html` 文件锁**：build 退出后 404.html 残留句柄，Python `rm -rf` / `fs.rmSync` 删不动（EPERM）。**绕过**：开新目录（如 `{游戏名}_build2/`），用 PowerShell `New-Item -ItemType Junction -Path <new>/node_modules -Target <src>/node_modules` 软链 `node_modules`，完整复制 `app/components/public/*.json` 后重建。
25. **静态导出 + `http.server` 验证优于 dev server**：`output:"export"` 产物 `out/` 可直接用于 GitHub Pages，且静态服务验证不触发 build 挂死、更贴近真实部署形态。dev server 仅适合纯开发调试。
26. **Playwright 全量自动扫描优于逐页截图**：用 `mcp__playwright-extension__browser_run_code_unsafe` 一次脚本循环所有页，自动断言 console error==0 / 404==0 / 主题色生效 / title·h1 正确 / main 文本长度达标，比逐页 `browser_navigate` + 肉眼看截图更快更可靠。截图只能写 MCP runtime 目录（见 9）。
27. **build 后产物残留 + SEO 自动化校验**：用技能自带 `scripts/validate_site.py <out_dir>`（参数 `--ref-name farever` 改对标站名、`--old-name X` 加旧游戏名、`--no-seo`/`--no-placeholder` 关闭软检查）。它扫 `out/*.html` 断言 对标站名/旧游戏名/CJK/占位符（WIP·待补充·Lorem）/ SEO 长度（title≤60, desc 140–160, kw≤100），build 完、提交前跑一次即可清零。源码级 Grep 不够——build 可能把残留带进 HTML（如 CSS 注释里的对标站名）；且 **HTML 实体膨胀**（`'`→`&#x27;` 等）会让源码合规的 meta 在产物里超长，必须扫产物而非源码。

