bento-slides:用 Agent 生成单文件 Bento 演示稿

前言

做演示稿最常见的两种做法,成本都不低:一是让模型直接输出 Markdown,再手动粘进 Keynote / PPT 排版;二是先用 JS 画库搭一套幻灯片脚手架,再逐页写组件。前者丢掉了布局,后者要先花时间把工程搭起来。

bento-slides 这个 Skill 走的是第三条路:演示稿就是一个 .bento.html 单文件,文档本体是一段纯 JSON,写在 #bento-doc 的 script 块里。Agent 负责把这坨 JSON 写出来,浏览器打开即得成品,不需要装任何工具,也不需要在文件里引入依赖。

下面介绍它的定位、能力、安装方式和使用中容易踩的地方。

这是什么

bento-slides 是 Bento(bento.page)官方为 AI Agent 提供的演示文稿写作指南打包成的 Skill。它把 bento.page/agents.md 里的格式规范、元素清单和复制即用的配方(morph 过渡、图表、状态页、ken-burns、运动路径)收进一个 SKILL.md,让 Agent 能直接产出可运行的 deck。

SkillHub 上另有一个同名社区版,坐标 @user_5ee3f67c/bento-slides,版本 1.0.0,发布者 user_5ee3f67c,来源标记为 community,分类 office-efficiency,标签 requires_api_key=false(无需 API Key)。该页自述是「基于 bento slides 官方给 Claude Code 的 skill,改造为适用于 CodeBuddy、Workbuddy 的 skills,并加入了本地缓存能力」。

需要说明的是,本轮写作时该 SkillHub 页面(api.skillhub.cn/user_5ee3f67c/bento-slides 与 skillhub.cn/skills/user_5ee3f67c/bento-slides)均抓取失败,其自述的改造细节和安装方式无法二次核对,下面正文以 Bento 官方文档为准。

核心能力

  1. 从零开始:当前目录没有 .bento.html 时,Skill 会自己下载最新版 Bento 应用,直接在空文件里写文档。用户不需要预先安装 Bento——应用本身已经打包在 deck 文件里。
  2. 就地编辑现有 deck:定位 #bento-doc 块、解析 JSON、改写,其余文件内容(压缩后的运行时)一字不动。
  3. 内容到特性的映射:这是它和「把文字贴到幻灯片」最关键的区别。官方给出的对应关系是:
    - 需要视觉比较的数字 → chart 元素
    - 对比 / 规格 / 定价 / 功能网格 → table 元素
    - 同一对象在连续页面中变化 → morph:共用元素 id + 后一页 transition:"morph"
    - 需要下钻的点 → state slide(stateOf + 元素 link)
    - 全屏主图 → 铺满图片 + scrim 矩形 + 文字,配 ken-burns 缓推
    - 顺序 / 流程 / 时间线 → 带 dash-march 循环的线或 path
    - 头号数字 → 大号文本 + fx:{countUp:true}
    - 封面与章节页 → 至少一处环境动效
  4. 自我检查清单:完成前逐项核对——数字是否该用图表、连续页是否共用 id 做 morph、封面是否有动效、是否该用 state slide、配色是否单色系、每页是否写了 speaker notes。

文档格式

一个 deck 就是一个自包含的 HTML 文件,文档放在靠近顶部的唯一文本块里:

<script type="application/bento+json" id="bento-doc">
{ "format": "bento/slides", ... }
</script>

两份资料给出的版本信息一致:agents.md 标注 Guide version 1.2.10,文档格式 bento/slides (v1)。

编辑时遵守两条硬规则:

  1. JSON 中所有 < 必须转义成 \u003c,避免块内出现字面量 </script> 提前闭合脚本。
  2. 只改这一个块,不要重新生成整个 HTML 文件。

在没有文件载体的聊天环境里,改用复制粘贴:用户通过 Save → Copy document JSON 取出 JSON,Agent 返回完整替换文档,用户用 Save → Replace from JSON… 贴回(可撤销)。浏览器控制台里也可以用 window.bento.doc 读取、window.bento.loadDoc(json) 写入。

安装与启用

Bento 官方给出的安装方式分几种,按使用环境选择。

Claude Code 用插件方式装,一条命令:

/plugin marketplace add nyblnet/bento
/plugin install bento-slides@bento

或者当普通个人 Skill 装:

mkdir -p ~/.claude/skills/bento-slides && curl -fsSL https://bento.page/skills/bento-slides/SKILL.md -o ~/.claude/skills/bento-slides/SKILL.md

claude.ai / Claude Desktop 没有本地目录,改为上传 zip:https://bento.page/skills/bento-slides.zip,在 Settings → Skills 里添加。

不装 Skill、直接手工干活时,先下载应用文件,这就是你要写入文档的文件:

curl -fsSL https://bento.page/releases/slides/Bento_Slides.bento.html -o "<Topic>.bento.html"

Windows 没有 curl 时:

iwr https://bento.page/releases/slides/Bento_Slides.bento.html -OutFile <Topic>.bento.html

下载下来的文件,#bento-doc 块是空的。这是正常的:在浏览器里首次打开它会生成一份示例 deck 帮新用户上手,但磁盘上的文件里没有任何可丢弃或可复制的内容,直接往空块里写文档即可。

装完确认两件事:文件里存在 id="bento-doc";写文档前先抓 https://bento.page/agents.md,从其中的「Minimal valid document」骨架起步。

典型用法

从空目录起步

1、确认当前目录没有 .bento.html,执行上面的 curl 下载,文件名跟主题走,例如 Q4_Review.bento.html。
2、抓取 bento.page/agents.md,用其中的最小骨架填出文档。size 和 theme(含 theme.fontFamily)是必填项,缺了应用起不来。
3、元素字段要写全:形状要有 stroke / strokeWidth,文本要有 fontFamily / align / valign。字段缺失要么渲染不出来,要么位置是错的。
4、docId 和 collab 整体省略,首次打开时应用会自己签发新身份。
5、写完用 open(macOS)/ xdg-open(Linux)/ start(Windows)打开,文件会直接进入编辑器。

编辑已有 deck

工作流固定为:

1、定位 #bento-doc 块并解析 JSON,记下 doc.size(标准 1280×720)、doc.theme、已有元素 id,以及 doc.template / doc.readonly 是否设置。
2、读用户给的素材,逐块分类——是数据、表格、流程、待展开的定义,还是图片。
3、按上面「内容到特性」的映射选元素,不要默认成项目符号文本。
4、对照 schema 写作,保持一个强调色、最多 2 种字体、左右各 96px 边距(最右侧 x ≤ 1184),每页写 speaker notes。
5、按自检清单过一遍。
6、把编辑后的 #bento-doc 块写回(转义 <),或返回替换用的完整 JSON。

morph 配方

morph 是 Bento 最标志性的用法,前提是两页里共用同一个 id。下面这段是官方配方的骨架:第一页的标题和色条各有一个 id;第二页沿用相同 id、改掉坐标尺寸,并把 transition 设为 "morph",元素就会平滑滑过去而不是硬切。

{ "id":"s1","transition":"none","elements":[
  { "id":"headline","type":"text","x":96,"y":140,"w":900,"h":200,"html":"Big claim.","fontSize":120,"fontWeight":900,"color":"#111","align":"left","valign":"top","lineHeight":1,"rotation":0,"opacity":1 },
  { "id":"bar","type":"shape","shape":"rect","x":96,"y":380,"w":320,"h":16,"fill":"#E8442E","stroke":"none","strokeWidth":0,"radius":0,"rotation":0,"opacity":1 } ] }

{ "id":"s2","transition":"morph","elements":[
  { "id":"headline","type":"text","x":96,"y":84,"w":500,"h":80,"html":"Big claim.","fontSize":40,"fontWeight":900,"color":"#888","align":"left","valign":"top","lineHeight":1,"rotation":0,"opacity":1 },
  { "id":"bar","type":"shape","shape":"rect","x":96,"y":170,"w":16,"h":450,"fill":"#E8442E","stroke":"none","strokeWidth":0,"radius":0,"rotation":0,"opacity":1 } ] }

图表数据写法

柱状图和折线图的 data 必须是纯数字数组。写成 {value, ...} 这样的对象会被强制转成 0;只有饼图接受 {name, value} 形式。配色按系列来,不要逐条设置。option 里只能是纯 JSON 加模板占位符({b} / {c} / {d}),不能出现函数。

注意事项与坑

协作密钥会随文件走。 如果文档开了实时协作,#bento-doc 里会带 collab 密钥(房间号、可能还有 writer / owner 私钥)。这是设计如此——文件本身就是邀请函,谁拿到文件谁就能加入房间。后果在于:文档看起来完全不像凭证,但任何收到文件或 JSON 的地方(聊天、工单、harness、模型厂商的日志)都等于拿到了房间入口。所以动手前先检查 collab 键:没有它,或者有它但没有 ownerPriv / writerPriv / invite,就没有泄露风险;有这些字段时,先告知用户再继续,因为只有他能决定,而且他可能不知道这份 deck 处于共享状态。更稳妥的做法是用只读副本(Save ▾ → Save read-only copy…)或在副本上 Share → Stop sharing。浏览器里 window.bento.validate() 会把它报成 collab-secrets-present。

需要强调:在文件里编辑 JSON 不改变上述暴露面,风险在读文件而不在写;事后把密钥删掉也不等于撤回——已经外发的文件,补救办法是 Share → Rotate keys。

其他几个容易踩的点:

  • 编辑已有 deck 时不要重新生成 docId,它是文档的身份标识;新 deck 则整体省略,由应用签发。
  • 图片和字体必须作为 data URI 嵌入 doc.assets,元素里用 "asset:<key>" 引用,文件才能保持自包含。
  • media 元素(kind: video|audio)短片段用 data URI 嵌入,大文件用 URL 引用以控制体积;autoplay 只在演示模式生效,视频还需要 muted:true。不要嵌入大视频。
  • template:true 表示每次打开都生成一份新 deck;readonly:true 表示文件直接进入放映模式、不出编辑器。
  • 打开文件后逐页看一遍再报告完成。文字溢出、元素挤在一起、标题折成三行、图表某个 key 被渲染器丢弃,这些在 JSON 里看不出来,在屏幕上一目了然。做法是:写、渲染、检查、修。

适用场景

适合需要直接产出可放映文件、且希望页面之间有动效而非静态文字页的场景,尤其是从零开始、手上只有大纲或素材文档的情况。它不依赖任何在线服务,产物单文件可分发,配合实时协作时分享文件本身即完成邀请。

不适合需要复杂动画编排、逐帧控制或作为静态页面嵌入网站的场景;也不适合需要多个应用(Spaces、Dash)协作的场合——Bento 是一套应用,Slides 只是其中之一,本 Skill 只覆盖 Slides。编辑文件前先看它的 "format" 字段,用对应的指南;遇到没有指南的格式,不要猜结构。

官方地址:https://api.skillhub.cn/user_5ee3f67c/bento-slides ;格式规范与配方见 https://bento.page/agents.md 。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜