mengrru/spherse/spherse-write-html
Claude Code and agent skill by mengrru/spherse
- community
Checking that the SKILL.md file is still in the repository.
在 Spherse 中产出任何 HTML 之前必须先阅读本 skill。当用户要求创建或修改 HTML 页面、生成网页、制作可视化展示(欢迎页、侧边面板、导览主页、内容卡片、预览页等任意 HTML 交付物)时,务必在写出 HTML 代码前先读本 skill,了解 charset、数据与渲染分离的决策、数据加载模式与 App 能力调用(含交互式卡片回传会话)的约定;切勿未经阅读直接输出 HTML
Install
npx vskill@latest install mengrru/spherse/spherse-write-htmlSKILL.md
编写 HTML 页面 — 数据读写与 App 能力调用
本 skill 只规范 HTML 页面如何读取/写入数据、如何调用 App 内能力,不约束页面视觉风格、布局或代码风格。
强制:声明字符编码
所有 HTML 页面必须在 <head> 中添加 <meta charset="UTF-8">,且尽量靠近 <head> 起始位置,避免中文乱码。
强制:不要禁止页面滚动
HtmlCard 在固定高度的 iframe 中渲染(默认 400px,上限 600px)。当页面内容超出卡片高度时,必须能滚动查看全部内容——切勿设置 `body { overflow: hidden }` 或 `html { overflow: hidden }`,否则超出部分被裁剪、无法滚动,用户看不到完整内容。
即便不加overflow:hidden,App 也会在渲染时强制注入html,body{overflow-y:auto!important}作为兜底;但请勿依赖兜底,页面自身就应保持可滚动。自定义侧边面板(约 260px 窄栏、占满面板高度、原生滚动)没有这层兜底注入,更要保持可滚动,不要设overflow: hidden裁剪内容。
区分两种渲染模式
Spherse 中的 HTML 有两种加载方式,决定了数据能否通过 fetch 访问同目录文件:
| 模式 | 加载方式 | 能否 fetch 同目录文件 | 典型场景 | |
|---|---|---|---|---|
| 文件模式 | HTML 落在项目目录,经 preview 路由以 src 加载(真实 origin) | ✅ 可以 | Welcome Page、自定义侧边面板、Content Browser 预览、HtmlCard 带 file_path | |
| 字符串模式 | 纯 HTML 字符串经 srcDoc 加载(无真实 origin) | ❌ 不可以 | Chat HtmlCard 无 file_path |
判断方法:如果页面是作为文件写入用户项目目录(而非内联字符串),按「文件模式」处理。
何时将数据与渲染分离
实现一个 HTML 页面前,先判断它属于哪类,决定数据是「外置 JSON」还是「内联进 HTML」:
| 倾向 | 适用场景 | 做法 | |
|---|---|---|---|
| 外置 JSON(推荐) | 信息量较大(多条目列表/表格/清单)、预计需要长期维护与更新、数据可能被其它页面复用 | 数据存成独立的 {页面名}.data.json 文件,HTML 只负责渲染并用 fetch 加载数据 | |
| 内联进 HTML | 少量一次性展示内容、纯结构展示、字符串模式且无需持久化 | 数据直接写进 <script> 中的 JS 对象或 DOM |
外置的好处:数据与结构解耦,后续只改 JSON 即可更新内容,无需触碰 HTML;JSON 也可被其它页面 fetch 复用。
实现时务必用 write 工具分别落盘两个文件:HTML 页面(如world/atlas.html)和数据文件(如world/atlas.data.json),不要只写 HTML。
只读展示数据:外置为同目录 JSON(文件模式推荐)
文件模式下,把页面需要的展示数据外置到同目录的 .json 文件,用 fetch 加载。这样数据与结构分离,便于维护和更新,也避免把大段数据塞进 HTML。
约定:数据文件名形如 {页面名}.data.json,与 HTML 同级。
假设页面为 world/atlas.html,数据文件为 world/atlas.data.json:
- 字符串模式下fetch相对路径会解析到about:srcdoc而失败。此时把数据直接内联进 HTML(如<script>中的 JS 对象),或改用 ui-sdk 的 data action(见下文)。- preview 路由支持json、css、js、图片、字体等常见静态资源类型,同目录的 CSS / JS / 图片同样可用相对路径引用。- 需要在 JSON 被外部工具或 agent 修改后自动刷新页面时,用spherse.events.on("file:update", { path: "./atlas.data.json" }, handler)订阅。.//../路径与fetch一样基于当前 HTML 的 base 解析;也可以传项目根目录相对路径。完整说明见spherse-use-ui-sdkskill。
持久化读写:使用 ui-sdk data action
页面需要写入/持久化数据(如表单、进度、勾选状态)时,使用注入的 window.spherse.data.* key-value 接口。请读取 spherse-use-ui-sdk skill 获取完整 API。
要点速览(详情见 spherse-use-ui-sdk):
spherse.data.get/spherse.data.set/spherse.data.delete:对 key-value 数据的读写删(均返回 Promise)spherse.data.mutate:执行数据文件$manifest声明的业务 mutation 入口(结构性写入用,见下文$manifest一节)- 数据文件路径通过
file参数显式指定;推荐命名为{HTML文件名}.data.json并与 HTML 同级(如world/atlas.html→world/atlas.data.json),多个页面也可共用一个显式指定的数据文件;字符串模式下 HTML 不是文件,需自行指定一个项目内的.data.json路径 - 数据文件不能放在
.spherse/目录下 - 两种渲染模式都可用(经 App 注入的 SDK,不依赖
fetch)
强制:会增长/需要 agent 互动的数据文件必须内嵌 $manifest
判断:数据是静态展示(一次性内容,页面只 fetch 渲染)→ 无需 manifest;数据会随使用增长(清单、记录、游戏存档)或需要 agent 与页面互动读写 → 先加载 spherse-build-data-app skill 设计数据模型、命名 query/mutation 与协作流程,再生成 HTML。
HTML 落地时遵守:
- 同源生成 HTML、业务数据和
$manifest,字段名与 enum 必须和页面渲染逻辑一致。 - 页面会执行的每种结构性写入都必须有对应 mutation,并通过
spherse.data.mutate({ file, name, args })调用。 data.set仅用于单值、标量或低冲突数据,不得整体回写增长型数组。- 页面订阅数据文件的
file:update,在 Agent 或其他页面写入后重新读取并渲染。 - 业务数据键不得以平台保留的
$开头。
跳转到项目内其它文件:openFile
页面中点击跳转/打开项目内的其它文件时,使用 spherse.openFile(在 Content Browser 中打开)。不要用 <a href="..."> 直接链接(iframe 内的链接不会触发 App 导航)。
path为项目内相对路径。spherse全局对象由 App 自动注入,无需自己引入脚本。完整 API 见spherse-use-ui-sdkskill。
打开外部链接:openExternalLink
页面中需要打开外部网页(http/https/mailto/tel)时,使用 spherse.openExternalLink 在系统默认浏览器中打开。不要用 `<a href="https://...">` 直接链接——iframe 中的原生外链只会在 iframe 内原地跳转,无法跳出 App。
仅 http/https/mailto/tel 协议生效,其它协议会被静默忽略。指向项目内文件请用spherse.openFile。完整 API 见spherse-use-ui-sdkskill。
交互式 HtmlCard:将用户选择回传当前会话
当 HTML 作为聊天 HtmlCard 渲染时,可以为用户制作带交互性的卡片——例如让用户在多个选项中勾选,点击「提交」后把选择结果直接作为一条消息发回当前会话,驱动后续对话或 agent 行为。
实现要点:
- App 会自动向每个 HTML 注入
window.spherseSDK。 - 当 HTML 作为聊天 HtmlCard 渲染时,
spherse.runtime携带当前会话上下文(sessionId/agentId/projectId);加载即使用时用await spherse.getRuntime()(内部已处理竞态)。 - 用户点击提交时,读取
sessionId,组装消息文本,通过spherse.sendMessage发送。 spherse.sendMessage是请求型,会话忙碌时会 reject(session_busy),消息不会发出,应提示用户稍后重试。
spherse.sendMessage/spherse.getRuntime的完整签名见spherse-use-ui-sdkskill。
示例:选项卡片,用户勾选后提交,结果回传当前会话。
- 此模式仅适用于聊天 HtmlCard(Welcome Page / 自定义侧边面板 / Content Browser 预览中spherse.runtime为null)。- 提交内容应是有意义的、可被会话/agent 理解的自然语言,而非原始参数。
其它 App 能力调用
需要触发 App 内其它能力时,阅读 spherse-use-ui-sdk skill,通过 window.spherse.* 调用。可用方法包括:
spherse.createSession(params)→Promise<{ sessionId }>— 创建新会话并导航到聊天页;open: false时只创建不跳转,resolve 返回新会话 ID;可选name参数为会话命名(显示在会话列表)spherse.openSession(sessionId)— 打开已有会话并导航,不发消息(只跳转用这个)spherse.sendMessage(params)→Promise— 向已有会话发送消息(message必填;会话忙碌时 rejectsession_busy;open: false时静默发送——不跳转,未打开的会话由 server 直接执行)spherse.toast(params)— 弹一条 toast 提示({ variant, message, description? })spherse.emitAgentTriggerEvent(params)— 触发自定义事件,激活匹配的事件触发器spherse.floatSession(id)/spherse.unfloatSession()— 浮窗显示/关闭会话spherse.openFile(path | { path, float })— 在 Content Browser 打开项目文件;float:true以浮窗打开(desktop)spherse.openExternalLink(url)— 在系统默认浏览器打开外部链接(http/https/mailto/tel)spherse.data.get/set/delete(params)→Promise— key-value 数据读写spherse.api.*— 只读查询项目信息(agents / sessions / content / fileTree,完整 op 清单见spherse-use-ui-sdkskill)spherse.events.on("file:update", filter, handler)— 订阅指定项目文件的变化信号
spherse 全局对象由 App 自动注入到每个 HTML,无需自己写 <script> 加载或内联 wrapper。
向当前会话发消息:当 HTML 作为聊天 HtmlCard 渲染时,spherse.runtime(或await spherse.getRuntime())携带当前会话上下文(sessionId/agentId/projectId)。详见spherse-use-ui-sdkskill 的「运行时上下文」一节。
速查:场景 → 方案
| 需求 | 方案 | |
|---|---|---|
| 声明字符编码 | <head> 内加 <meta charset="UTF-8"> | |
| 保持卡片内容可滚动 | 切勿设 body{overflow:hidden};保持默认或 overflow-y:auto(超长内容需可滚动) | |
| 信息量大 / 需长期维护的页面 | 数据与渲染分离:外置 {页面名}.data.json,HTML 用 fetch() 读取,分两个文件落盘 | |
| 文件模式下加载展示数据 | 外置同目录 .json,用 fetch() | |
| 字符串模式下加载展示数据 | 数据内联进 HTML,或用 ui-sdk data.get | |
| 持久化读写数据 | ui-sdk data.get / data.set / data.delete;结构性集合写入用 data.mutate | |
| 枚举数据文件 key / 批量读取 | ui-sdk data.keys / data.entries | |
| 列出目录内容 | ui-sdk api.content.listDir | |
| 获取文件大小/类型/修改时间 | ui-sdk api.content.stat | |
| 播放音视频 | HTML <audio src="music.mp3"> / <video src="clip.mp4">(相对路径,支持拖动进度条) | |
| 点击打开项目内文件 | ui-sdk openFile | |
| 点击打开外部链接(网页/邮箱) | ui-sdk openExternalLink(http/https/mailto/tel),勿用 <a href> | |
| 打开/发送 chat 会话 | ui-sdk createSession(新建,返回 sessionId)/ openSession(只打开已有会话,不发消息)/ sendMessage(发消息)/ floatSession | |
| 后台静默创建/驱动会话 | await createSession({ ..., open: false }) 拿到 sessionId,再 await sendMessage({ sessionId, message, open: false }) 静默执行 | |
| 弹 toast 提示 | ui-sdk toast({ variant, message, description? }) | |
| 触发事件驱动 agent 执行 | ui-sdk emitAgentTriggerEvent(配合 agent 触发器配置) | |
| 交互式卡片 / 向当前会话发消息 | 读 spherse.runtime.sessionId,调 spherse.sendMessage(如收集用户选择后提交回传,会话忙碌 reject session_busy) |
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/presets/skills/spherse-write-html/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/mengrru/spherse/spherse-write-html)