写给发布者
拿到「发布者」角色后,登录画廊首页就会看到「发布新作品」磁贴。作品是纯静态网页(HTML/CSS/JS),
上传后跑在 /p/<id>/ 子路径下,任何人打开即用。
作品要求
- ZIP 或整个文件夹:ZIP 里任意层级有
index.html即可(自动取最浅的那个作入口)。 - 构建型项目(Vite / React 等)传
dist/,不要传源码根目录;node_modules、.git会被自动跳过。 - 路径用相对路径:作品跑在
/p/<id>/下,src="/app.js"这种绝对路径会指到站点根目录而找不到文件。 Vite 请设base: './'。 - 封面:根目录放
cover.png/cover.jpg/cover.webp(≤2MB)会自动成为画廊封面; 也可以在发布对话框里单独选图。没有封面时显示渐变色 + 首字母。 - 大小:单个 ZIP ≤512MB(超过 80MB 网页端会自动分片上传);解压后 ≤1GB。
- 配额:每位发布者默认 10 个作品 / 500MB(按解压后大小计)。账号中心与发布对话框都会显示已用量。
作品代码与本站同源,能读到打开它的访客在本站的登录态。这正是下面 SDK 能「零后端」工作的原因, 也意味着授予发布者角色等于信任其代码——请只上传你自己写的东西。
更新 / 可见性 / 删除
- 自己的作品卡片右上角有 ✎(编辑)与 ✕(删除)。
- 更新内容不换链接:编辑对话框里选一个新 ZIP,内容整体替换但
/p/<id>/不变,已分享出去的链接照常可用。 不选 ZIP 就只改名称 / 描述 / 分类。 - 可见性(发布或编辑时四选一):
- 公开:进画廊列表,任何人可打开。
- 登录可见:只有登录本站账号的人能在画廊看到、打开;访客打开链接会看到「需要登录」与登录按钮,登录后自动回到作品。适合只给家人朋友(已注册账号)看。
- 隐藏:不出现在画廊列表(自己和管理员仍看得到),但直链照常可访问——适合半公开分享或调试期。
- 私人:只有你自己能看到、打开,其他人(含管理员)一律 404。
- 删除不可恢复;作品目录与封面一起清除。
接入统一账号(可选,零后端)
作品可以识别当前登录用户,并把进度 / 设置存到该用户的云端(多设备同步)。站点托管了官方 SDK
/sdk/mksync-1.js,把下面几行放进你的 index.html 就够了:
<script src="/sdk/mksync-1.js?v=20260907"></script>
<script>
const sync = MKSync.create({
slug: 'myapp', // 必填:小写字母数字-,作品的短名
initial: () => ({ score: 0, unlocked: [] }), // 空档形状
onChange: (data) => render(data), // 云端有新数据到达(含启动首拉)时被调
});
const { authed, data } = await sync.start(); // 唯一需要 await 的调用;未登录也正常返回
render(data);
sync.set(d => ({ ...d, score: d.score + 1 })); // 改数据:本地立即落盘,2 秒防抖推云
loginBtn.onclick = () => sync.login(); // 登录按钮必须放在用户点击里(iframe 会拦非手势弹窗)
</script>
三条纪律
- 未登录也要能玩——账号是增强不是门槛,SDK 未登录时自动降级到 localStorage。
- 登录状态只信 SDK /
/api/user/me——cookie 是 HttpOnly 的,JS 读不到。 - 数据整文档读写——一个作品一份 JSON(≤256KB),读回来、改内存、整体写回。
注意事项
?v=请写一个固定版本号(如日期):Cloudflare 会让浏览器缓存 js 4 小时,带版本号才能在你更新作品时拿到新鲜 SDK。 网页端上传不会自动替换它。- 引 SDK 用 绝对路径
/sdk/mksync-1.js,不要把它打进 bundle;构建型项目只把.d.ts复制进源码拿类型。 - 要一个现成的「登录以同步 / 用户名 + 状态点」角标:再引
/sdk/mkchip-1.js,一行MKChip.attach(sync)。 - 本地开发直接打开 html 也能跑(命名空间自动变成
<slug>-devlocal),上线后 SDK 从/p/<id>/自动推断命名空间。
深浅色主题(1 行接入)
本站与所有作品共用一个主题开关。在 <head> 里加一行,作品就会跟随站内当前主题并实时切换:
<script src="/sdk/mktheme-1.js?v=20260907"></script>
它会给 <html> 打 data-theme="light|dark",你的 CSS 用 [data-theme="dark"] 选择器写深色样式即可。
不要自建主题键,也不要写死 prefers-color-scheme。协议细节见 /sdk/README.md。
多人联机(对战 / 协作 / 聊天 / 同屏)
再引一个 SDK,作品就能让多个玩家进同一个房间实时互动。登录可选:未登录以匿名访客参与,登录用户带账号名。 服务端只做通道(成员表、消息路由、共享状态、房主、断线恢复),游戏规则由作品自己定。
<script src="/sdk/mkroom-1.js?v=20260919"></script>
<script>
const room = MKRoom.create({ slug: 'mygame' });
room.on('join', p => addPlayer(p));
room.on('leave', p => removePlayer(p));
room.on('message', (data, from) => handle(data, from)); // 别人 send() 的内容
room.on('state', state => render(state)); // 共享状态(迟到者进房直接拿到)
room.on('host', (id, isMe) => { if (isMe) becomeAuthority(); });
const { code } = await room.create({ max: 4 }); // 6 位房间码给朋友;或 room.join('AB3K9Q')
room.send({ t: 'move', x, y }); // 广播;(data, 'host') 只发房主;(data, peerId) 点对点
room.setState({ phase: 'playing' }); // 浅合并,全员按同一顺序收到
</script>
- 固定大厅:
room.join('lobby', { create: { public: true, max: 16 } });room.list()列出公开房间。 - 断线 15 秒内自动重连并恢复席位(含房主身份);房主离开自动移交给最早加入的人。
- 限额:单房 2~16 人、单条消息 / 共享状态 16KB、每连接 30 条/秒;高频同步请节流到 ≤20 条/秒。
- 完整 API、语义纪律、排错与底层协议见 room-api.md;开两个标签页打开 roomdemo.html 即可体验全部功能。
加载进度与就绪(MKApp)
访客从画廊或分享链接打开作品时,会先看到一层带作品名和进度条的加载遮罩,作品在它下面的 iframe 里加载。
不做任何事遮罩也会揭开(资源请求安静下来就判定就绪,最长 20 秒兜底);引 /sdk/mkapp-1.js 上报真实进度,
遮罩就能准确地在「真正能玩」那一刻揭开,大资源作品不会提前露出黑屏。
<script src="/sdk/mkapp-1.js?v=20261006"></script>
<script>
let done = 0;
Promise.all(assets.map(a => load(a).then(() => window.MKApp && MKApp.progress(++done, assets.length))))
.then(() => { startGame(); window.MKApp && MKApp.ready(); }); // ready() 幂等,多调无害
</script>
- 调用写成
window.MKApp && …:直接打开 html、本地开发服务器、没引 SDK 的环境都会静默跳过,作品不会因此报错。 不在外壳里(直接打开/p/<id>/)时 SDK 本身也全部 no-op。 - 接到哪一步:首屏前只等一个 bundle、其余都懒加载的作品,只调
ready()就够(每次打开约快 0.7 秒); 有预加载循环、首屏前要等 1MB 以上、或自带加载屏的,再报progress()。 - 怎么报:只算首屏真正在等的资源;多阶段合成一个 0..1;加载失败也计数;别提前报 1(外壳收到 1 立即揭开),
分母多留 1 份给
ready()。只加回调,不为上报加 await 或串行化加载。详见 app-api.md「加载进度接入建议」。 MKApp.context()给出项目 id、命名空间(与 MKSync 同规则)、是否在外壳里、从哪个展示集点进来的。MKApp.me()拿当前登录用户(不登录也正常返回{authed:false});MKApp.login()在新标签打开登录页,必须放在用户点击里。- 完整 API 与外壳消息协议见 app-api.md;demo.html 里有自测按钮。
素材库(MKVault)
需要给每个登录用户存大量条目或图片 / 音频 / 视频(作品集、日记、卡片、录音……)时用素材库:条目是任意 JSON(每条 ≤256KB),
文件单独上传后把 fileId 写进条目引用。只存进度 / 设置用上面的 MKSync 就够了。素材库必须登录,未登录没有本地降级。
<script src="/sdk/mkvault-1.js?v=20261006"></script>
<script>
const vault = MKVault.open({ slug: 'myapp' }); // 线上自动按 /p/<id>/ 隔离;本地开发落 myapp-devlocal
const list = await vault.items(); // 带缓存与 ETag,没变化时几乎零流量
const f = await vault.upload(file, { downscale: { maxSide: 2048 }, onProgress: p => bar(p) });
await vault.put(MKVault.newId(), { title: '水墨山', media: [{ fileId: f.fileId }] });
img.src = vault.fileUrl(f.fileId);
</script>
- 限额:单张图片 / 音频 / 视频 10MB / 30MB / 80MB,每用户总空间 3GB;
downscale会在上传前把图片缩边并转 WebP,通常只剩几百 KB。 - 删条目时它
media[]里引用的文件会被服务端一并删除;文件地址只对本人有效,不能当公开外链。 - 错误都带
err.code:needs_login(引导登录)、conflict(多设备同时改,见err.item)、quota、too_large等。 - 完整 API、并发控制与底层 HTTP 见 vault-api.md。
下载与参考
| 文件 | 用途 |
|---|---|
| mksync-1.js · mksync.d.ts | 统一账号云同步 SDK(全局 MKSync)。运行时请引站内绝对路径,.d.ts 只用于类型。 |
| mkchip-1.js · mkchip.d.ts | 可选的账号 / 同步状态角标(全局 MKChip)。 |
| mktheme-1.js · mktheme.d.ts | 统一深浅色主题(全局 MKTheme)。 |
| mkroom-1.js · mkroom.d.ts | 联机房间 SDK(全局 MKRoom):建房 / 加入、消息、共享状态、房主、断线恢复、WebRTC 信令。 |
| mkapp-1.js · mkapp.d.ts | 平台桥(全局 MKApp):加载进度 / 就绪、运行上下文、当前用户、登录、分享短链。平台外全部静默。 |
| mkvault-1.js · mkvault.d.ts | 用户素材库(全局 MKVault):条目 JSON + 图片 / 音视频上传,带缓存、并发控制与图片压缩。 |
| app-api.md · vault-api.md | 平台桥与素材库接入指南。 |
| room-api.md · roomdemo.html | 联机接入指南与自测台。 |
| user-api.md | 完整接入指南:全部选项、匿名进度合并、冲突 merge、登录引导、排错手册、底层 HTTP API。 |
| demo.html | SDK 自测台:登录 / 多标签同步 / 冲突场景一步步验证。 |
| README.md | SDK 版本纪律与主题协议。已被引用的文件永不删除、永不做破坏性改动。 |
遇到问题:给 MKSync.create 加 debug: true,所有静默失败都会 console.warn。