visual-deck

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

visual-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
    references/safe-zone-spec.md
    for specific safe zone percentages

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
    Description / Composition / Style / Do not include
    must be complete
  • 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
    references/image-prompts-v2.md
    for templates and examples

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
    references/nano-banana-ratios.md
    for details

完整 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
文件角色
文件作用是否改
pipeline/html2pptx.js
HTML→PPTX 渲染器,处理定位/文字/图片/shape/overflow 检测不改
templates/build.js
构建入口。支持
--lint
(只校验不出 pptx)/
--strict
(首错即停)
改元信息(title/author/文件名)
templates/player.html
无依赖 HTML 播放器,键盘翻页 + 全屏 + 缩略图可选:填 TITLES 供缩略图显示
templates/tools/scrim-bake.js
Sharp 把 scrim 暗罩烘进背景 PNG(HTML2PPTX 不认 CSS gradient)按项目填 PAIRS 数组
templates/tools/check-overflow.js
Playwright 验证每页 ≤ 540px(preview 级别)不改
templates/tools/fix-html-for-pptx.js
<p class="...">
有 background/border 的,自动转
<div><p>...</p></div>
不改
templates/themes/*.css
主题 token —
dark-coral.css
(默认)/
dark-teal.css
换主题只改这里
templates/layouts/*.html
版式骨架库(见下方决策树)复制后填内容
templates/notes-map.js
溢出文案映射
{ slideNum: "notes..." }
按需填
templates/package.json
依赖(playwright / pptxgenjs / sharp)不改
references/html2pptx-contract.md
必读 · 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.js
File Roles:
FilePurposeEditable?
pipeline/html2pptx.js
HTML→PPTX renderer, handles positioning/text/images/shapes/overflow detectionNo
templates/build.js
Build entry point. Supports
--lint
(validation only, no pptx output) /
--strict
(stop on first error)
Yes (modify metadata: title/author/file name)
templates/player.html
Dependency-free HTML player with keyboard navigation, fullscreen, and thumbnailsOptional (fill TITLES for thumbnail display)
templates/tools/scrim-bake.js
Uses Sharp to bake scrim masks into background PNGs (HTML2PPTX doesn't recognize CSS gradients)Yes (fill PAIRS array per project)
templates/tools/check-overflow.js
Uses Playwright to verify each slide ≤ 540px (preview level)No
templates/tools/fix-html-for-pptx.js
Scans for
<p class="...">
with background/border and automatically wraps them in
<div><p>...</p></div>
No
templates/themes/*.css
Theme tokens —
dark-coral.css
(default) /
dark-teal.css
Yes (modify only this file to change themes)
templates/layouts/*.html
Layout skeleton library (see decision tree below)Yes (copy and fill in content)
templates/notes-map.js
Overflow content mapping
{ slideNum: "notes..." }
Yes (fill as needed)
templates/package.json
Dependencies (playwright / pptxgenjs / sharp)No
references/html2pptx-contract.md
Required Reading · Valid HTML/CSS subset + common error fixesNo

版式决策树(选 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用途关键信号
slide-cover.html
HF 全幅,封面/章节/封底有背景图 + 大标题
slide-quote.html
居中金句一句话,≤40 字
slide-stats.html
2×2 数字格子3~4 个并列 KPI
slide-timeline.html
水平时间轴3~5 阶段/节点
slide-2col.html
双栏对比二元对比(A/B)
slide-3col.html
三栏并列三段论 / 三种 X
slide-r34.html
右图 + 左文(主力)一个论点 + 2~4 bullet
slide-l34.html
左图 + 右文(镜像)同 r34,但换方向
每个 layout 文件顶部有
USE WHEN
/
DO 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 页?→ 金句稀释了,降级成 r34
Layout Directory (8 Types):
LayoutUse CaseKey Signals
slide-cover.html
Full-screen HF, for covers/section dividers/back coversHas background image + large title
slide-quote.html
Centered key quoteSingle sentence, ≤40 characters
slide-stats.html
2×2 grid of numbers3~4 parallel KPIs
slide-timeline.html
Horizontal timeline3~5 stages/nodes
slide-2col.html
Two-column comparisonBinary comparison (A/B)
slide-3col.html
Three-column parallelThree-part argument / three types of X
slide-r34.html
Right image + left text (main layout)One argument + 2~4 bullet points
slide-l34.html
Left image + right text (mirror)Same as r34, just reversed direction
Each layout file has
USE WHEN
/
DO NOT USE WHEN
comments at the top; open the file if you're unsure.

扩展约束(给未来的自己)

Extension Constraints (For Future Reference)

新增 layout / theme 前必须回答
  1. 现有版式为什么不够?举一个具体 slide 说不通的场景。
  2. 新版式的 USE WHEN / DO NOT USE WHEN 分别是什么?
  3. 这条决策树改动后,是否让"选择更容易"而不是"更纠结"?
如果这三题任何一题答不清,这个版式就不该加。扁平地堆 layout 会让 Claude 面对 skill 时选择困难,信息结构 ≫ 选项数量。
新增 theme 同理:说清"为什么现有 dark-coral / dark-teal 不够"再加。
Must Answer These Before Adding New Layouts/Themes:
  1. Why are existing layouts insufficient? Provide a specific slide scenario where they don't work.
  2. What are the USE WHEN / DO NOT USE WHEN conditions for the new layout?
  3. 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

  1. 明确主题与页数 — 先问用户:主题色系(默认暗色 CORAL)、页数、是否需要封面/目录/封底
  2. 先读契约
    references/html2pptx-contract.md
    ,了解 HTML/CSS 合法子集,避免撞雷
  3. 生成 HTML slides — 基于
    templates/layouts/
    骨架,每页先写 HTML
  4. preview 验证 — 用
    templates/player.html
    翻页 +
    node tools/check-overflow.js
    跑 540px 硬边界
  5. 生成 image prompts — 按 V2 四段式格式,输出到
    image-prompts.md
    ,用户拿去 Nano Banana 批量跑
  6. 收齐图片 + 烘 scrim — 把图放进
    images/
    ,配置
    tools/scrim-bake.js
    里的 PAIRS,
    node tools/scrim-bake.js
    烘出
    *-scrimmed.png
  7. 先 lint
    node build.js --lint
    ,一次看齐所有 slide 的契约违规(不写 pptx)
  8. 修违规 — 能机械修的跑
    node tools/fix-html-for-pptx.js
    (把带 bg 的
    <p>
    自动包
    <div><p>
    );手动修余下的
  9. 填 notes-map.js — 溢出内容、口播补偿都进这里
  10. 出 pptx
    node build.js
  1. 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
  2. Read the Contract First
    references/html2pptx-contract.md
    to understand the valid HTML/CSS subset and avoid pitfalls
  3. Generate HTML Slides — Write HTML for each slide based on the
    templates/layouts/
    skeletons
  4. Preview Validation — Use
    templates/player.html
    for navigation + run
    node tools/check-overflow.js
    to verify the 540px hard boundary
  5. Generate Image Prompts — Follow the V2 four-segment format and output to
    image-prompts.md
    ; users will run these in batches via Nano Banana
  6. Collect Images + Bake Scrims — Place images in
    images/
    , configure the PAIRS array in
    tools/scrim-bake.js
    , then run
    node tools/scrim-bake.js
    to generate
    *-scrimmed.png
  7. Run Lint First
    node build.js --lint
    to check all slides for contract violations in one go (no pptx output)
  8. Fix Violations — Run
    node tools/fix-html-for-pptx.js
    for automated fixes (wrap
    <p>
    with bg in
    <div><p>
    ); manually fix remaining issues
  9. Fill notes-map.js — Put overflow content and supplementary speaking notes here
  10. Generate PPTX — Run
    node build.js

关键陷阱(Claude 自己最容易犯的)

Key Pitfalls (Most Common for Claude)

HTML/CSS 契约违规(详见
references/html2pptx-contract.md
):
  • ❌ 在元素上用 CSS gradient —— 必须
    tools/scrim-bake.js
    烘进 PNG
  • ❌ 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
    自动修
  • <div>
    里直接放文字(mixed content)—— 文字必须用
    <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 尺寸写错(非
    720pt × 405pt
    for 16:9)——
    html2pptx.js
    会抛 dimension mismatch 错误
  • ❌ 在
    build.js
    里硬编码页数 —— 用
    fs.readdirSync('slides/')
    动态枚举
HTML/CSS Contract Violations (See
references/html2pptx-contract.md
for details):
  • ❌ Using CSS gradients on elements — Must bake into PNG via
    tools/scrim-bake.js
  • ❌ Writing
    margin-*
    on inline
    <span>
    — Use
    padding-*
    or
    display: block
    + parent
    <p>
  • <p>
    /
    <h1-6>
    /
    <ul>
    with
    background
    /
    border*
    /
    box-shadow
    — Wrap in
    <div class="X"><p>...</p></div>
    or run
    tools/fix-html-for-pptx.js
    for automated fix
  • ❌ Directly placing text in
    <div>
    (mixed content) — Text must be wrapped in
    <p>
    or similar tags
  • <p>
    starting with
    *
    /
    -
    /
    — 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
    --lint
    for pre-check
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
    720pt × 405pt
    for 16:9) —
    html2pptx.js
    will throw a dimension mismatch error
  • ❌ Hardcoding slide count in
    build.js
    — Use
    fs.readdirSync('slides/')
    for dynamic enumeration

主题系统

Theme System

所有色彩/字体/字号/padding 都在
templates/themes/*.css
里作为 CSS 变量。每个 slide HTML 顶部
<link rel="stylesheet" href="../themes/<theme>.css">
引用,内部
<style>
只用
var(--xxx)
不许写死 hex
可选主题
  • dark-coral.css
    (默认) — 暖色,偏情感/洞察/人文调性
  • dark-teal.css
    — 冷色,偏技术/架构/理性调性
切主题:改所有 slide HTML 里
<link>
的路径即可(或者全 deck 同一主题就用项目级 sed/find 一键替换)。
换主题:只改
theme.css
一个文件,所有 slide 跟着变。theme.css 末尾注释了暗色 TEAL / 浅色 NAVY 两套示例变量。
核心 token
  • --bg / --fg / --muted / --dim / --faint
    — 底/正文/次/最弱/footer
  • --accent / --accent-2
    — 主/副点缀色
  • --font-sans
    --fs-hero/title/subtitle/lede/body/label/source
    — 字体字号
  • --pad-slide / --pad-r34 / --pad-l34
    — 三种 layout 的 padding
  • --scrim-base / --scrim-left / --scrim-heavy
    — 暗罩透明度档位
All colors/fonts/font sizes/padding are defined as CSS variables in
templates/themes/*.css
. Each slide HTML references the theme via
<link rel="stylesheet" href="../themes/<theme>.css">
at the top; internal
<style>
tags must only use
var(--xxx)
never hardcode hex values.
Available Themes:
  • dark-coral.css
    (default) — Warm color scheme, suitable for emotional/insight/humanistic tones
  • dark-teal.css
    — Cool color scheme, suitable for technical/architectural/rational tones
Switch Themes: Modify the
<link>
path in all slide HTML files (or use project-level sed/find for one-click replacement if the entire deck uses the same theme).
Customize Themes: Only modify the
theme.css
file; all slides will update accordingly. The end of theme.css includes commented example variables for dark TEAL and light NAVY schemes.
Core Tokens:
  • --bg / --fg / --muted / --dim / --faint
    — Background/body text/secondary text/weakest text/footer
  • --accent / --accent-2
    — Primary/secondary accent colors
  • --font-sans
    ,
    --fs-hero/title/subtitle/lede/body/label/source
    — Font family and sizes
  • --pad-slide / --pad-r34 / --pad-l34
    — Padding for three layout types
  • --scrim-base / --scrim-left / --scrim-heavy
    — Scrim opacity levels

快速开始

Quick Start

examples/minimal/
—— 2 页可跑的最小例子。复制整个目录到新项目,
npm install
node build.js
就有 pptx。
推荐的改一页验证一次反馈循环:
bash
node tools/check-overflow.js   # 1. 540px preview 硬边界
node build.js --lint           # 2. 契约完整校验(所有违规一次列齐)
node build.js                  # 3. 真正出 pptx
Check
examples/minimal/
— A 2-slide minimal working example. Copy the entire directory to a new project, run
npm install
, then
node build.js
to generate the pptx.
Recommended 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