Community研究与数据分析github.com

AhmedAttia3/agent-skills

将一个项目创意转化为一个生产就绪、响应式、可安装的 PWA,包括完整的后端、数据库、推送通知和离线支持。

agent-skills 是什么?

此技能为 AI 代理(如 Claude Code、Cursor 等)提供了一个固定的、生产就绪的框架,用于从零构建 PWA。它采用严格的非协商性技术栈:Express 4 + CommonJS 后端、内置的 `node:sqlite` 数据库、React 18 + Vite + Tailwind CSS 前端、手写的 Service Worker 以及基于 `web-push` 的推送通知。该技能专为资源受限的主机环境(无编译器、约 300MB RAM、无 Postgres/MongoDB 或无 sudo 权限)设计,通过强制使用纯 JavaScript 库来避免本地依赖。工作流程包括八个有序阶段:主机侦察、用户需求访谈(最多 5 个问题,每个问题 3 个选项)、领域设计、代码脚手架搭建、领域逻辑替换、RTL 优先的前端开发、PWA 配置和推送通知集成、最终验证与交付(含 Git 提交和可选的 Cloudflare 隧道发布)。该技能特别强调验证,通过 API 测试和无法打开浏览器时的 curl 请求来确保结果可复现。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/AhmedAttia3/agent-skills/tree/HEAD/skills/pwa-app-builder

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

PWA 应用构建器

将一个项目创意转化为一个第一天就真实可用的应用:本地运行、可安装到手机、支持离线使用、发送通知,并且可以通过公共链接分享。以下技术栈是故意固定的——它是唯一能在这些项目所运行的主机限制(无编译器、约 300MB RAM、无 Postgres/MongoDB、无 sudo)下生存的组合。项目之间变化的是领域;保持不变的是骨架。

开始任何操作之前,请阅读整个文件。然后按顺序执行各个阶段——它们有检查点。


0. 技术栈(不可协商)

层选择为什么是这个而不是明显的替代方案
后端Express 4, CommonJS, 'use strict'一个进程服务 API + 构建好的 UI + 图片 → 无 CORS,只需重启一个东西,内存占用最低
数据库node:sqlite (DatabaseSync)内置于 Node ≥22.5。零本地模块。better-sqlite3 甚至无法安装(无 gcc)
密码crypto.scrypt + timingSafeEqual无 bcrypt(本地)。绝不存储明文
会话HMAC 签名令牌存放在 HttpOnly cookie 中无 jsonwebtoken 依赖,无 localStorage 暴露给 XSS
前端React 18 + Vite 5 + Tailwind 3,构建到 server/public快速低内存构建,静态输出由 Express 提供,无需 SSR
PWA手写 sw.js + manifest.webmanifest无 Workbox / vite-plugin-pwa;完全控制缓存策略
推送web-push + 本地生成的 VAPID 密钥免费,无需 Firebase 账户
图片上传前在浏览器中使用 Canvas 压缩无 sharp/multer(本地),更少的服务器 RAM
i18n小型内部字典,无 i18next即时 RTL/LTR 切换,包体积小

绝不添加: better-sqlite3, mongodb, pg, bcrypt, argon2, jsonwebtoken, sharp, canvas, multer, i18next, Workbox, vite-plugin-pwa, socket.io,或任何包含本地代码的包。如果某个任务似乎需要这些,请使用标准库或在浏览器中解决。


1. 阶段 0 — 侦察主机(先做这个)

bash <skill>/scripts/check-host.sh      # node, 编译器, RAM, swap, CPU, 端口, cloudflared

它会输出一个结论。你必须将两点纳入你的计划:

  • 无编译器 → 上述纯 JS 规则是一个硬性事实,而非偏好。
  • 资源不足(⚠️ LOW RESOURCES)→ npm install 和 npm run build 必须在后台运行,并带有一个日志文件供你轮询;前台长时间运行的命令会被杀死。参见 references/host-constraints.md。

浏览器规则(重要,而且是有条件的)

默认使用 curl 和 API 冒烟测试进行验证——这样更快、更省资源。但规则是**“未经许可不要启动浏览器”**,而非“永远不启动”:

  • 在资源充裕的主机(≥4 个 CPU,有 swap,充足空闲 RAM)上:许可只是一个形式。你可以说想打开无头浏览器检查渲染后的 UI,让用户决定。

  • 在低资源主机(例如 2 vCPU / ~300MB / 无 swap)上:提前告知用户原因,在与请求相同的句子中说明。一个 Chromium 实例可能耗尽整台机器资源,导致服务器被 OOM 杀死,需要重启。类似这样:

    «تحتاج للتأكد البصري من الواجهة؟ تشغيل المتصفح على هذا السيرفر (٢ كور وبدون swap) قد يستهلك الموارد بالكامل ويوقف السيرفر فيحتاج إعادة تشغيل. أفحص بـcurl واختبارات الـAPI بدلاً منه، أم تفضّل أن أشغّل المتصفح؟»

然后尊重用户的回答。永远不要静默启动浏览器。


2. 阶段 1 — 理解创意,然后访谈用户(硬性检查点)

2a. 用 5 行而非 50 行重述你的理解

包括:谁使用它,核心循环(他们重复最多的操作),他们存储的数据,以及第一个版本“完成”是什么样的。暂不规划架构。

2b. 在开始构建前询问偏好——这是必需的,不是可选的

用户在知道什么是 Service Worker 之前很久,就已经知道自己想看到什么。提前获得这些答案,是首次尝试就让他们喜爱的应用与需要三轮“改颜色”之间的区别。使用 system_ask_user 工具,让用户可以一键回答——最多 5 个问题,每个问题恰好 3 个选项。选择那些对构建影响最大的问题;跳过你可以合理推断或自行决定的内容。

问题库(根据项目领域调整措辞;使用用户的母语提问):

#问题选项
1默认界面语言阿拉伯语 (RTL),可切换 EN · 英语 (LTR),可切换 AR · 仅阿拉伯语
2色彩身份温暖(橙色/琥珀色)· 冷静(蓝绿色/蓝色)· 优雅(紫色/靛蓝)——或根据项目领域
3设计情绪简单实用且信息密集 · 现代圆角带动画 · 优雅深色默认
4移动优先还是桌面优先布局带底部导航栏的移动应用 · 带侧边栏的桌面控制台 · 两者兼顾(默认响应式)
5账户系统注册 + 无需注册的访客模式 · 仅访客模式(稍后升级) · 完全不需要账户
6通知定时提醒 + 推送 · 仅应用内提醒 · 无通知
7现成的公共内容由 JSON 文件提供内容的目录 · 仅用户内容 · 稍后再说
8名称和图标带 emoji 的阿拉伯语 + 英语名称 · 一个名称加手绘图标 · 你选最好的

访谈规则:最多问 5 个;绝不问你可以凭良好品味决定的问题(间距、动画曲线);如果用户说「اختر أنت」(你选),就做决定并继续——不要再问。记录答案:它们将成为阶段 3 中的脚手架标志。

2c. 回复计划并等待

给出一个简短计划(技术栈已定;页面;数据模型一行概括;各阶段)并停下来。此工作流中的大多数用户希望在编写代码前获得批准——一行「موافق، ابدأ」(同意,开始)比一个快速但错误构建更有价值。


3. 阶段 2 — 设计领域(小型、具体)

在编写代码之前,在聊天中写下:

  1. 实体 + 字段 — 用户核心循环所需的每个字段;标记必填与可选。将必填字段控制在绝对最少(名称和类别优于十个字段的表单)。
  2. 页面 — 列出它们;每个页面映射到 web/src/pages/ 中的一个文件。
  3. 路由 — 每个实体一个 REST 组,外加认证。
  4. 哪些可选模块适用 — 账户/访客模式、闹钟+推送、公共分享链接、公共内容目录。每个模块已在模板中实现;你是在选择,而非发明。

4. 阶段 3 — 脚手架(一个命令,然后验证)

node <skill>/scripts/scaffold.mjs \
  --dir <workspace> --name "应用名称" --name-en "AppName" \
  --slug appname --prefix ap --palette orange --ink warm [--with-catalog]

这将创建约 68 个文件:完整的工作骨架(认证、一个演示 CRUD 实体、PWA 外壳、推送、i18n、UI 工具包、运维脚本),并已全局替换了应用身份、cookie 前缀和品牌调色板。调色板:orange amber rose violet indigo sky teal emerald;色调:warm cool stone。

然后,在触碰任何其他内容之前——验证流水线是否工作:

export PATH="$HOME/node-v24.20.0-linux-x64/bin:$PATH"   # 这些主机上 Node 不在 PATH 中
npm install            # 低 RAM 主机?在后台运行并带日志,然后轮询
npm run build
./scripts/run.sh start
curl -s http://127.0.0.1:3000/api/health
npm run test:api       # 在新的演示脚手架上应显示 "110 通过,2 失败"

2 个失败是目录断言,需要真实的图片文件(npm run catalog:images 获取它们;需要网络)。在开始更改领域之前,其他所有内容必须通过——否则你将不知道后面的失败是否是你引起的。

阅读 references/templates-guide.md,了解每个创建的文件是什么,以及哪些部分是你即将替换的演示领域。


5. 阶段 4 — 用真实领域替换演示领域

脚手架附带了一个完整的工作示例(一个餐食应用),正是为了让你复制其形态。从数据层向外工作,确保没有任何悬空依赖:

  1. server/db.js — 为你的实体重写演示表。始终是添加性的:在 CREATE TABLE IF NOT EXISTS 块中新增表,在迁移数组中追加新列。然后编写查询函数。
  2. server/routes/<entity>.js — 复制 routes/meals.js 作为规范的 CRUD 路由器 (optionalFields、一个 toEntity() 映射器、INSERT/PATCH)。匹配导出风格以确保 server/index.js 正确导入(module.exports = router 对比 { router } —— 仓库中可能不一致,编写前请检查)。
  3. 在 server/index.js 中挂载路由器;不要给其他任何东西添加 API 前缀(SPA 回退已排除 /api)。
  4. web/src/lib/api.js — 每个路由对应一个方法。页面或组件中永远不要使用 fetch。
  5. web/src/pages/* + web/src/App.jsx 中的路由。
  6. scripts/smoke-test.js — 使用现有的 check(name, condition, extra) + call(path, {method, body}) 辅助函数重写演示断言。这是你的证明。

删除你的领域不需要的内容(演示实体的路由器、页面、API 方法和 i18n 键),而不是留下死代码。


6. 阶段 5 — 前端:RTL 优先,两种语言,一个设计系统

  • 每个面向用户的字符串必须同时存在于 web/src/lib/i18n.js 的 dict.ar 和 dict.en 中,使用 t('key') 读取,通过 {name} 占位符进行插值。一个键只存在于一个字典中是 bug。
  • 使用逻辑工具类(start-*/end-*/ps-*/pe-*/ms-*/me-*),以便 RTL 和 LTR 都能正常工作。有意例外:密码输入框使用 dir="ltr",因此使用物理定位 pr-12 / right-3。
  • 在编写分散的 Tailwind 之前,重用 web/src/styles.css 中的组件类(.card、.btn-primary、.input、.label、.chip)和 web/src/components/ui.jsx 中的原语。
  • 主题基于 documentElement 的 class、持久化在 localStorage 中,并由 web/index.html 中的内联脚本在首次绘制之前应用(消除闪烁并修复 iOS 状态栏)。
  • 响应式:移动优先,底部导航栏从 md: 断点起变为侧边栏(AppShell.jsx)。
  • 在以下位置验证 RTL/LTR:表单、列表、应用栏、模态框和 Toast 位置。

7. 阶段 6 — PWA + 通知

sw.js 和 manifest.webmanifest 已创建。有两件你绝不能忘记的事情:

  1. 每次更改 web/public/sw.js 文件时,必须更新 VERSION,否则已安装的客户端将永远保留过时的缓存。
  2. VAPID 密钥在首次启动时生成到 data/vapid.json。VAPID 的 sub 必须是真实可解析的域名(mailto:[email protected])—— Apple 会拒绝 *.local/@localhost 并返回 403 BadJwtToken,而 Google 会接受,这会产生经典的“Android 上正常工作,iPhone 上静默失败”现象。用 VAPID_SUBJECT 覆盖;绝不要硬编码个人地址。
  3. 在没有提供者真实响应的情况下,绝不要报告推送成功:sendToUser 返回 {total, sent, failed:[{status, reason}]} 并清理失效的订阅(404/410/403)。
  4. iOS 要求应用安装到主屏幕,并且需要从点击操作请求权限。请确保应用内本地通知回退(App.jsx 中的 useAlarmWatcher)正常工作。

详细信息和平台限制(通知中的图片、状态栏颜色、独立模式的 letterboxing)在 references/pwa-and-push.md 中——在承诺有关 iOS 的任何内容之前,请先阅读它。


8. 阶段 7 — 验证(这是交付物的证明)

npm run test:api                                    # 独立的 data/test.db,端口 3100,不碰实时数据库
npm run build && ./scripts/run.sh restart
curl -s http://127.0.0.1:3000/api/health
curl -s http://127.0.0.1:3000/ | head -3            # 提供构建好的 SPA
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/manifest.webmanifest
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/sw.js

还要使用 curl 模拟真实用户路径(注册/访客 → 创建 → 读取 → 更新 → 删除),以便你可以报告真实输出,而不是“应该可以工作”。然后,如果允许使用浏览器,在手机大小的视口上进行视觉检查。

报告确切的命令及其实际输出。如果某些内容失败,请附上错误说明。


9. 阶段 8 — 交付

  1. 本地 Git 仓库 + 首次提交(git init -b main),以便在进行任何有风险的实验之前有一个已知的良好状态。除非要求,否则绝不 push。使用 Conventional Commits 格式,主题为阿拉伯语:feat(meals): إضافة فلتر الفئات。

  2. 公共链接,通过 Cloudflare 快速隧道(./scripts/tunnel.sh start,然后从 tunnel.log 读取 URL)。此步骤是可选的,需要两个独立的批准:

    1. 询问他们是否想要公共链接。 如果他们已拥有域名、反向代理或可以部署到的主机,则不需要隧道——不要强推一个。
    2. 在承诺任何事情之前检查 cloudflared(scripts/check-host.sh 会报告)。如果缺失,请说明并在运行任何安装程序之前询问安装权限;绝不要静默安装二进制文件。提供 brew install cloudflared、他们平台的官方 Cloudflare 下载或他们已经拥有的 CLOUDFLARE=/path/to/binary。

    一旦获得批准,解释暴露风险:隧道会公开地发布该应用,免费的快速隧道主机名每次重启都是随机的,并且与 Chrome 的密码启发式算法有不良声誉(预计会出现“检查您的密码”提示——这是域名问题,而非您的代码问题)。

  3. 文档,一旦应用稳定后:docs/API.md(每个路由 + 一个可复制粘贴的 curl)、 README.md(功能、运行、测试)、AGENTS.md(供未来会话使用的仓库契约)。从最终代码编写 AGENTS.md——它是仓库中杠杆率最高的文件,并且应陈述与本技能相同的规则:技术栈、黄金数据库规则、验证命令、边界。

  4. 保持工作目录整洁:无 tmp-*.js,仓库根目录无零散日志,无提交的秘密。


10. 黄金规则(违反这些规则会导致项目崩溃)

  • 绝不删除或截断实时数据库。 始终使用迁移。绝不在生产数据库上运行未测试的 DROP TABLE 或 ALTER TABLE 命令,除非你百分之百确定没有数据需要保留。
  • 绝不将秘密提交到 Git。 使用环境变量或 .env 文件(绝不会被提交)。
  • 绝不直接在生产环境中修改 node_modules。 始终通过 npm install <package> 管理依赖。
  • 绝不绕过验证阶段。 每个阶段都必须通过其检查点才能继续。
  • 绝不承诺你无法验证的功能。 如果不确定平台限制(例如 iOS 推送通知),请测试并报告结果,而不是猜测。
  • 绝不留下未使用的死代码。 如果你替换了演示领域,请彻底清理。
  • 绝不假设用户的偏好。 询问他们(但用 5 个问题或更少)。
  • 绝不在没有用户明确同意的情况下静默启动浏览器或安装软件。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能