功能
Seed 提供的一切,以及还没有的部分
Seed 是一个免费、MIT 许可的 SaaS 启动模板,提供邮箱、Google 和 GitHub 登录、通行密钥、魔法链接、访客账号、双重验证、带角色的群组、按成员计费的 Stripe 订阅、实时更新、离线应用、管理后台、监控,以及可选的每日加密备份。下面每个部分都附有代码链接。
作者 Anton Shubin更新于
Seed 现在就能用,并且在公开开发中。缺少的部分会在受影响的功能旁标注“尚未完成”,如有对应的 issue,也会附上链接。
替你搞定
群组和计费都已接好的 SaaS 启动模板
账号、群组和收款:每个产品在开发第一个功能之前都需要,也是最容易出错的部分。
目前可用已在 CI 中测试。Google 和 GitHub 登录以及 Stripe 需要你自己的密钥,所以在演示中是关闭的。
账号
登录,已搞定
用户用邮箱和密码注册,并通过验证码验证邮箱。忘记密码可以重置,也可以用 Google 或 GitHub 继续、用通行密钥登录,或者通过邮件获取登录链接(没有账号时会顺便完成注册)。也可以先用访客账号试用应用,之后再添加登录方式。身份验证器应用可以开启双重验证(2FA)。用户能看到自己登录过的每台设备,并可以让其他设备退出登录。更改登录方式时需要验证身份,并会发送邮件通知。
- 密码通过 Web Crypto 用 PBKDF2-SHA-256 哈希,默认 600,000 轮
- 签名的会话 Cookie,每次登录事件都有审计记录
- 个人 API 令牌,只以带密钥的哈希形式存储
- 通行密钥:只存储公钥,每次登录的挑战只能使用一次
- 魔法链接:一个链接即可登录或注册,只能使用一次,15 分钟内有效,并且只以哈希形式存储
- 访客账号(匿名登录):访客一键开始,无需任何登录方式,之后可以在同一个账号上添加邮箱和密码、Google、GitHub 或通行密钥
- 按登录名统计所有网络地址上的密码错误次数,超过后短暂锁定

群组
带角色的群组,从第一分钟就有
每个账号注册时都会获得一个个人群组。用户可以创建共享群组、邀请他人、分配从查看者到所有者的角色,并一步完成所有权转让。已删除的群组可在 30 天内恢复,每个群组都有活动日志。
- 群组是唯一的租户边界:个人数据和共享数据经过同样的检查
- 应用、代码和本站都统一称它为群组
- 没有第二套权限模型需要与第一套保持同步
- 邀请、角色变更和所有权转让,各有独立的测试

概览
每个群组的概览
任意日期范围的关键数据和图表。每个人都可以隐藏和重新排列小组件,布局会同步到他们的其他设备。
- 每个数字都与上一周期对比,但不用红绿色下结论
- 只统计数量:不涉及笔记内容,也不给人排名
- 每个小组件独立加载、独立报错、独立重试
- 新增的聚合会带上自己的小组件,管理后台也会显示
收款
通过 Stripe 按成员计费
用户可以看到价格表、有使用限制的免费版,以及付费套餐的 14 天试用。所有者在邀请新成员之前就能看到多一位成员要多付多少钱;银行卡扣款失败时,会收到一条带日期的清晰提醒。
- Stripe Checkout 和客户门户;webhook 是套餐状态的唯一来源
- 订阅数量随成员人数自动调整
- 付款失败后有宽限期,默认 7 天
- 套餐限制在服务器端检查,而不只是在应用里
- 套餐保存在一个目录文件中,价格页直接读取它
- Stripe 以外的支付服务商

隐私
用户可以随时离开的账号
用户可以在个人资料中下载自己的数据副本,或删除账号,并有 7 天时间改变主意。已读通知会在 90 天后删除。
- 下载我的数据:一个包含 JSON 和 CSV 文件的 ZIP,在后台生成,保留 7 天
- 删除会等待 7 天;期间重新登录即可取消
- 每晚清理已读通知、失效邀请和旧的审计事件
导出
你的数据,随你带走
可以把任意群组导出为开放的 JSON 文件,之后再作为新群组导入。原来的群组永远不会被覆盖。
- 所有者负责导出;任何能创建群组的人都可以导入
- 写入任何数据之前会先检查整个文件,然后一步完成导入
- 每条笔记和每个标签都会获得新的 ID,因此导入永远不会与现有数据冲突
- 每个聚合各自注册它在文件中的部分
多语言
从一开始就支持九种语言
应用、管理后台和本网站支持英语、俄语、西班牙语、德语、巴西葡萄牙语、阿拉伯语、法语、日语和简体中文。用户在应用中选择语言,选择会保存到账号中。本网站的每个页面在每种语言下都有独立的地址。
- 每种语言一个 TypeScript 目录文件,由测试检查并列出所有缺失或过时的文案
- 复数、数字和日期使用平台自带的 Intl,不依赖任何 i18n 库
- 网站的每个页面都有 hreflang 链接,站点地图列出每种语言
- 阿拉伯语页面从右向左排版
- 邮件以收件人的语言发送
需要时随时可用
实时同步、离线和后台任务
大多数启动模板因为太难而略过的部分:实时更新、没有网络也能用的应用,以及绝不能丢失的任务。
目前可用离线写入支持笔记和标签;其他列表在离线时会显示上次加载的内容。
实时同步
无需刷新,更改即时可见
一位成员的更改会出现在该群组每个打开的标签页中;笔记本从休眠中唤醒后,也会补上错过的内容。
- 标准 WebSocket,每次更改都带有序号
- 从休眠中唤醒的标签页会重新连接,并拉取错过的内容
- 实时同步可以关闭:应用会改为定时轮询,使用体验不变


离线
没有网络也能打开的应用
应用可以像原生应用一样安装,没有网络也能打开,网络恢复后会自动发送排队中的更改。过时的更改会显示为需要你处理的冲突,绝不会悄悄覆盖。
- 每个列表在 IndexedDB 中都有一份副本,写入队列带有幂等键
- 每个冲突都可以选择“保留我的版本”或“使用服务器版本”
- 改一项设置即可关闭,或者彻底移除:删除一个文件夹,再按书面清单操作

键盘
应用和管理后台都支持键盘快捷键
按 ? 查看所有快捷键。在任意页面按 N 即可添加笔记,无需离开当前页面;先按 G 再按一个字母即可打开对应栏目。在输入框中打字时,快捷键不会干扰你。
- 按 Ctrl K(Mac 上为 ⌘K)或 / 打开搜索
- 每个应用用一份列表绑定按键并生成 ? 对话框的内容,所以它绝不会显示一个按了没反应的键
- 可以在某台设备上关闭单键快捷键;Ctrl K 和 Esc 仍然有效
- 在管理后台中,先按 G 再按一个字母即可打开各个模块
通知
应用内、手机、桌面和 Telegram 通知
用户在受到邀请、获得新角色或被转让群组时会收到通知:在应用内、通过手机或桌面上的 Web 推送,以及关联 Telegram 后在 Telegram 中。
- 使用你自己密钥的 Web 推送,一条任务即可生成:deno task vapid-key:create
- 应用内的未读数,以及“全部标为已读”
- 个人资料中列出每台设备的推送订阅
- Telegram 机器人,设置令牌之前处于关闭状态:通过一次性验证码关联,你的产品自己的命令只需在一个文件中添加

后台任务
崩溃也不会丢失的任务
即使服务器中途重启,邮件和通知也照样会发出,因为任务在执行之前就已保存。你自己的任务可以立即运行、稍后运行或定时运行。
- 每个命令都在与更改相同的数据库事务中写入它的事件
- Worker 消费这个 outbox,发送邮件、推送和实时更新
- 一个任务就是一个定义:名称、处理函数,如果需要重复执行,再加上调度计划
- 失败的尝试会以逐渐延长的间隔重试;运营人员可以在管理后台看到每一次运行
你的产品
复制一个功能,就能添加一个新功能
笔记是一个贯穿所有层的完整功能:数据库、API、界面、离线和测试。新功能照着它逐个文件复制即可,有一份清单按顺序列出了每个文件。
- 每个功能都是同一种结构,代码始终好找
- 每一层都有自己的测试,可以一并复制
- 每个 ID 都是按时间排序的 UUID(第 7 版)
运维
运行它、监控它、支持它的用户
一台你租用的服务器,看清它在做什么的工具,以及一个让运营人员帮助产品用户的后台。
目前可用下面每个模块现在都已上线。尚未完成的部分都列在对应模块下方。
支持
给运营人员用的管理后台
运营人员可以按姓名或邮箱查找用户,查看其登录方式、会话、群组和历史记录。在同一个地方,他们还能管理群组、退款、维护邮件简报的订阅者、查看所有后台任务、重新运行失败的任务,以及检查系统健康状况。 59 秒看完演示.
- 独立的应用,运行在独立的域名上,使用独立的会话 Cookie
- 13 个模块,从仪表盘到 API 令牌
- 有风险的操作会先确认,每个操作都会写入审计日志
- 以用户身份登录,看到对方所看到的内容
部署
一台服务器,一条命令
Seed 可以运行在你租用的任何 Linux 服务器上,开发和生产环境都使用 Docker Compose。多个产品可以共用一台服务器。
- Traefik 作为入口,自动签发证书
- Postgres 和 Valkey 与应用一起运行
- Garage(一个 S3 文件存储)用于存放笔记中的图片和 PDF 以及头像。上传通过签名链接进行,并按文件内容检查。照片(包括 HEIC)会被转换为体积小巧的 AVIF 和 WebP 版本,并移除位置等元数据
- VictoriaMetrics、VictoriaLogs 和 Grafana,带告警
- 可选的每日 restic 加密数据库备份,以及书面的恢复步骤
- 推送版本标签时,由 CI 发布正式版镜像
- Traefik
- Postgres
- Valkey
- VictoriaMetrics
- VictoriaLogs
- Grafana
- Alertmanager
- Garage file store
- restic backups
网站
可直接改造的公开网站
就是本站:快速、服务端渲染,关闭 JavaScript 也能使用,包含价格页、法律页面、博客和邮件简报。
- 服务端使用 Fresh;每个操作都是真实的链接或表单
- 价格读取自应用的套餐目录
- 双重确认订阅的邮件简报,一键退订,邮件以收件人的语言发送
- 在管理后台撰写的博客,支持每种语言的文章及其译文、主题、RSS 订阅源和文章结构化数据
- 在管理后台设置的联系方式,显示在页脚和结构化数据中
- 可选的商品目录,适合网店,在管理后台编辑:商品照片、颜色、尺码、尺码表和售罄尺码,覆盖你销售的每种语言,并为每个商品和每个分享渠道生成一个短追踪链接
- sitemap.xml、robots.txt、规范链接和 Open Graph 图片
- 可选的无 Cookie 统计,使用你自己的 Umami,每个行动号召都有事件记录,管理后台有统计页面:按来源和商品查看访问量和下单点击
- 每个页面都支持九种语言,各有独立地址和 hreflang 链接;法律页面保留英文版
质量
该测的地方都测了
统计于2026年10月16日:应用有 34 个浏览器测试套件,另有单元测试和界面测试,全部在 CI 中运行。每项更改在合并之前都要经过 pull request 和代码审查。
- 使用 Playwright 的浏览器测试,直接针对真实的 API 和数据库
- 单元测试和界面测试就放在被测代码旁边
- 针对 Postgres 的集成测试
常见问题
Seed 能做到吗?
Seed 能在 Vercel 或 Serverless 函数上运行吗?
不能。Seed 以常驻容器的形式,用 Docker Compose 运行在你租用的一台 Linux 服务器上,因为 API 需要保持 WebSocket 连接,Worker 需要持续消费队列。
Seed 能在 Node.js 或 Bun 上运行吗?
目前还不能。Seed 的服务器在 Docker 中的 Deno 2 上运行,任务和测试也使用 Deno。代码基于 fetch、Request 和 Web Crypto 等 Web 标准编写。
Seed 能使用 Postgres 以外的数据库吗?
不能。Seed 基于 Postgres 构建:它的迁移、查询和集成测试都以 Postgres 为前提。
Seed 能发布为移动或桌面应用吗?
暂时还不能作为应用商店里的应用发布。目前,Web 应用可以在手机和电脑上通过浏览器安装,没有网络也能打开;Android 和桌面应用已在计划中。
一分钟看它跑起来
演示就是你第一天就能拿到的应用。无需注册即可打开:你的访客账号自带示例数据。

