1实现原理 · 为什么它能做到
这个 skill 不是可执行程序,而是注入给本机 coding-agent CLI 的一段提示词:宿主取 SKILL.md 正文,前面压一段全站共享设计指令、后面接用户内容,拼成一条 prompt 交给已登录的 agent,再把 agent 的 stdout 当 HTML 取回。
【输入格式】: ${opts.format} 【用户内容】: ${opts.content}
共享指令层(不属于任何单个 skill,但每个模板都被它压着)把输出钉成『自包含单文件 HTML』,并明令禁止 agent 使用 Write/Edit/Bash 等文件系统工具,HTML 直接以对话正文流式输出。
- **禁止使用 Write / Edit / MultiEdit / Bash / Create / 任何文件系统工具**。不要把 HTML 写到任何 \`.html\` 文件里。前端直接捕获你的 stdout 文本, 文件落盘由前端负责。
SKILL.md 之外还有一条『内容驱动数量』覆盖规则:模板里写的任何页数/帧数/卡片数一律视为参考下限,实际数量由用户内容决定——防止 agent 用模板数字压缩用户内容。
- 模板只定义"可用版面 / 风格 / 配色 / 字体 / 组件库", **不定义** slide / 帧 / 卡片 / section 的数量。
加载约定是『一个 skill = 一个文件夹』:SKILL.md(YAML frontmatter 供选择器 + 正文即模板 prompt),可选 example.md(样本输入)与 example.html(可直接打开的预览样张);新增模板只需加目录,不改 TS 代码。
* SKILL.md — frontmatter (id, scenario, tags, …) + prompt body * example.md — (optional) sample input content * example.html — (optional) pre-rendered preview, shown inline in the picker
选择链路(CLI 侧)是三级漏斗:关键词强信号(每命中 1 词 2 分,阈值 3)→ 退化为 tags/scenario 打分 → 仍无把握就把用户内容前 800 字交给本地 agent 做一句话分类。
const CONFIDENCE_THRESHOLD = 3;
预览链路独立于生成:/api/templates/<id>/preview 把 example.html 原样以 text/html 返回给 iframe;前端 iframe 用 sandbox="allow-scripts allow-same-origin"。
sandbox="allow-scripts allow-same-origin"
画布是这套模板的辨识点:推荐 2.39:1 letterbox(1920×800,上下黑边各 140px),也支持全幅 16:9(1920×1080)。
aspect_hint: "2.39:1 letterbox (1920×800) 或 16:9 (1920×1080)"
胶片漏光用 2-3 个大 radial-gradient 椭圆 + 1 条底部 linear-gradient 叠出来,颜色限定暖橙/桃/玫红/暗黄,并明确『不要冷蓝』——用色彩温度而不是滤镜来立胶片感。
- **胶片漏光 (Light Leak)**: 2-3 个大 `radial-gradient(ellipse at top right, #ffb547 0%, transparent 50%)` + 1 个底部 `linear-gradient(to top, #d97757 0%, transparent 30%)`; 颜色取暖橙 / 桃 / 玫红 / 暗黄, **不要冷蓝**。
颗粒用全屏 SVG turbulence noise(opacity 14%、mix-blend-mode overlay)实现,并提供 data-URI 版 feTurbulence 写法;另有可选 feDisplacementMap 模拟胶片摆动(标注慎用)。
- **35mm Grain**: 全屏覆盖 SVG turbulence noise 图层, opacity 14%, `mix-blend-mode: overlay`; 也可用 `background-image: url("data:image/svg+xml,...feTurbulence...")`。
胶片物理细节补全:胶片划痕(1-2px 竖向白线、不规则间距)与胶片齿孔(letterbox 黑边内等距小白方块用 repeating-linear-gradient)。
example_desc: "2.39:1 letterbox + 衬线斜体大字 + 胶片齿孔"
文字与色数双向约束:衬线大字(Source Serif Pro / Playfair / EB Garamond)5-8vw italic + 暖白;颜色绝不超过 4 个色相;中文因 Noto Serif SC 无 italic,改用 regular + 加大字距。
- 中文: `Noto Serif SC` italic 不存在 → 用 `Noto Serif SC` regular + 字距加大。
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| network | Google Fonts(EB Garamond / Source Serif Pro / IBM Plex Mono / Noto Serif SC,示例页实际引用) |
| network | Tailwind Play CDN(共享指令强制;示例页亦引用) |
| network | hyperframes 目录页(frontmatter 出处标注,非运行时请求) |
4风险提醒 风险提醒:绿色 · 放心使用
- 色相纪律是硬约束也是脆弱点:一旦模型多堆一层紫/蓝,胶片感立刻变霓虹,模板只能靠文字禁止。 — SKILL.md:颜色绝不超过 4 个色相…不要冷蓝
- 字体依赖较重:EB Garamond / Source Serif Pro / Noto Serif SC 若不可得,衬线气质会退化为系统字体。 — example.html 的 Google Fonts 链接
- 宿主侧:预览 iframe sandbox="allow-scripts allow-same-origin";颗粒/漏光动画脚本在预览环境权限宽松。 — sandbox="allow-scripts allow-same-origin"(next/src/components/preview-pane.tsx)
- 注入面:用户标题与元数据被逐字拼进 prompt;模板允许模型『自动估算』年份/章节/地点,存在编造元数据的误导可能。 — SKILL.md:自动估算合理"年份 / 章节 / 地点" 元数据 (但来源用户内容)
5第二遍独立确认
- [ok] 画布/漏光/颗粒规格 — 重读 SKILL.md【画布】【背景】【文字】三段,逐字复核 2.39:1、140px、opacity 14%、overlay 等数值。
- [ok] 『不要冷蓝』约束 — SKILL.md 原文:颜色取暖橙 / 桃 / 玫红 / 暗黄, **不要冷蓝**。与 JSON 引用一致。
- [ok] 『无外链图片』结论 — 示例页 URL 扫描仅命中 fonts.googleapis.com 与 cdn.tailwindcss.com,无图片资源域;颗粒为 data-URI SVG。
- [ok] 中文 italic 处理 — SKILL.md 原文:中文: `Noto Serif SC` italic 不存在 → 用 `Noto Serif SC` regular + 字距加大。,引用逐字通过。
- [ok] 安全面 — 目录内 3 个文件无自写脚本、无凭证、无写盘、无表单外发。
- [ok] meta 元数据 — GitHub API 实查 stars=8827、pushed_at=2026-09-15T03:36:24Z、license Apache-2.0。
- [unlocatable] 安装量 — 无公开安装量数据源,installs=null。
6结论
b36d67728ab9f7bb…553ed98c28