首页 / 全部技能 / 设计 / social-spotify-card
设计 · nexu-io/html-anything

social-spotify-card

Spotify Now Playing 风格卡: 专辑封面 + 进度条 + 播放控制, 适配视频叠加 / 个人主页

L3 联网 · 声明域名与密钥范围V1 已固定联网Dual-pass Audit
Author nexu-ioGitHub nexu-io/html-anything ↗Stars 8827License Apache-2.0(仓库根 LICENSE = Apache License 2.0;GitHub API spdx_id=Apache-2.0)Commit 553ed98c28
管控等级描述 skill 的能力与建议配套的管控措施,不代表质量或安全认证,也不表示可用或不可用。是否使用由用户和管理者决定。不同 agent 宿主对权限的约束各不相同,请勿假定宿主一定会提供安全兜底。第三方 skill 版权归原作者,使用风险由使用者自行承担。

1实现原理 · 为什么它能做到

本模板是「文件夹即模板」结构里的一份纯数据:SKILL.md 用 YAML frontmatter 供选择器使用,正文是给 agent 的版式指令;仓库不为单个模板写任何代码,新增模板=新增一个文件夹。

next/src/lib/templates/loader.ts
SKILL.md — frontmatter (id, scenario, tags, …) + prompt body
loader.ts 在文件头注释里写明目录约定;frontmatter 由进程内正则解析(无 YAML 依赖),正文原样作为 prompt body 取出,前端不会拿到(「Body is excluded so we can return the entire registry in one cheap fetch without shipping prompt text to the browser.」)。

运行时由宿主把本模板正文夹在共享设计指令与用户内容之间拼成一次 prompt —— 模板的「智能」全在这段自然语言里,没有可执行代码。

next/src/lib/templates/shared.ts
return `${SHARED_DESIGN_DIRECTIVES} ${opts.body.trim()}
assemblePrompt 的返回是「共享设计指令 + 模板正文 + 【输入格式】+【用户内容】」。共享段(同一文件 SHARED_DESIGN_DIRECTIVES)负责单文件 HTML、Tailwind/字体 CDN、内容驱动数量、禁止使用文件系统工具等硬性要求,对所有模板一致,不是本模板自带。

宿主的 /api/convert 载入该模板后把这些文字交给本地已登录的 coding-agent CLI,只把 stdout 当 HTML 流式回收;模板本身不发网络、不读凭证、不写文件。

next/src/app/api/convert/route.ts
prompt = assemblePrompt({ body: skill.body, content, format });
同一 route 随后调用 invokeAgent({ … }) 拉起 CLI(claude / codex / cursor-agent 等,由宿主 PATH 探测);与其配套的共享指令还明写「**禁止使用 Write / Edit / MultiEdit / Bash / Create / 任何文件系统工具**」。

随模板附带的 example.html 是「预渲染示例」,由预览接口原样吐出、进入选择器与画廊的 iframe —— 它决定模板卡片有没有可视预览,不参与内容生成。

next/src/app/api/templates/[id]/preview/route.ts
Returns the skill's `example.html` verbatim so it can be loaded into an
预览按 skill id 缓存(Cache-Control: public, max-age=300);前端在预览面板里给 iframe 加了 sandbox="allow-scripts allow-same-origin"(宿主侧实现,本模板不可控)。

frontmatter 的字段被逐项映射成选择器元数据(featured 决定全量排序、recommended 进顶部「★ 推荐」组、example_* 生成示例卡文案),并决定它在分类/场景过滤里出现在哪里。

next/src/lib/templates/loader.ts
if (typeof fm.featured === "number") meta.featured = fm.featured;
fmToMeta 同时把 category/scenario/aspectHint/tags 直接搬到 SkillMeta;example 块在 example_id 或 example.{md,html} 存在时生成(id/name/format/tagline/desc + 可选 source)。这些字段只影响展示与排序,不影响生成行为。

该模板的生成能力全部由它自己的正文兑现:social-spotify-card/SKILL.md 只描述版面、配色、字体与内容纪律,没有一句让 agent 去跑工具、取接口或读外部数据。

next/src/lib/templates/skills/social-spotify-card/SKILL.md
【模板: Spotify Now-Playing 卡】
skill 目录共 2–3 个文件(SKILL.md + example.html[+ example.md]),无 scripts/references/数据文件;example.html 只是同一模板的人工示例产物(见 internal_assets)。

意图是把一首歌/一段播客/一段个人介绍渲染成 Spotify 正在播放卡,并注明灵感来自 hyperframes 的 spotify-card。

next/src/lib/templates/skills/social-spotify-card/SKILL.md
【意图】把一首歌、一段播客、或一段个人介绍渲染成 Spotify 正在播放卡, 适合 video overlay / 个人 about page / 创作者 hero。Inspired by hyperframes spotify-card。

正文提供两个画布:横版 1280×720 视频叠加位与 600×200 紧凑横条 widget。

next/src/lib/templates/skills/social-spotify-card/SKILL.md
- 紧凑横条 widget: 600×200, 可嵌入到任何 hero。

卡面结构由眉标 + 歌名 + 艺人 + 进度条 + 时间戳 + 控制行组成,进度条要求两端写时间戳。

next/src/lib/templates/skills/social-spotify-card/SKILL.md
- 进度条: 4px 高, 圆角, 灰色背景 + 白色 fill (`width: 38%`); 两端时间戳 `1:24 / 3:42` (mono, 11px, 灰)。

非音乐输入也能用:把「标题」当歌名、「副标/作者」当艺人,时长默认 3:42。

next/src/lib/templates/skills/social-spotify-card/SKILL.md
- 若用户输入是文本/标题 → 把 "标题" 当歌名, "副标/作者" 当艺人, 估算"时长" 3:42 默认。

动效要求克制且可关闭:音波用 @keyframes,且能被 prefers-reduced-motion 关掉。

next/src/lib/templates/skills/social-spotify-card/SKILL.md
- 微动效: 音波动效用 `@keyframes`, 可被 `prefers-reduced-motion` 关闭。

示例产物用三个 bar + animation: wave 复现音波,时间戳 1:24 / 3:42 与正文一致。

next/src/lib/templates/skills/social-spotify-card/example.html
.wave i { display:inline-block; width:3px; margin-right:2px; background:#1DB954; transform-origin:bottom; animation: wave 1s ease-in-out infinite; }

2核心能力

01双画布适配(1280×720 视频叠加 / 600×200 紧凑横条)
02Now Playing 卡面结构(眉标 + 歌名 + 艺人 + 进度条 + 时间戳)
03播放控制行(⏮ ⏯ ⏭ 内联 SVG + shuffle/repeat)
04专辑封面用 CSS 渐变 + monogram/几何绘制,禁外链图片
05任意文本 → 歌曲语义映射(标题→歌名,副标→艺人,默认时长 3:42)
06可关闭的音波微动效(@keyframes + prefers-reduced-motion)
07示例产物:Lo-Fi 卡 + 1:24/3:42 进度 + 绿色音波

3外部依赖

KindDependency / Endpoint
networkTailwind CDN(仅出现在产物示例 example.html,运行时不要求)
networkGoogle Fonts(仅出现在产物示例 example.html)
network灵感出处标注(frontmatter example_source_url,非运行时调用)
cli本地 coding-agent CLI(宿主提供,模板自身不调用)

4管控建议与判定依据

建议配套管控措施
面向 Agent
声明可访问域名与密钥范围
面向管理者
密钥最小权限,保留请求日志
判定依据(文件路径与关键语句摘要)
  • 网络端点: 声明外部网络访问: cdn.tailwindcss.com(example.html 的 <script src>,选择器预览/本地打开示例时由浏览器请求)
审计说明: 。判级对象=本 skill 目录(SKILL.md + example.html[+ example.md]):无自带脚本、无凭证读取、无写盘指令、运行时不要求任何外部端点——正文只给版面/配色/字体族名与内容纪律,字族名不构成请求。目录内实际出现的外链全部是「产物示例」性质,逐条列出自证:cdn.tailwindcss.com(example.html 第 6 行 <script src>)、fonts.googleapis.com(example.html 第 8 行 <link>,Inter + Noto Sans SC)、hyperframes.heygen.com(frontmatter 出处标注)。 按批4 口径(端点仅见于产物示例/出处标注 → green)不影响档位。宿主侧行为(loader.ts 读盘、assemblePrompt 拼 prompt、agents/invoke.ts 拉起本地 CLI、预览 iframe 的 sandbox="allow-scripts allow-same-origin")写在 verdict.risks,不作为档位依据。

5第二遍独立确认

  • [ok] skill 目录的脚本 / 网络 / 凭证 / 写盘面 — 目录仅 SKILL.md / example.html / example.md 3 个文件,无 scripts/references/数据目录;token 扫描(curl / wget / fetch / exec / spawn / process.env / API_KEY / token / secret / write / save / delete)在该目录的 SKILL.md 中零命中;无自带可执行脚本。
  • [ok] 运行时链路复核 — 重读 loader.ts / shared.ts / app/api/convert/route.ts / app/api/templates/[id]/preview/route.ts:模板正文只作为 prompt body 被 assemblePrompt 拼装,宿主 spawn 本地 CLI 并捕获 stdout;模板不参与任何执行。
  • [ok] commit 与元数据 — 工作副本 git HEAD = 553ed98c283f9c0f489902d035416a972d6a9699(=任务表 pin 的 full 40 位);GitHub API nexu-io/html-anything:stars 8827、license spdx Apache-2.0、pushed_at 2026-09-15T03:36:24Z(与本地 HEAD 提交时间 2026-09-15 11:36:24 +0800 一致)。
  • [discrepancy] README 与源码的 frontmatter schema 漂移(仓库级) — README 第 213 / 217 / 468 行称模板 frontmatter 必须含 mode · scenario · surface · preview · design_system;但在 next/src/lib/templates/skills/ 下 '^mode:'、'^surface:'、'^design_system:' 全部零命中,实际字段是 category / scenario / aspect_hint / featured / recommended + example_*(loader.ts 的 SkillFrontmatter)。文档滞后于代码,不影响本模板运行,但照 README 新写模板会踩空。
  • [ok] frontmatter 元数据映射 — loader.ts fmToMeta 逐字段映射 zhName / enName / emoji / description / category / scenario / aspectHint / tags + featured / recommended + example 卡;本模板取自 SKILL.md 的实际取值与之相符。
  • [ok] example.html 与 SKILL.md 的一致性 — 固定色 #1DB954、时间戳 1:24 / 3:42、音波动效(animation: wave)均在示例实现;专辑封面为 CSS 绘制,无外链图片,符合正文「不能外链图片」。
  • [ok] 端点扫描(目录内) — 3 处:cdn.tailwindcss.com、fonts.googleapis.com(均在 example.html)+ frontmatter 的 hyperframes.heygen.com 出处标注;SKILL.md 正文无 URL。
  • [discrepancy] 「prefers-reduced-motion 可关闭」核对 — 正文要求 "- 微动效: 音波动效用 `@keyframes`, 可被 `prefers-reduced-motion` 关闭",但 example.html 中只有 animation: wave 的定义,未找到 @media (prefers-reduced-motion: reduce) 规则——无障碍承诺在示例里没兑现(规格要求,示例未实现)。

6结论

  • 双画布(视频叠加位 + 600×200 横条)让同一套视觉既能剪视频也能嵌主页
  • 语义映射降低输入门槛:任意文本都能当 Now Playing 渲染
  • 品牌视觉锁定到色值级(#121212 / #1DB954 / #b3b3b3)
  • 唯一显式照顾无障碍动效偏好的模板(@keyframes + prefers-reduced-motion)
  • 封面禁外链,用 CSS 渐变/monogram,产物自足
  • 适合: 适合视频叠加(播客/歌单/直播字幕条)、个人主页或创作者 hero 的「正在播放」装饰位;也适合把一段自我介绍包装成 Now Playing 的趣味场景。
    不适合: 不适合需要真实播放状态(不接 Spotify API、不读播放数据,进度条靠写的)、不适合正经品牌物料(商标拟真),也不适合信息量大的介绍——卡面只容纳歌名/艺人/一行进度。
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload social-spotify-card.tar.gz
    sha256: 80174180f4c38b73…
    Option B · Copy Guide for Agent
    install.json
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit 553ed98c28.