visual-deck
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesevisual-deck — 视觉版 PPT 生成
visual-deck — Visual PPT Generation
何时触发
When to Trigger
适用:
- 布道版 / 对外方案 / 内部分享类 PPT,版式优先、内容随图走
- 需要背景图 + 前景文字的「图+文」统一风格
- 单页信息密度高,但视觉需要干净
不适用:
- 纯数据报表、纯文字文档 → 用 docx/xlsx
- 临时一次性 PPT,不值得搭 pipeline → 直接用 pptx skill
- 客户方不接受 cinematic 风格 → 本 skill 的图像语言不匹配
Applicable Scenarios:
- Evangelism decks, client-facing proposals, internal sharing PPTs where layout takes priority and content follows the imagery
- Unified "image + text" style requiring background images with foreground text
- High information density per slide while maintaining a clean visual appearance
Inapplicable Scenarios:
- Pure data reports or text-heavy documents → Use docx/xlsx instead
- Temporary one-off PPTs where building a pipeline isn't worth it → Use the pptx skill directly
- Clients who don't accept cinematic style → The visual language of this skill doesn't match
三条硬约束(不可妥协)
Three Non-Negotiable Hard Constraints
这三条是踩过坑换来的,违反任何一条直接退回:
These are lessons learned from past mistakes; any violation will result in immediate rejection:
1. 文字只进安全区,溢出走 notes
1. Text Only in Safe Zones, Overflow Goes to Notes
- 每张 slide 都有天然的图像安全区(暗色区/留白区),前景文字只能排在里面
- 正文装不下时:不许缩字号,不许退回"全屏蒙版压字"。把溢出内容灌进
slide.addNotes() - 具体安全区%见
references/safe-zone-spec.md
- Each slide has a natural image safe zone (darkened/blank area); foreground text must be placed only within this zone
- When content doesn't fit: Never reduce font size, never revert to "full-screen mask over text". Pour overflow content into
slide.addNotes() - See for specific safe zone percentages
references/safe-zone-spec.md
2. Image prompt 必须 V2 四段式
2. Image Prompts Must Follow V2 Four-Segment Format
- 四段齐全
描述 / Composition / Style / Do not include - 安全区百分比写死在 Composition 段("top 15% / bottom 15% fade to void")
- 色彩用 token + hex 双写("warm coral, hex #FF6B47")
- 模板和示例见
references/image-prompts-v2.md
- All four segments must be complete
Description / Composition / Style / Do not include - Safe zone percentages are hardcoded in the Composition segment (e.g., "top 15% / bottom 15% fade to void")
- Colors are specified using both token and hex code (e.g., "warm coral, hex #FF6B47")
- See for templates and examples
references/image-prompts-v2.md
3. Nano Banana 比例有限
3. Nano Banana Has Aspect Ratio Limitations
- 支持:16:9 / 4:3 / 1:1 / 3:4 / 9:16
- 不支持 21:9 — 需要超宽时走变通(拼接 / 裁切 / HF 铺底 + 暗罩)
- 细则见
references/nano-banana-ratios.md
- Supported ratios: 16:9 / 4:3 / 1:1 / 3:4 / 9:16
- 21:9 is NOT supported — Use workarounds for ultra-wide needs (stitching / cropping / HF background + dark mask)
- See for details
references/nano-banana-ratios.md
完整 Pipeline
Complete Pipeline
image-prompts.md notes-map.js
│ │
▼ (Nano Banana) ▼
images/*.png 溢出文案映射
│ │
▼ (tools/scrim-bake.js) │
images/*-scrimmed.png │
│ │
▼ (CSS background) │
slides/*.html ──────────────► html2pptx.js ──► pptx
│
▼ preview
player.html + tools/check-overflow.js文件角色:
| 文件 | 作用 | 是否改 |
|---|---|---|
| HTML→PPTX 渲染器,处理定位/文字/图片/shape/overflow 检测 | 不改 |
| 构建入口。支持 | 改元信息(title/author/文件名) |
| 无依赖 HTML 播放器,键盘翻页 + 全屏 + 缩略图 | 可选:填 TITLES 供缩略图显示 |
| Sharp 把 scrim 暗罩烘进背景 PNG(HTML2PPTX 不认 CSS gradient) | 按项目填 PAIRS 数组 |
| Playwright 验证每页 ≤ 540px(preview 级别) | 不改 |
| 扫 | 不改 |
| 主题 token — | 换主题只改这里 |
| 版式骨架库(见下方决策树) | 复制后填内容 |
| 溢出文案映射 | 按需填 |
| 依赖(playwright / pptxgenjs / sharp) | 不改 |
| 必读 · HTML/CSS 合法子集 + 常见错误修复套路 | 不改 |
image-prompts.md notes-map.js
│ │
▼ (Nano Banana) ▼
images/*.png 溢出文案映射
│ │
▼ (tools/scrim-bake.js) │
images/*-scrimmed.png │
│ │
▼ (CSS background) │
slides/*.html ──────────────► html2pptx.js ──► pptx
│
▼ preview
player.html + tools/check-overflow.jsFile Roles:
| File | Purpose | Editable? |
|---|---|---|
| HTML→PPTX renderer, handles positioning/text/images/shapes/overflow detection | No |
| Build entry point. Supports | Yes (modify metadata: title/author/file name) |
| Dependency-free HTML player with keyboard navigation, fullscreen, and thumbnails | Optional (fill TITLES for thumbnail display) |
| Uses Sharp to bake scrim masks into background PNGs (HTML2PPTX doesn't recognize CSS gradients) | Yes (fill PAIRS array per project) |
| Uses Playwright to verify each slide ≤ 540px (preview level) | No |
| Scans for | No |
| Theme tokens — | Yes (modify only this file to change themes) |
| Layout skeleton library (see decision tree below) | Yes (copy and fill in content) |
| Overflow content mapping | Yes (fill as needed) |
| Dependencies (playwright / pptxgenjs / sharp) | No |
| Required Reading · Valid HTML/CSS subset + common error fixes | No |
版式决策树(选 layout 时走这个)
Layout Decision Tree (Follow This When Choosing a Layout)
问 1:这页是章节边界 / 封面 / 封底吗?
是 → slide-cover.html (HF)
否 → 继续
问 2:这页只有一句金句(≤40 字),别的都稀释它?
是 → slide-quote.html
否 → 继续
问 3:这页是"数字说话"(KPI / 成绩单 / 市场数据)?
是 → 只有一个核心数字?
是 → slide-quote.html(把数字放大成金句)
否(3~4 个并列数字)→ slide-stats.html
否 → 继续
问 4:这页是"按时间/阶段讲流程"?
是 → slide-timeline.html(3~5 个节点)
否 → 继续
问 5:这页是"对比/并列"?
是 → 几项?
2 项 → slide-2col.html(before/after, A/B)
3 项 → slide-3col.html(三段论)
4+ → 拆页或 stats
否 → 继续(下面是默认主力)
问 6:有一个核心视觉隐喻 + 2~4 条要点?
是 → 前后页已连续 r34 两次?
是 → slide-l34.html(换方向打破节奏)
否 → slide-r34.html(默认)
否 → 停下来想想这页要讲什么,版式够不够(不够再扩)
每次选完问自己:
- 前后三页是否都是同一个版式?→ 考虑切镜像或换 layout
- quote 页是否超过 3 页?→ 金句稀释了,降级成 r34版式目录(8 个):
| Layout | 用途 | 关键信号 |
|---|---|---|
| HF 全幅,封面/章节/封底 | 有背景图 + 大标题 |
| 居中金句 | 一句话,≤40 字 |
| 2×2 数字格子 | 3~4 个并列 KPI |
| 水平时间轴 | 3~5 阶段/节点 |
| 双栏对比 | 二元对比(A/B) |
| 三栏并列 | 三段论 / 三种 X |
| 右图 + 左文(主力) | 一个论点 + 2~4 bullet |
| 左图 + 右文(镜像) | 同 r34,但换方向 |
每个 layout 文件顶部有 / 注释,选不定就打开文件看。
USE WHENDO NOT USE WHEN问 1:这页是章节边界 / 封面 / 封底吗?
是 → slide-cover.html (HF)
否 → 继续
问 2:这页只有一句金句(≤40 字),别的都稀释它?
是 → slide-quote.html
否 → 继续
问 3:这页是"数字说话"(KPI / 成绩单 / 市场数据)?
是 → 只有一个核心数字?
是 → slide-quote.html(把数字放大成金句)
否(3~4 个并列数字)→ slide-stats.html
否 → 继续
问 4:这页是"按时间/阶段讲流程"?
是 → slide-timeline.html(3~5 个节点)
否 → 继续
问 5:这页是"对比/并列"?
是 → 几项?
2 项 → slide-2col.html(before/after, A/B)
3 项 → slide-3col.html(三段论)
4+ → 拆页或 stats
否 → 继续(下面是默认主力)
问 6:有一个核心视觉隐喻 + 2~4 条要点?
是 → 前后页已连续 r34 两次?
是 → slide-l34.html(换方向打破节奏)
否 → slide-r34.html(默认)
否 → 停下来想想这页要讲什么,版式够不够(不够再扩)
每次选完问自己:
- 前后三页是否都是同一个版式?→ 考虑切镜像或换 layout
- quote 页是否超过 3 页?→ 金句稀释了,降级成 r34Layout Directory (8 Types):
| Layout | Use Case | Key Signals |
|---|---|---|
| Full-screen HF, for covers/section dividers/back covers | Has background image + large title |
| Centered key quote | Single sentence, ≤40 characters |
| 2×2 grid of numbers | 3~4 parallel KPIs |
| Horizontal timeline | 3~5 stages/nodes |
| Two-column comparison | Binary comparison (A/B) |
| Three-column parallel | Three-part argument / three types of X |
| Right image + left text (main layout) | One argument + 2~4 bullet points |
| Left image + right text (mirror) | Same as r34, just reversed direction |
Each layout file has / comments at the top; open the file if you're unsure.
USE WHENDO NOT USE WHEN扩展约束(给未来的自己)
Extension Constraints (For Future Reference)
新增 layout / theme 前必须回答:
- 现有版式为什么不够?举一个具体 slide 说不通的场景。
- 新版式的 USE WHEN / DO NOT USE WHEN 分别是什么?
- 这条决策树改动后,是否让"选择更容易"而不是"更纠结"?
如果这三题任何一题答不清,这个版式就不该加。扁平地堆 layout 会让 Claude 面对 skill 时选择困难,信息结构 ≫ 选项数量。
新增 theme 同理:说清"为什么现有 dark-coral / dark-teal 不够"再加。
Must Answer These Before Adding New Layouts/Themes:
- Why are existing layouts insufficient? Provide a specific slide scenario where they don't work.
- What are the USE WHEN / DO NOT USE WHEN conditions for the new layout?
- Will modifying the decision tree make layout selection "easier" rather than "more confusing"?
If you can't answer any of these three questions clearly, this layout shouldn't be added. Piling up layouts flatly will make it difficult for Claude to choose when using this skill; information structure ≫ number of options.
Same applies to new themes: Only add after explaining "why existing dark-coral / dark-teal are insufficient".
标准执行流程
Standard Execution Process
- 明确主题与页数 — 先问用户:主题色系(默认暗色 CORAL)、页数、是否需要封面/目录/封底
- 先读契约 — ,了解 HTML/CSS 合法子集,避免撞雷
references/html2pptx-contract.md - 生成 HTML slides — 基于 骨架,每页先写 HTML
templates/layouts/ - preview 验证 — 用 翻页 +
templates/player.html跑 540px 硬边界node tools/check-overflow.js - 生成 image prompts — 按 V2 四段式格式,输出到 ,用户拿去 Nano Banana 批量跑
image-prompts.md - 收齐图片 + 烘 scrim — 把图放进 ,配置
images/里的 PAIRS,tools/scrim-bake.js烘出node tools/scrim-bake.js*-scrimmed.png - 先 lint — ,一次看齐所有 slide 的契约违规(不写 pptx)
node build.js --lint - 修违规 — 能机械修的跑 (把带 bg 的
node tools/fix-html-for-pptx.js自动包<p>);手动修余下的<div><p> - 填 notes-map.js — 溢出内容、口播补偿都进这里
- 出 pptx —
node build.js
- Clarify Theme and Slide Count — First ask the user: theme color scheme (default dark CORAL), number of slides, whether covers/table of contents/back covers are needed
- Read the Contract First — to understand the valid HTML/CSS subset and avoid pitfalls
references/html2pptx-contract.md - Generate HTML Slides — Write HTML for each slide based on the skeletons
templates/layouts/ - Preview Validation — Use for navigation + run
templates/player.htmlto verify the 540px hard boundarynode tools/check-overflow.js - Generate Image Prompts — Follow the V2 four-segment format and output to ; users will run these in batches via Nano Banana
image-prompts.md - Collect Images + Bake Scrims — Place images in , configure the PAIRS array in
images/, then runtools/scrim-bake.jsto generatenode tools/scrim-bake.js*-scrimmed.png - Run Lint First — to check all slides for contract violations in one go (no pptx output)
node build.js --lint - Fix Violations — Run for automated fixes (wrap
node tools/fix-html-for-pptx.jswith bg in<p>); manually fix remaining issues<div><p> - Fill notes-map.js — Put overflow content and supplementary speaking notes here
- Generate PPTX — Run
node build.js
关键陷阱(Claude 自己最容易犯的)
Key Pitfalls (Most Common for Claude)
HTML/CSS 契约违规(详见 ):
references/html2pptx-contract.md- ❌ 在元素上用 CSS gradient —— 必须 烘进 PNG
tools/scrim-bake.js - ❌ inline 上写
<span>—— 用margin-*或padding-*+ 父display: block<p> - ❌ /
<p>/<h1-6>有<ul>/background/border*—— 包box-shadow,或跑<div class="X"><p>...</p></div>自动修tools/fix-html-for-pptx.js - ❌ 里直接放文字(mixed content)—— 文字必须用
<div>等包起来<p> - ❌ 以
<p>/*/-起头 —— 被当成手动 bullet 拒收• - ❌ 内容塞到离 slide 底边 < 0.5"(36pt)—— 预览能过,build 不过。用 预检
--lint
其他常见坑:
- ❌ "字装不下就缩小到 10pt" —— 违反约束 1,必须 notes
- ❌ "这个图要 21:9 超宽" —— Nano Banana 不支持,要么 16:9 HF 裁掉两侧,要么拼图
- ❌ Image prompt 漏了 "Do not include" 段 —— 会生成文字/logo/水印污染
- ❌ HTML body 尺寸写错(非 for 16:9)——
720pt × 405pt会抛 dimension mismatch 错误html2pptx.js - ❌ 在 里硬编码页数 —— 用
build.js动态枚举fs.readdirSync('slides/')
HTML/CSS Contract Violations (See for details):
references/html2pptx-contract.md- ❌ Using CSS gradients on elements — Must bake into PNG via
tools/scrim-bake.js - ❌ Writing on inline
margin-*— Use<span>orpadding-*+ parentdisplay: block<p> - ❌ /
<p>/<h1-6>with<ul>/background/border*— Wrap inbox-shadowor run<div class="X"><p>...</p></div>for automated fixtools/fix-html-for-pptx.js - ❌ Directly placing text in (mixed content) — Text must be wrapped in
<div>or similar tags<p> - ❌ starting with
<p>/*/-— Will be rejected as manual bullets• - ❌ Content placed within < 0.5" (36pt) of the slide bottom edge — Preview may pass, but build will fail. Use for pre-check
--lint
Other Common Pitfalls:
- ❌ "Reduce font size to 10pt when content doesn't fit" — Violates Constraint 1; must use notes instead
- ❌ "This image needs to be 21:9 ultra-wide" — Not supported by Nano Banana; either crop to 16:9 HF or stitch images
- ❌ Missing "Do not include" segment in image prompts — Will result in text/logo/watermark contamination
- ❌ Incorrect HTML body size (not for 16:9) —
720pt × 405ptwill throw a dimension mismatch errorhtml2pptx.js - ❌ Hardcoding slide count in — Use
build.jsfor dynamic enumerationfs.readdirSync('slides/')
主题系统
Theme System
所有色彩/字体/字号/padding 都在 里作为 CSS 变量。每个 slide HTML 顶部 引用,内部 只用 ,不许写死 hex。
templates/themes/*.css<link rel="stylesheet" href="../themes/<theme>.css"><style>var(--xxx)可选主题:
- (默认) — 暖色,偏情感/洞察/人文调性
dark-coral.css - — 冷色,偏技术/架构/理性调性
dark-teal.css
切主题:改所有 slide HTML 里 的路径即可(或者全 deck 同一主题就用项目级 sed/find 一键替换)。
<link>换主题:只改 一个文件,所有 slide 跟着变。theme.css 末尾注释了暗色 TEAL / 浅色 NAVY 两套示例变量。
theme.css核心 token:
- — 底/正文/次/最弱/footer
--bg / --fg / --muted / --dim / --faint - — 主/副点缀色
--accent / --accent-2 - 、
--font-sans— 字体字号--fs-hero/title/subtitle/lede/body/label/source - — 三种 layout 的 padding
--pad-slide / --pad-r34 / --pad-l34 - — 暗罩透明度档位
--scrim-base / --scrim-left / --scrim-heavy
All colors/fonts/font sizes/padding are defined as CSS variables in . Each slide HTML references the theme via at the top; internal tags must only use — never hardcode hex values.
templates/themes/*.css<link rel="stylesheet" href="../themes/<theme>.css"><style>var(--xxx)Available Themes:
- (default) — Warm color scheme, suitable for emotional/insight/humanistic tones
dark-coral.css - — Cool color scheme, suitable for technical/architectural/rational tones
dark-teal.css
Switch Themes: Modify the path in all slide HTML files (or use project-level sed/find for one-click replacement if the entire deck uses the same theme).
<link>Customize Themes: Only modify the file; all slides will update accordingly. The end of theme.css includes commented example variables for dark TEAL and light NAVY schemes.
theme.cssCore Tokens:
- — Background/body text/secondary text/weakest text/footer
--bg / --fg / --muted / --dim / --faint - — Primary/secondary accent colors
--accent / --accent-2 - ,
--font-sans— Font family and sizes--fs-hero/title/subtitle/lede/body/label/source - — Padding for three layout types
--pad-slide / --pad-r34 / --pad-l34 - — Scrim opacity levels
--scrim-base / --scrim-left / --scrim-heavy
快速开始
Quick Start
看 —— 2 页可跑的最小例子。复制整个目录到新项目, 后 就有 pptx。
examples/minimal/npm installnode build.js推荐的改一页验证一次反馈循环:
bash
node tools/check-overflow.js # 1. 540px preview 硬边界
node build.js --lint # 2. 契约完整校验(所有违规一次列齐)
node build.js # 3. 真正出 pptxCheck — A 2-slide minimal working example. Copy the entire directory to a new project, run , then to generate the pptx.
examples/minimal/npm installnode build.jsRecommended Modify One Slide, Validate Once Feedback Loop:
bash
node tools/check-overflow.js # 1. 540px preview 硬边界
node build.js --lint # 2. 契约完整校验(所有违规一次列齐)
node build.js # 3. 真正出 pptx