Matrix App Builder
使用时机
当用户要求构建、创建、修复、重新设计或发布一个 Matrix OS 应用时使用此技能。
不可妥协的规则
- 在
~/apps/<slug>/中构建面向用户的应用。 - 默认使用 Vite、React 19、TypeScript 和
runtime: "vite"。 - CRM、路线图、仪表盘、管理后台以及数据密集型应用默认仍然是 Vite React SPA。使用 Matrix/Postgres 桥接 API 进行数据操作,而不是创建 Next.js API 路由。
- 除非用户明确要求服务器运行时或 Next.js,否则不要创建 Next.js、
.next/、app/路由文件、runtime: "node"、serve.start或npm start。 - 除非用户明确要求纯 HTML 应用,否则不要创建纯 HTML 应用。
- 始终创建或更新
matrix.json。为所有者构建的应用包含listingTrust: "first_party"和scope: "personal";缺失信任块时应用仍会构建,但无法启动。切勿对已下载、商店或社区应用重新标记以绕过策略。 - 依赖变化后始终运行
pnpm install,并且在确认应用可以工作之前始终运行pnpm build。 - 验证
dist/index.html是否存在。 - 使用注入的 Matrix 主题变量和 iframe 安全尺寸。自定义应用默认继承 shell 主题;仅在用户要求或应用有明确的领域理由时添加显式的应用品牌。
- 对于 UI,请阅读
matrix-design-system、matrix-app-ui-patterns和 App craft。在设计之前发现并阅读已安装的emil-design-eng和apple-designSKILL.md 文件;使用animate处理特定的动效。保留 Matrix 主题/运行时规则,并为应用的实际用途选择布局、材质和动效。 - 通过 Matrix/Postgres 桥接 API 存储结构化应用数据,不要使用临时的本地数据库。
- 绝不要将提供者密钥、API 密钥或 OAuth token 放在应用目录内。
- 在 Matrix shell 内,不要使用浏览器
localStorage作为应用持久化。沙箱化 iframe 可能抛出SecurityError;请使用window.MatrixOS.db,并将本地回退路径保留为仅测试/无操作。 - 对于
home/apps/**下的默认或第一方应用,保持清单确定性:runtime: "vite"、build.output: "dist"、模式列在storage.tables中声明,icon指向home/system/icons/中的已提交资源。
设计工作流
在搭建脚手架之前,阅读 craft 参考文件和已安装的设计技能。选择一个简洁的设计方向和主要用户流程。先构建核心交互,添加有目的的反馈,然后在 Matrix 中检查和优化正在运行的应用。避免使用通用的欢迎英雄区、装饰性的统计卡片、重复的玻璃容器和自动交错入场。记录你实际检查过的技能和表面。
标准结构
~/apps/<slug>/
matrix.json
package.json
vite.config.ts
tsconfig.json
index.html
src/
main.tsx
App.tsx
App.css
dist/
index.html
清单
使用此基线并根据需要调整应用名称、描述、类别、图标和存储表:
{
"name": "My App",
"description": "A concise app description",
"slug": "my-app",
"version": "1.0.0",
"runtime": "vite",
"runtimeVersion": "^1.0.0",
"listingTrust": "first_party",
"scope": "personal",
"icon": "my-app",
"category": "productivity",
"build": {
"command": "pnpm build",
"output": "dist"
},
"storage": {
"tables": {}
}
}
有效的存储列类型包括 text、boolean、integer、float、timestamptz、jsonb 和 uuid。
在聊天中展示应用和图表
验证应用后,链接其所有者相对目录,例如 [AI Adoption](~/apps/ai-adoption)。Electron Desktop 会将已安装的应用目录解析到应用目录,并通过正常的启动器行为打开它们。不要声称任意文件夹是一个已安装的应用。
使用 Markdown 图片和完整的所有者相对路径显示保存的图表或截图,例如 。Electron Desktop 可以显示这些图片并在文件预览中打开;不要告诉用户图片只能出现在代理的终端中。对于其他保存的文件,请使用 Markdown 链接。静态 HTML 预览是沙箱化的,没有脚本;链接已安装的应用以获得交互式图表,而不是承诺在聊天内部执行活跃的 HTML。如实报告缺失文件或预览失败。
命名
name是人类可读的、Title-Case 标签,显示在启动器、底座和标题栏中——例如"Calorie Tracker"、"Habit Garden"。保持简短和真实;永远不要向用户显示 slug。slug是在路径/URL 中使用的小写、连字符分隔的标识符(^[a-z0-9][a-z0-9-]{0,63}$)。从名称派生(例如calorie-tracker)。它是内部的——不要在任何地方将其用作显示字符串。
图标(必需——否则应用会显示损坏的磁贴)
启动器从 ~/system/icons/<icon>.svg(或 .png)加载每个应用的图标,与清单中的 icon 字段匹配。**如果你没有提供该文件,则 /icons/<icon> 会返回 404,并且应用会得到一个损坏/占位符图标。**因此请始终:
- 在
matrix.json中设置"icon": "<slug>"(使用应用 slug,除非你有更好的概念名称)。 - 使用 Matrix OS 内置图标样式创建
~/system/icons/<slug>.png: 轻量高级的 iOS/macOS 拟物化应用图标艺术作品,精炼的苹果风格产品渲染,明亮温暖的米白色或柔和粉彩背景,微妙的陶瓷/玻璃深度,柔和的斜角,光泽高光,逼真的工作室阴影,以及一个代表应用的单一大型触觉 3D 物体或符号。保持图标家族与 Matrix OS 森林、奶油、余烬和深色强调色一致。不要包含文本、标志、水印、透明背景、黑色/深色底座背景、空内边距或单独可见的图标框架;Matrix shell 拥有最终圆角。保持光照和材质处理与~/system/icons/中的默认应用 PNG 一致。
对于第一方/默认应用,优先使用 home/system/icons/ 中的已提交 PNG 图标。SVG 仅用于系统 chrome 或简单的兼容性回退,不用于新生成的应用标志。
数据(通过 MatrixOS 桥接的 Postgres)
应用在沙箱化的、空源 iframe(CSP connect-src 'self')中运行,因此直接 fetch() 到 /api/bridge/* 被阻止,localStorage 抛出 SecurityError。仅通过注入的桥接进行持久化:
- 在
matrix.json的storage.tables(如上)中声明你的表。网关会自动配置 Postgres 模式——对于已发布的应用在启动时配置,对于你现在构建的应用在第一次查询时惰性配置,因此新构建的应用的db调用无需任何重启即可工作。 - 在代码中使用
window.MatrixOS.db(find/findOne/insert/update/delete/count/onChange)。检查是否为undefined(在单元测试中不存在),将每个调用包装在try/catch中(记录日志 + 用户可见的错误;永远不要使用空的 catch),乐观地更新本地状态,并在onChange上协调。 - 对于外部/第三方 API,使用
window.MatrixOS.proxyFetch(url)(已加入白名单)——永远不要使用原始的 fetch。 - 不要在 shell 中添加一个运行的
localStorage回退;它在沙箱中会抛出异常。一个带有try/catch保护的 localStorage 路径仅在单元测试环境中作为无操作是可接受的。
主题继承
Shell 将 --matrix-* token 注入每个桥接的应用 iframe,并在主题变化时更新它们。首先在这些 token 上构建应用 CSS,仅将字面颜色作为回退:
:root {
--app-bg: var(--matrix-bg, #FAFAF9);
--app-fg: var(--matrix-fg, #32352E);
--app-card: var(--matrix-card, #FCFCF8);
--app-primary: var(--matrix-primary, #434E3F);
--app-primary-fg: var(--matrix-primary-fg, #FAFAF5);
--app-accent: var(--matrix-accent, #D06F25);
--app-success: var(--matrix-success, #3A7D44);
--app-warning: var(--matrix-warning, #E0A12E);
--app-danger: var(--matrix-destructive, #D74A3A);
--app-border: var(--matrix-border, #D8D6C7);
}
使用继承的 shell 字体(var(--matrix-font-sans)、var(--matrix-font-mono)),而不是加载远程字体样式表。不要在默认 UI 中使用应用本地的蓝色、绿色或紫色调色板。如果需要显式的应用品牌,将其限定在命名的品牌 token 中,并使系统控件、焦点状态、状态颜色和面板保持在 Matrix token 上。
持久化规则
- 在
matrix.json的storage.tables中声明每个持久化字段,包括审计字段如created_at、最佳得分/最佳时间列以及 JSONB 状态负载。 - 在启动时从桥接存储加载;不要在真实行加载后播种重复的回退行。
- 在创建、更新、删除和重新排序失败时回滚乐观 UI 更改。保持待删除项从可见状态中过滤掉,直到桥接确认或回滚。
- 序列化更新排序、最佳得分、统计计数器或历史行的依赖写入。避免两个桥接写入竞态,导致它们覆盖彼此的派生状态。
- 将仅限浏览器的辅助函数保留为测试保护。在生产 shell iframe 中,直接的
localStorage访问和原始的桥接fetch()调用不是可靠的持久化。
第一方默认应用
在此仓库中编辑捆绑的默认应用时:
- 将应用清单和模式保持在
home/apps/<slug>/matrix.json中。 - 重用共享的默认应用 Vite 构建路径;除非应用确实需要,否则不要添加过时的每个应用包/运行时字段。
- 当默认应用源代码更改后,在主机捆绑工作前运行
node scripts/build-default-apps.mjs home/apps。 - 优先使用共享的
game-center图标用于游戏,除非存在具体的已发布图标。 - 根据
home/system/icons/<slug>.svg或.png验证应用图标 slug;永远不要依赖运行时图标生成。
脚手架命令
当存在 Matrix 捆绑的 Vite 模板时,优先复制:
cp -a ~/apps/_template-vite ~/apps/<slug>
cd ~/apps/<slug>
pnpm install --prefer-offline
pnpm build
test -f dist/index.html
如果模板不存在,直接使用 react、react-dom、@vitejs/plugin-react、typescript 和 vite 创建标准 Vite 文件。
数据访问
使用注入的 window.MatrixOS.db 桥接进行结构化数据。不要直接从应用代码调用 /api/bridge/query;运行时应用作为沙箱化 srcdoc iframe 加载,直接的桥接获取被 shell 的 CORS/CSP 边界阻止。
示例 CRUD:
const db = window.MatrixOS?.db;
if (!db) throw new Error("Matrix data bridge is unavailable");
const tasks = await db.find("tasks", { orderBy: { created_at: "desc" } });
const created = await db.insert("tasks", { title: "Ship" });
await db.update("tasks", created.id, { done: true });
await db.delete("tasks", created.id);
集成
如果应用需要 Gmail、Calendar、GitHub、Slack、Drive 或其他提供者,请使用 Matrix 集成 API 或 matrix-integrations 技能。平台拥有提供者凭据。应用从不存储提供者密钥。
验证
在报告完成之前:
cd ~/apps/<slug>
pnpm build
test -f dist/index.html
node <resolved-matrix-app-builder-skill-directory>/scripts/verify-app.mjs "$PWD"
根据你加载的 SKILL.md 解析技能目录;脚本与它一起提供,不需要依赖。在真实的应用目录上运行,而不是模板。它验证所有者构建的 Vite 清单和生产入口;它从不更改信任或证明实时登录。
启动和身份验证
Matrix 提供所有者身份验证。不要构建单独的登录页面或在应用中读取/复制网关凭据。原生启动器通过 POST /api/apps/<slug>/session-token 获取一个短期令牌;启动路径是 /apps/<slug>/。缺失或未知的 listingTrust 导致 403 install_blocked_by_policy,而不是过期的登录。你刚刚为所有者构建的现有应用可以在检查其来源后纠正缺失的元数据;永远不要默默提升导入的应用。401 表示身份验证,403 表示策略,409 表示范围/确认,404 表示发现,5xx 表示服务器故障。准确报告失败,而不是为所有情况推荐登录。不要禁用身份验证、削弱策略、重启 VPS 或添加服务器来绕过启动失败。
然后从 Matrix 启动器使用现有的已验证会话打开应用。验证应用资源、图标、桥接操作、保存/重新打开往返以及 craft 参考文件的视觉/状态检查。如果浏览器访问不可用,请将启动和视觉验证报告为待定,而不是声称应用可以工作。检查浏览器控制台/网络以获取:
needs_build- 应用包或图标路径的 404
- 直接提供者调用的 CORS 错误
- 未处理的 React 错误
