关于 make-deck
make-deck 是用于生成 HTML 幻灯片演示文稿的技能,面向需要制作设计统一且可验证的演示文稿的用户。它包含设计上下文检测、版式预算和溢出检查流程,并支持演讲者备注与导出流程。
主要功能
- 01检测项目与品牌设计上下文
- 02构建 HTML 幻灯片
- 03规划版式与垂直空间
- 04按信号决定演讲者备注
- 05检查溢出并验证布局
- 06提供导出与后续编辑流程
适用场景
- 01根据项目设计令牌制作演示文稿
- 02将长文档内容整理为带备注的幻灯片
- 03检查幻灯片内容是否溢出画布
- 04将 HTML 幻灯片导出为 PDF 或 PPTX
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bluzir/ claude-code-design --skill make-deck安装后在 Claude Code 中输入/make-deck确认已加载。
详细介绍
制作幻灯片
构建一套经过精心设计、而非看起来像 AI 生成的 HTML 幻灯片。使用 starters/deck_stage.js 实现键盘导航、缩放、演讲者备注和打印为 PDF。
阶段 0 — 上下文预检(自动检测,最多提问 1 次)
提出设计问题之前,先通过自动检查静默检测上下文。只有在没有发现任何信息时,才询问用户。
自动检测(无需用户输入)
Read .claude/design-tokens.json— 如果存在,则加载项目设计令牌Bash(ls ~/.claude/design-systems/ 2>/dev/null)— 组织级注册表。如果需求中提到的品牌名称与某个文件夹匹配,则自动应用该设计系统(例如,需求中提到“Acme deck”,且存在~/.claude/design-systems/acme/→ 使用 Acme)- 在项目根目录执行
Glob **/tailwind.config.* **/theme.{ts,js,json} **/tokens.{css,scss} **/_variables.*— 如果找到文件,则记录“检测到代码库”并Read这些文件 - 扫描用户消息/附件,查找:
- GitHub URL → 先调用
Skill: ingest-github - Figma URL → 先调用
Skill: ingest-figma - 图像附件 → 先调用
Skill: ingest-screenshot - 附加的
.md/.txt/.pdf文件 →Read文件(其中可能包含品牌参考或内容)
- GitHub URL → 先调用
单问题回退方案(仅当未检测到任何信息时)
如果自动检测后仍未找到上下文,则使用 AskUserQuestion 提出一个问题,选项为文本:
- 使用现有设计系统 — 列出
~/.claude/design-systems/中的名称(如有) - 来自代码库 — “粘贴本地路径或 github URL”
- 来自截图 — “附加图像”
- 来自 Figma — “粘贴 figma URL(需要 FIGMA_TOKEN)”
- 无上下文 — 调用
Skill: frontend-design,从零开始设计美学风格 - 替我决定 — 由 Claude 选择 frontend-design
用一行报告找到或选择的内容:“正在使用。继续……”
阶段 1 — 模糊性检查
检查用户的需求($ARGUMENTS),查找以下信号:
- 受众 — “面向 X”“面向投资者”“团队”“利益相关者”等
- 风格 — 指定的美学风格(“New Yorker”“WSJ”“极简”“醒目”“类似 Apple”)或品牌参考
- 长度 — “N 张幻灯片”“简短”“快速”
如果三项中至少有两项 → 跳过长问卷,最多提出 1–2 个澄清问题后继续。
如果少于两项 → 调用 AskUserQuestion,询问:
- 受众(谁会观看、情绪状态、技术水平)
- 语气(正式/随意、幽默/严肃)
- 长度(幻灯片数量)
- 视觉效果(简约/丰富、照片/插图/图表)
- 方案选择(是否需要 2–3 套幻灯片方案,还是只要一套)
即使通过模糊性检查,只要仍有不明确之处,也至少提出 4 个相关问题。不要询问品牌背景——阶段 0 已处理。
阶段 1.5 — 演讲者备注启发式判断(由 Agent 决定,不提供开关)
不要询问用户“是否使用演讲者备注?”,而是根据以下信号判断:
| 需求中的信号 | → 演讲者备注 |
|---|---|
| “快速”“站会”“闪电演讲”“回顾”,或少于 100 个字符 | 关闭 — 幻灯片内容完整自足,不添加备注 |
| “面向投资者”“董事会会议”“主题演讲”“全员大会” | 开启 — 幻灯片内容精简,由备注承载叙述 |
| 附有 PRD/长文档(超过 500 词) | 开启 — 幻灯片提炼内容,备注提供讲稿 |
| 只要求 1–3 张幻灯片 | 关闭 |
| 要求 10 张或更多幻灯片 | 开启(可能需要故事线) |
| 模糊/以上信号都没有 | 提出一个是/否问题 |
如果开启:在 <body> 末尾生成 <script type="application/json" id="speaker-notes">[...]</script>,每张幻灯片对应一个字符串——采用完整、自然的口语叙述,而非项目符号摘要。幻灯片应以视觉内容为主。
如果关闭:完全跳过备注;幻灯片必须独立成篇。
阶段 2 — 视觉系统
根据阶段 0 收集的上下文,预先确定视觉系统:
- 章节标题版式、主标题版式、图像版式
- 整套幻灯片最多使用 1–2 种背景颜色
- 字体层级(展示字体/一级标题/正文/说明文字)
- 配色方案(使用已加载的设计令牌,或通过
Skill: frontend-design生成)
撰写幻灯片之前,先用一段话说明视觉系统。
阶段 3 — 构建
- 使用 shell 创建
artifacts/<slug>.html:<!doctype html> <html lang="en"> <head> <meta charset="utf-8"/> <title>{{deck title}}</title> <script src="./deck_stage.js"></script> <style>/* your tokens + slide styles */</style> </head> <body> <deck-stage width="1920" height="1080"> <section></section> ... </deck-stage> </body> </html> Bash(cp starters/deck_stage.js "$(dirname <html>)/")— 将 starter 复制到 与 HTML 相同的目录(对于artifacts/foo/deck.html这类嵌套路径尤其重要)- 一次性编写所有幻灯片。规则:
- 第 1 张幻灯片不能只有标题(直接进入内容)
- 在 1920×1080 画布上,文本字号 ≥ 24px
text-wrap: pretty- 使用 CSS Grid 布局
- 不使用渐变、表情符号或 Inter/Roboto/Arial — 选择有特色的字体
- 不使用 SVG 绘制图像 — 改用带标签的占位 div
- 在幻灯片间变换布局节奏(不要全部使用同一模板)
- 演讲者备注:遵循阶段 1.5 的决定 — 不要再次询问。
3.1 垂直空间预算 — 编写前先计算(!)
<deck-stage> 区段设置了 overflow: hidden — 溢出在视觉上不会提示,超出的内容会直接消失。必须提前做好垂直空间预算。
每张幻灯片的典型 chrome 布局会占用 1080px 画布约 430px:
| 项目 | 预留空间 |
|---|---|
| 区段顶部内边距 | 96px |
| Chrome 行(绝对定位,但有视觉分量) | 24px |
| Kicker 上边距 + Kicker | 44 + 22 = 66px |
h2.section-title(字号 80–96px × 2 行) | ~200px |
| h2 下边距 | 36px |
| 内容网格上边距 | 16px |
| 区段底部内边距 | 96px |
| 预留空间总计 | ~430px |
内容预算:1080 − 430 = ~650px。 内容区内的主要卡片、行或媒体容器都必须在此范围内。
严格限制,确保布局合理:
- 主要卡片
min-height:≤ 500px - 模拟界面之后的内容列/深度内容列
min-height:≤ 620px - 解剖结构行最多 5 行,每行约 110px;或 4 行,每行约 130px
- 简短的 h2(1 行,≤ 60 个字符)→ 可多出 140px 预算;较长的 h2(2 行)→ 按 200px 计算
- 如果需要更高的内容,请移除 Kicker,或将 Kicker 与 h2 合并到一行 — 不要让卡片变高
如果某张幻灯片显得太拥挤 — 拆分内容,或删减内容。溢出是设计问题,不是字体排版问题。
3.2 俄语/长词连字符处理
在 <section> 上设置 hyphens: manual; -webkit-hyphens: manual;,以防浏览器在单词中间插入软连字符(这会导致较窄列中的俄语长单词被拆行)。
阶段 4 — 验证
-
/done artifacts/<slug>.html— 在浏览器中打开,检查控制台并保存截图 -
修复所有错误;反复运行,直到没有问题
-
必须执行程序化溢出审计(如果任何幻灯片溢出或空间过紧,将无法结束本轮):
// Paste into mcp__chrome-devtools__evaluate_script async () => { const stage = document.querySelector('deck-stage'); if (!stage) return { skipped: 'no deck-stage' }; // Decoratives we deliberately ignore (bleed past section bounds by design): // glow halos, hero backdrops, chrome overlays, anything flagged data-decorative. const DECORATIVE = '.glow, .glow-2, .hero-glow, .chrome, [data-decorative], [aria-hidden="true"].backdrop'; const isDecorative = (el) => { if (el.matches(DECORATIVE) || el.closest(DECORATIVE)) return true; const cs = getComputedStyle(el); // pointer-events:none + no text + low opacity → visual decoration, skip if (cs.pointerEvents === 'none' && !el.textContent?.trim() && parseFloat(cs.opacity) < 1) return true; return false; }; const out = []; for (let i = 0; i < stage.totalSlides; i++) { stage.goToSlide(i); await new Promise(r => setTimeout(r, 80)); const s = stage.querySelectorAll('section')[i]; const sRect = s.getBoundingClientRect(); const scale = 1080 / sRect.height; // Measure ALL elements (including position:absolute like .arrow-between, .save-cta, // .footer-row that ARE meaningful content) — only decoratives are skipped. let maxBottom = 0, culprit = null; for (const el of s.querySelectorAll('*')) { if (isDecorative(el)) continue; const cs = getComputedStyle(el); if (cs.display === 'none' || cs.visibility === 'hidden') continue; const r = el.getBoundingClientRect(); if (r.height === 0 && r.width === 0) continue; const b = (r.bottom - sRect.top) * scale; if (b > maxBottom) { maxBottom = b; culprit = el.className?.toString?.().slice(0, 40) || el.tagName; } } const contentBottom = Math.round(maxBottom); const overflow = contentBottom - 1080; const headroom = 1080 - contentBottom; const status = overflow > 0 ? 'FAIL' : headroom < 40 ? 'WARN' : 'OK'; out.push({ slide: i + 1, contentBottom, overflow, headroom, status, culprit }); } stage.goToSlide(0); return out; }FAIL(overflow > 0)— 内容被裁切。不要声称已完成。 缩小卡片、字体或内边距,然后重新运行。WARN(headroom < 40px)— 内容在视觉上过于贴近边缘(字体度量稍有变化就可能导致裁切)。目标是至少留出 60px 的余量。OK— 可以交付。
常见修复方法:减小卡片的
min-height,缩小标题字号,删去一行,合并 Kicker 和标题,缩小垂直间距。如果浏览器显示溢出,但此脚本检测不到,请通过绕过缓存强制重新加载:
mcp__chrome-devtools__navigate_page({ type: "reload", ignoreCache: true })。这类不一致大多是因为最新一次Edit之前的 CSS 状态被缓存。 -
在后台静默调用
Skill: verify-artifact(检查布局视觉效果 — 检测到<deck-stage>时会自动处理每张幻灯片的截图) -
在本轮结束摘要中引用
.claude/last-preview.png
阶段 5 — 提供后续选项
/export-pptx artifacts/<slug>.html— 通过截图生成原生 PPTX/export-pdf artifacts/<slug>.html— PDF/export-standalone artifacts/<slug>.html <dist>.html— 单文件离线 HTML/register-asset artifacts/<slug>.html— 添加到assets.html概览- 演讲者备注模式 → 添加
<script type="application/json" id="speaker-notes">[...]</script> - 可调整模式 →
/make-tweakable artifacts/<slug>.html
反模式 — 严禁使用
- 首先展示标题幻灯片
- 填充内容
- AI 生成的劣质卡片样式(圆角 + 左侧边框强调)
- 通用渐变背景
- 编造数字或统计数据
- 编造颜色(使用
oklch()与现有调色板协调)