SuperAPI AI 工具集

trmnl-dev

编程与开发

查看项目

更新于 10-15 11:08

技能介绍

TRMNL Dev 是一套经过实践检验的知识集合,用于端到端地构建、更新和运营 TRMNL 电子墨水屏私有插件。它既涵盖官方文档所述内容,也补充了文档未提及的坑点,例如渲染几何裁剪、MCP 的怪异行为、CSS 级联层以及载荷字节限制。

心智模型

TRMNL 是服务端渲染的电子墨水设备。设备主动轮询,没有任何内容被推送到设备。数据源通过 webhook POST 更新合并变量,标记编辑器或 MCP 编辑 Liquid 模板,二者汇合后由 TRMNL 渲染成 PNG,设备唤醒后下载图像再休眠。

存在两条相互独立的更新路径,切勿混淆:

  • 改变屏幕显示内容:生成 JSON,POST 到插件 webhook。webhook 只更新合并变量,从不改变标记。
  • 改变屏幕外观:编辑 Liquid 标记,保存、预览、强制刷新。标记编辑器本身不会获取新数据。

webhook 提交会在约 2 秒内触发服务端重新渲染,但物理设备只在下一次唤醒时显示(默认每 15 分钟一次)。服务端提交不会唤醒设备,也不消耗电池。

密钥与标识符

  • 设备 API key:不透明令牌,在 Devices → Edit 中找到,用于 /api/display 和 /api/current_screen 的 access-token 请求头。
  • 账户 API key:形如 user_…,在账户设置中找到,用于账户 API(设备、播放列表)的 Authorization: Bearer 请求头。
  • 插件 Settings UUID:webhook URL 中的 UUID,首次保存插件时生成,webhook POST 到 /api/custom_plugins/<uuid>。
  • 插件 MCP key:形如 ps_mcp_…,保存后在插件设置页右侧找到,用于 https://trmnl.com/mcp?api_key=…。

MCP key 是按插件隔离的:它只能读写该插件的标记、设置和合并变量,无法控制设备、播放列表、电池、截图或预览,也不会泄露插件 UUID 或 webhook URL。设备或播放列表相关工作应改用账户 API。所有真实值应保存在环境变量或操作系统钥匙串中,绝不提交到文件。webhook URL 本身应视为机密,持有它的人就能写入你的屏幕。

Webhook 数据更新

载荷结构:所有内容位于顶层 merge_variables 之下。示例:

curl "https://trmnl.com/api/custom_plugins/${TRMNL_PLUGIN_UUID}"
-H "Content-Type: application/json"
-X POST
-d '{"merge_variables":{"headline":"Hello TRMNL","items":[{"time":"09:00","title":"Standup"}]}}'

硬性限制(标准档):请求体 2 KB,每小时 12 次提交(TRMNL+ 为 5 KB、每小时 30 次)。发送过快会返回 429。插件“Debug Logs”模式在开发期间会临时提高限制。

避免麻烦的规则:只发送精简后的显示文本(如 {"time","title"}),绝不发送上游 API 原始输出,否则会超出字节限制并泄露不必要的数据。在真实限制之下设置本地护栏(例如 2 KB 档位用 1900 字节),并让生成器降级而非失败:削减行数并渲染诚实的“+ N more”标签,而不是抛错或静默裁剪。模板循环上限应不低于生成器上限,否则模板 limit 低于生成器发送量会静默丢弃条目。有状态更新:merge_strategy: "deep_merge" 可修补嵌套键;merge_strategy: "stream" 配合 stream_limit 可向顶层数组追加并限制增长。存储数据仍须符合大小限制。对同一 webhook URL 发起 GET 可获取当前存储的合并变量。

标记要点

完整几何与 CSS 细节及其引发的 bug 见 references/framework.md。不可违背的要点:始终按 800x480 创作。TRMNL X 以 4 位(16 级灰度)渲染 1040x780,但框架会自动缩放你的 800x480 标记(scale_factor: 1.8)。切勿硬编码原生分辨率。每个视图一个 <div class="layout">…</div>,可选同级 <div class="title_bar">。切勿在 .layout 内嵌套 .layout。不要把 .screen/.view 包装器粘贴到 TRMNL 编辑器中,那些仅用于离线预览。框架将 .layout 尺寸设为 screen-h − 2×gap(10 px 边框内为 460 px;有 title_bar 时更小)。若使用自定义根元素代替 .layout,必须复制该高度:height: calc(var(--screen-h, 480px) - var(--gap, 10px) * 2)。height: 100% 会在 460 px 盒子内渲染 480 px 并裁剪底部约 20 px。省略 title_bar 是合法且常常正确的(它占用约 35 px)。不带 title_bar 保存标记会触发“Missing title_bar include”警告,这是预期行为,可忽略。plugins.css 使用 CSS 级联层:带层的 !important 会胜过你无层的 !important 和内联样式。你无法通过提高特异性覆盖框架的尺寸设定,应采纳其变量(--screen-h、--gap、--full-w)或类。私有插件标记中允许自定义 <style> 块,但 TRMNL 应用内 AI 代理强制“无自定义样式”,若要求它“改进”会压平你的设计。请保留本地文件作为唯一事实来源。电子墨水可读性:相信物理设备而非任何浏览器预览。存疑时——更大字号、2 px 线条(1 px 细线在远处会消失)、font-feature-settings: "tnum" 1 对齐时间,远距离阅读的屏幕正文字号不要低于约 19 px,改用两列。

每插件 MCP

完整工具表、curl 配方和所有坑点见 references/mcp.md。要点:端点 https://trmnl.com/mcp?api_key=… 是无状态 JSON-RPC over HTTP,直接调用 tools/list / tools/call,无需 initialize 握手。工具名是 PascalCase 加 Tool 后缀(MarkupsWriteTool),不是应用内代理的 snake_case 名称。snake_case 会返回 Tool not found。MarkupsWriteTool 接受 {size, content},传 markup 而非 content 会返回无用的 -32603 Internal error。MCP 盲写标记(不存在截图/预览工具)。安全写入流程:读取线上 → 备份 → 写入 → 读回 → 反转义 → 与本地源比较。在编辑器预览器或离线测试环境中目视验证。

离线预览

在 TRMNL 官方 CSS/JS 包装器内用示例数据本地渲染 Liquid 模板,然后对 .screen 元素截图(精确 800x480)。完整配方与陷阱见 references/preview.md。离线迭代直到布局正确,再推送标记。包含最坏情况示例载荷(最大行数、最长标题),忙碌的日子才是布局出问题的时候。

电池与刷新节奏

插件刷新(服务端)与设备唤醒(电池)是分开的。webhook 提交免费;设备唤醒消耗电池(WiFi + 获取 + 电子纸刷新)。睡眠模式是最容易的优化:22:00–06:00 睡眠、15 分钟节奏可避免每天约 32 次唤醒。节奏应与内容匹配:由每日/每小时数据驱动的仪表盘很少需要全天 15 分钟刷新。合理配置:早高峰 15–30 分钟,中午 60 分钟,傍晚 30–60 分钟,夜间睡眠。/api/display(设备密钥)会推进播放列表,不要用它做监控轮询;应少量使用 /api/current_screen。

故障排查

  • 预览渲染为空:先 POST 一个小载荷;确认 strategy = Webhook;载荷位于 merge_variables 下;插件已保存一次(UUID 存在)。
  • 屏幕底部被裁剪:自定义根元素缺少 calc(var(--screen-h) - var(--gap)*2) 高度;或忘记为 title_bar 预留空间。
  • 物理设备比预览差:相信设备——更大字号、更少显示字体、显式网格列、更粗线条。
  • Webhook 429:超出每小时提交上限——批量更新;开发期间启用 Debug Logs。
  • 渲染缺少条目:模板 limit 低于载荷内容;或载荷超出字节上限且生成器削减了行。
  • MCP Tool not found:使用了 snake_case;应使用 PascalCase + Tool 后缀。
  • MCP 写入 -32603 Internal error:传了 markup;参数应为 content。
  • MCP 读回与本地文件不符:信封转义了 \n/"/\,比较前先反转义。
  • 编辑器保存“Missing title_bar include”警告:有意省略标题栏时的预期行为,忽略即可。

文档链接

文档索引:https://docs.trmnl.com/go/llms.txt Webhooks:https://docs.trmnl.com/go/private-plugins/webhooks.md 模板:https://docs.trmnl.com/go/private-plugins/templates.md Framework 3.1:https://trmnl.com/framework/docs/3.1/v3_overview.md TRMNL X 指南:https://trmnl.com/framework/docs/3.1/trmnl_x_guide 原生插件标记示例:https://github.com/usetrmnl/plugins/