游戏站搭建器 (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 生成顺序:
package.json+next.config.js+tailwind.config.js(项目配置)app/globals.css(主题色 CSS 变量,用调研的 HSL 色值)components/下所有组件(参照对标站截图和 DOM 结构)app/layout.tsx(全局布局,组合导航栏 + 页脚)app/page.tsx(首页,组合 Hero + 各内容板块)app/[lang]/[slug]/page.tsx(内页动态路由,读取 MDX 内容)lib/seo.ts(SEO 元数据配置工具)content/en/下占位 MDX 文件(下一步填充真实内容)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 填充规则:
- 全站游戏名替换:将所有占位符
{GAME_NAME}替换为真实游戏名,检查 header、footer、sidebar、法律页无残留 - Hero stats:选 5 个最贴近玩家直觉的真实数据(发行日期、Metacritic、Steam 评测、玩家数、成就数),纯字符串数组
- 新手引导卡片:4 张卡片,第 1 张固定 Beginner Guide,后 3 张根据游戏特点选玩家前 2 小时最常搜的内容
- 兑换码:买断制游戏填"暂无",有兑换码系统的游戏填真实码,绝不编造
- 官方链接:全部用真实链接,AI 用浏览器抽检 1-2 个确认非 404
- SEO 元数据:title ≤ 60 字符,description 140-160 字符,keywords ≤ 100 字符
- 不确定的标"待确认":不要编造数值、角色名、兑换码
步骤 2.3:填充内页内容
AI 逐个读取内页素材文档,为每个关键词创建一个 MDX 内容文件。
填充顺序(按优先级):
- P0 级:首页(已在 2.2 完成)
- P1 级:Guide(新手引导)、Tips(技巧)、Best Tower Order(最佳顺序)
- P2 级:Codes(兑换码)、Crossplay(联机)、Review(评测)
- 其他内页:按关键词清单逐个填充
每个内页的 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 内页内容要求:
- 页面 title 含关键词,40-60 字符
- meta description 含关键词,140-160 字符
- 开头直接回答玩家的搜索问题,不绕弯
- 全文 1200 字左右;分 H2 小节,每段 3-4 句,适合扫读
- 只写素材文档中的真实信息,不确定的标"待确认"
- 不要编造数值、角色名、兑换码
步骤 2.4:全站残留检查(游戏名 / 参考站名 / 占位符 / CJK)
AI 用 Grep 工具全项目搜索,确保零残留。重点三类:
- 旧游戏名 / 对标站游戏名:不仅替换自己的旧占位符,还要确认对标站游戏名(如 farever)零残留——它常藏在 CSS 注释、
globals.css的Structure mirrored from ...注释、JS 字符串里,肉眼易漏。 - 占位符:
{GAME_NAME}、{TODO_CONTENT}、{TODO},以及内容里含糊的WIP/待补充token(正文诚实标注改用to be documented/still being confirmed)。 - 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 构建挂死)
# 安装依赖
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:本地静态服务
# 静态服务验证(不触发 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 长度,提交前零残留校验(模式一静态站用)。
执行要点
- 先上线,再打磨:首版只要能访问就是胜利,不要追求完美再上线
- 抄结构,不抄内容:页面布局/导航方式/配色可以参照对标站,但所有文字、数据、游戏名必须是自己调研的真实内容
- 不要编造任何数据:不确定的标"待确认",绝不编造数值、角色名、兑换码
- 旧内容必须彻底替换:从对标站复刻的代码,旧游戏名必须全替换,用 Grep 检查零残留
- 一个关键词一个内页:每个内页只承接一个关键词的搜索需求,精准匹配
- AI 直接执行全流程:分析对标站 → 生成代码 → 填充内容 → 本地验证 → git 提交,不需要用户复制提示词给外部工具
- 人工环节仅限:创建 GitHub 仓库(需要用户登录)、git 认证配置、域名/部署等后续步骤
需要一次铺几十个内页时:单篇跑顺后,交给
yxz-bulk-page-factory批量生产——它固化一套内页生成提示词 + 脚本挂载 + 防灌水闸门,本技能的"内页生成流程"(步骤 2.3)是它的单篇基线。本技能负责"做一个站",yxz-bulk-page-factory负责"把站内页铺满"。
浏览器抓取要点
- 统一用
mcp_playwright-extension:分析对标站、本地验证页面时用run_mcp调用本地浏览器 - DR 值无法自动化获取:SiteData 插件等扩展数据在 popup 渲染,playwright 读不到。让用户在自己的浏览器中安装 SiteData 插件查看 DR 值
- 截图是结构分析的核心:对标站的页面结构、配色、布局主要通过截图 + DOM 提取综合判断
- 等待加载:每次
browser_navigate后必须browser_wait_for,避免抓到空页面 - URL 编码:游戏名拼到 URL 时必须
encodeURIComponent - Google 搜索 IP 被标记:若出现 429 + /sorry/ 重定向,让用户切换网络环境,不降级 Bing
- 全页截图用于配色分析:
fullPage: true截取整页,用于判断整体配色和布局节奏
Playwright MCP 注意事项(已配 playwright-extension)
- MCP 禁止
file://协议:browser_navigate不接受file://。验证本地镜像改用python -m http.server 8765 --directory <out> --bind 127.0.0.1起静态服务,再 navigatehttp://127.0.0.1:8765/index.html。 - 截图只能存 MCP 工作目录:
browser_take_screenshot的filename受 allowed roots 限制(通常只能写进 MCP runtime 目录,如~/.workbuddy/logs/mcp-runtime/.../)。想落项目目录,先截到 MCP 目录再cp出来。 - 不要重新下载 Chromium:已配
playwright-extension(extension 模式)复用你已装的 Chrome,不要pip install playwright后另跑——那会触发独立 Chromium 下载(约 150MB),纯属多此一举。验证时直接调mcp__playwright-extension__browser_*工具。 - 合成点击在该环境有导航跟踪竞态:
locator.click()/ DOMa.click()不跟导航(测伪影)。验证链接可达性最可靠的方式:直接goto链接解析出的目标 URL,确认status==200且标题正确;或用browser_run_code_unsafe执行window.location.assign(targetUrl)。也可先用elementFromPoint确认<a>是顶层可点元素(无透明遮罩、pointer-events 正常)。
GitHub Pages 部署(静态导出首选,免费)
若用 output:"export",out/ 即为完整静态站,直接推到 GitHub Pages:
- 仓库 Settings → Pages → Source 选
gh-pages分支(root)。 next.config.mjs设basePath: "/{仓库名}"+assetPrefix: "/{仓库名}/"(仓库名即{游戏名}-wiki)。- 把
out/内容推到gh-pages分支(可用gh-pages包或手动 commit)。 - 访问
https://{用户名}.github.io/{仓库名}/。
Vercel 仍可选(连 GitHub 仓库自动部署),但静态导出站用 Pages 更省事、零配置。
输出文件
执行完成后产出:
完整的 Next.js 项目(本地目录
{游戏名}-wiki/)- 包含首页 + 导航页 + 详情页的完整代码
- 已填充真实内容,无旧游戏名残留
- SEO 元数据、主题色、多语言已配置
- 本地验证通过(所有页面可访问)
GitHub 仓库(远程)
- 仓库地址:
https://github.com/{用户名}/{仓库名} - 已推送首次提交(commit message: "first version")
- 仓库地址:
参考对象分析文档(可选)
{日期}-参考对象分析.md:记录 5-10 个候选站的评估结果,及最终选择理由
参考对象分析文档结构
# 参考对象分析 - {游戏主词}
> 分析日期:{日期}
> 游戏主词:{游戏主词}
## 候选站评估
| 序号 | 站点 URL | 页面结构 | UI 美观度 | 内容组织 | DR 值 | 综合评分 |
|------|----------|----------|----------|----------|-------|----------|
| 1 | ... | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | 0 | ★★★★★ |
| 2 | ... | ... | ... | ... | ... | ... |
## 最终选择
- **选中站点**:{URL}
- **选择理由**:{为什么选这个站,结构好在哪里}
- **复刻范围**:首页 + 列表页 + 详情页
- **提取的结构信息**:{导航栏结构、Hero 区布局、内容板块、侧边栏、页脚、配色方案}
实战踩坑教训
- DR 值无法通过 playwright 自动获取:Chrome 安全模型禁止扩展数据跨扩展读取(SiteData 插件的 DR 数据在 popup 渲染,不在网页 DOM)。对策:让用户在自己的浏览器装 SiteData 插件手动查看 DR,或直接看 Google 搜索结果——排名靠前且页面结构好的就是值得参考的。
- 对标站结构提取要全面:只截图不够,必须同时用
browser_evaluate提取 DOM 结构(导航栏文本、Hero 区内容、板块顺序、侧边栏内容、页脚链接),才能准确复刻布局。 - 复刻后旧游戏名残留:最容易出问题的是 footer、sidebar、法律页(About/Legal)。对策:AI 用
Grep全项目搜索旧游戏名和占位符,确保零残留。 - AI 编造兑换码:侧边栏兑换码是 AI 幻觉高发区。对策:填充时严格对照素材文档,没有就写"暂无",并在本地验证阶段核验。
- 内页内容质量不达标:AI 填充可能内容过短或结构混乱。对策:设定 1200 字下限、H2 小节、每段 3-4 句等硬性要求,确保可读性。
- Next.js 项目首次编译慢:首次
npm run dev可能需要 30-60 秒。对策:启动后等待Ready信号再进行浏览器验证,不要中断进程。 - MDX 内容路径必须正确:MDX 文件的存储路径必须匹配 Next.js 的路由结构,否则页面会 404。对策:AI 检查
content/目录结构与app/[lang]/[slug]/page.tsx的路由配置是否一致。 - 多语言配置遗漏:复刻时可能遗漏 i18n 配置。对策:AI 检查
i18n.ts或locales/目录,确保至少有en语言包。 - GitHub 首次推送认证问题:HTTPS 方式推送可能需要 token。对策:AI 暂停提示用户配置 Personal Access Token 或改用 SSH 方式,配置完成后重新执行 push。
- Vercel 部署前不要改太多:代码推到 GitHub 后直接连 Vercel 部署,不要在部署前做太多改动——先跑通再优化。
- 占位符必须全部替换:AI 生成代码时用的
{GAME_NAME}、{TODO_CONTENT}等占位符,在内容填充阶段必须全部替换为真实内容。对策:填充完成后用Grep搜索占位符模式,确认零残留。 - 浏览器截图是复刻的核心依据:文字描述对标站结构容易遗漏细节,截图 + DOM 提取双管齐下最可靠。AI 生成组件代码时,应参照截图判断间距、字号、配色等视觉细节。
克隆镜像专项踩坑教训(模式二)
- 克隆镜像必须同时重写 href 与 src:只改
src会漏掉全部/x/y/页面链接(一次约 1.1 万个),file:// 下变成file:///x/y/(文件系统根),HTTP 下变 404。两个属性都要改写。 - 目录链接要补 index.html:
/classes/在 file:// 和简单 HTTP 服务下不会自动解析成classes/index.html。必须显式补/index.html,否则点击无反应。 - Next.js 镜像在 file:// 下会闪退:hydration 脚本与路由不匹配导致卸载 DOM。剥离
_next脚本即可当静态设计稿查看(CSS/图片照常保留)。 - Windows os.path.relpath 对混斜杠相对路径报 "on mount":用纯 Python 实现 posix 相对路径(见
scripts/mirror_site.py的posix_relpath),并os.path.normpath(OUT)统一分隔符(walk 给反斜杠、硬编码常是正斜杠)。 - BeautifulSoup 改
<style>不能用.string.replace_with:复杂 style 会抛异常,用正则或整体字符串处理。 - Playwright MCP 已可复用系统 Chrome,勿再下载:配了
playwright-extension就直接调其工具;否则会误触发独立 Chromium 下载(浪费 ~150MB 与数分钟)。 - MCP 禁 file://、截图限工作目录、合成点击不跟导航:验证本地镜像改用
http.server+ 直接goto目标 URL,截图先存 MCP 目录再cp。 - robots.txt content-signals 格式:
ai-train=no仅禁止用于训练模型,一次性设计结构镜像允许;Allow: /表示标准爬虫可抓;仅特定 AI 训练 bot(GPTBot/ClaudeBot 等)被Disallow。 - Git Bash 无 wget/curl:克隆用 Python
requests(managed venv,路径C:/Users/Brahma/.workbuddy/binaries/python/envs/default/);优先用 managed runtime 而非系统 Python。 - 死链兜底:源站已软删除的隐藏页(如
release/farever-online被server-status引用)抓回 404,把该死链回退到最近存在的父目录页(如release/index.html)。 - 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 把文件移到临时目录(偶发不可靠)。 out/404.html文件锁:build 退出后 404.html 残留句柄,Pythonrm -rf/fs.rmSync删不动(EPERM)。绕过:开新目录(如{游戏名}_build2/),用 PowerShellNew-Item -ItemType Junction -Path <new>/node_modules -Target <src>/node_modules软链node_modules,完整复制app/components/public/*.json后重建。- 静态导出 +
http.server验证优于 dev server:output:"export"产物out/可直接用于 GitHub Pages,且静态服务验证不触发 build 挂死、更贴近真实部署形态。dev server 仅适合纯开发调试。 - Playwright 全量自动扫描优于逐页截图:用
mcp__playwright-extension__browser_run_code_unsafe一次脚本循环所有页,自动断言 console error==0 / 404==0 / 主题色生效 / title·h1 正确 / main 文本长度达标,比逐页browser_navigate+ 肉眼看截图更快更可靠。截图只能写 MCP runtime 目录(见 9)。 - 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 实体膨胀('→'等)会让源码合规的 meta 在产物里超长,必须扫产物而非源码。