Prototype Uploader
把刚刚和用户一起打磨好的 HTML 原型加密后发布到 GitHub Pages(Public 仓库),返回一个稳定链接。同事打开链接需要输入项目口令,浏览器本地解密后才能看到原型内容。
核心安全模型
- 仓库公开 ✅,但 HTML 内容是 AES-256-GCM 加密的密文
- 每个项目一个口令,同项目所有版本共用口令
- 同事输入口令后浏览器本地 PBKDF2 → 解密 → 渲染(口令永不上传服务器)
- 同事浏览器缓存口令 7 天(localStorage),同项目其他原型自动放行
- 没口令的人哪怕拿到链接也只能看到一段加密乱码
存储后端是可替换的(scripts/backends.py 的抽象层)。当前实现是 GitHub Pages,未来切换公司内网 CDN 时只需新增一个 Backend 类。
何时触发
- 用户说「上传一下」「发出去吧」「让 XX 看看」「传上去」「推到原型站」
- 用户刚生成/修改 HTML 原型,并暗示想分享
- 用户在配置 skill:贴 GitHub 用户名/token 等信息
决策路径
用户输入
│
├── 包含 GitHub 用户名/token 等? → 走「首次配置流程」
│
├── 想上传/分享原型? → 走「上传流程」
│
└── 模糊,先问清楚
上传流程
第 1 步:检查配置
python3 scripts/upload.py health
- ✅ 通过 → 进第 2 步
- ❌
找不到配置文件→ 走「首次配置流程」 - ❌
Token 无效→ 引导用户重新生成 token - ❌
403 Forbidden或blocked-by-allowlist→ 沙盒网络被禁了。引导用户:
> Claude 默认不让 skill 访问外部网络。请去 Settings → Capabilities → Allow network egress,在 Additional allowed domains 里加上api.github.com,然后开个新对话再来找我(这个设置不会应用到当前对话)。详见 SETUP.md 第 0 步。 - ❌ 其他网络错误 → 把错误原文给用户
第 2 步:拿到 HTML 内容
HTML 必须是本地文件。
- 如果对话里 HTML 在 artifact / 上传文件里 → 写入
/tmp/prototype.html - 如果只在你回复文本里 → 用
create_file写入/tmp/prototype.html
第 3 步:确定项目名
绝对不要自己猜。
-
列出现有项目:
bash python3 scripts/upload.py list -
把列表给用户看:
有项目时:
> 服务器上目前有:1. 登录页 2. 订单流程
>
> 这次的原型属于哪个?告诉我编号或者一个新项目名。
没项目时:
> 这是第一个原型,给它起个项目名吧(例如「登录页」「订单流程」)。
- 等用户回复,不要假设。
第 4 步:处理项目口令
4a. 项目已存在 —— 验证用户提供了正确口令
python3 scripts/upload.py has-password --project "<项目名>"
如果返回 has_password: true:
- 必须问用户该项目的口令是什么(在本对话里没拿到的话)
- 校验:
bash
python3 scripts/upload.py verify-password --project "<项目名>" --password "<用户给的口令>"
- 如果 valid: false → 告诉用户口令不对,让他重输。不要绕过这一步。
- 如果 valid: true → 进第 5 步
注意:现有项目用错误口令上传虽然技术上能加密成功,但同事用旧口令解不开,会让大家很困惑。所以必须校验。
4b. 新项目 —— 让用户设一个口令
如果是用户刚命名的新项目:
> 这是新项目,给它设个口令吧(同事访问时要输这个口令,至少 4 位)。
>
> 提示:选个简单好记的,比如 team2026、abcd1234 —— 它只用于本项目原型的访问保护,不是高安全场景。
等用户回复口令。不要自己生成口令 —— 用户得记住才行。
4c. 作者:新项目必问,已有项目可选
新项目:必须问作者名,作为这个项目 PRD 的负责产品经理。
> 这个项目的负责人(作者)是谁?我会把名字显示在原型页面和项目列表里。
让用户回答(可以是中文姓名、英文工号、邮箱前缀等,由用户决定格式)。不要自己猜或填默认值。
已有项目:默认不动作者,但可以让用户选择是否更新:
调用 meta 子命令查当前作者:
python3 scripts/upload.py meta --project "<项目名>"
返回 {author: "王云鹏", ...} 后,轻量提示一下:
> 当前作者是「王云鹏」,需要换成别人吗?(比如交接给新同事了。直接说"不用"就保持不变)
- 用户说"不用"/"保持"/没回应 → upload 时不传
--author - 用户给了新名字 → upload 时传
--author "新名字"
不要为这事卡住流程 —— 默认就是不变。
第 5 步:(可选)问一句备注
简短问「这次改了什么?我顺便记到 commit 里」。用户提了就传 --note,没提就跳过。
第 6 步:执行上传
python3 scripts/upload.py upload \
--project "<项目名>" \
--password "<项目口令>" \
--html-file /tmp/prototype.html \
--author "<新项目必填,已有项目省略代表不变>" \
--note "<可选>"
成功返回:
{
"success": true,
"url": "https://xxx.github.io/team-prototypes/登录页/latest.html",
"versioned_url": "https://xxx.github.io/team-prototypes/登录页/2026-04-28_15-30-00.html",
"project_url": "https://xxx.github.io/team-prototypes/登录页/",
"home_url": "https://xxx.github.io/team-prototypes/",
"filename": "2026-04-28_15-30-00.html",
"timestamp": "2026-04-28_15-30-00",
"author": "王云鹏"
}
第 7 步:把结果给用户
按这个格式(自然组织,别照搬):
✅ 已上传(已加密,需口令访问)
📐 项目:登录页 · 作者 王云鹏
🔗 发给同事的链接(永远指向最新版):
https://xxx.github.io/team-prototypes/登录页/latest.html
🔑 访问口令:<项目口令>
📌 这次具体版本:
https://xxx.github.io/team-prototypes/登录页/2026-04-28_15-30-00.html
📂 项目所有版本:
https://xxx.github.io/team-prototypes/登录页/
⏱ GitHub Pages 部署需 30-60 秒,第一次打开如果 404,稍等再刷新。
💡 同事输一次口令后 7 天免输入。
重要:每次上传都把口令一并展示给用户,让他能直接复制连同链接一起发给同事。
首次配置流程
第 1 步:判断阶段
-
如果用户没读过 SETUP.md → 让他读:
> 第一次用要做 5 分钟的 GitHub 设置(全程在浏览器里完成,不用打开终端)。
> 请打开 SETUP.md 跟着步骤走,最后一步把信息回贴给我。 -
如果用户已经把 GitHub 信息贴过来了 → 进第 2 步
第 2 步:解析配置信息
从用户消息里提取 4 个字段:
- GitHub 用户名(owner)
- 仓库名(repo)
- Pages 地址(pages_url)
- Token
任一缺失 → 问用户补全,不要瞎猜。
第 3 步:写 config.json
用 create_file 在 skill 根目录写:
{
"backend": "github",
"github": {
"token": "<token>",
"owner": "<用户名>",
"repo": "<仓库名>",
"pages_url": "<pages 地址>",
"branch": "main"
}
}
第 4 步:健康检查
python3 scripts/upload.py health
成功 → 「配置完成,可以上传原型了」并建议测试一次。
失败 → 按错误内容引导:
- Token 无效 → 让他确认 token 是否完整、是否选了 Contents: Read and write
- 仓库不存在 → owner/repo 拼写
- 403 Forbidden / blocked-by-allowlist / connection refused → 沙盒网络问题,引导用户去 Settings → Capabilities → Additional allowed domains 加上 api.github.com,然后开新对话再回来。这是首次配置最常见的卡点。
- 其他网络问题 → 让他重试或检查网络
第 5 步:保存到 Memory
如果 Memory 启用:把 owner/repo/pages_url 不含 token 存到 Memory,方便下次新对话直接读取。Token 已经在 config.json 里持久化了,不需要再在 Memory 里存第二份。
边界情况
用户说「上传」但没有 HTML:
问:「你想上传哪个原型?是当前对话里的某个 HTML,还是某个本地文件?」
同事说「打不开 / 口令不对」:
- 让用户确认发给同事的口令是不是这个项目的真实口令
- 让同事换个浏览器/隐身模式试试(避免 localStorage 干扰)
- 如果还不行,可能是 GitHub Pages 部署还没完成(>1 分钟)
用户忘了某项目口令:
口令只存了哈希,没法找回。两个选择:
1. 重新设口令(覆盖):python3 scripts/upload.py set-password --project "<n>" --password "<新口令>",但注意:旧版本是用旧口令加密的,仍然要旧口令才能解 —— 重设口令只影响之后上传的文件。告诉用户这一点。
2. 接受丢失,用新口令开始新一轮上传
用户想用同一份 HTML 传到多个项目:
依次跑两次 upload。注意每个项目可能口令不同。
HTML 体积大:
GitHub 单文件 100MB 上限,加密会让密文略大但同量级。>5MB 时提醒用户「这个原型有点大,可能是嵌入了图片」。
不要做的事
- ❌ 不要在缺 config.json 时假装上传成功
- ❌ 不要在没问清项目名时就上传
- ❌ 不要在已有项目跳过口令校验 —— 用错口令会让同事看不到
- ❌ 不要替用户生成口令 —— 他得记住
- ❌ 不要在新项目里跳过问作者 —— 这是必填字段
- ❌ 不要替用户填作者名("用您"、"产品经理"这类占位都不行)—— 必须问真名
- ❌ 不要在已有项目主动改作者 —— 默认保留,除非用户明确要换
- ❌ 不要把 token 反复在对话明文里出现(只在写入 config.json 时使用)
- ❌ 不要把项目名拼到 shell 命令时漏加引号(中文/特殊字符会出错)
- ❌ 不要忘了在最终输出里把口令和链接一起给用户