关于 Lumo

Lumo 是一个用 Go 编写的开源 CMS。它想解决的是一个很具体的问题:把一套完整的建站系统,交付成单个可执行文件。

没有运行时依赖,没有容器编排,没有构建流水线。一个二进制、一个 PostgreSQL,拷到服务器上就能跑。

它解决什么问题

现成的 CMS 不是太少而是太多,所以更有意义的是说清楚这里做了哪几个判断。

后台嵌进二进制。 后台是一个 React 单页应用,但它不是单独的构建产物——它被编译进 Go 二进制里。上线不需要同时部署前端和后端,也不会出现「前端版本和后端接口对不上」这类只会在生产环境暴露的问题。

前台由服务端渲染。 访客看到的页面是 Go 模板渲染出来的 HTML,不是 SPA。登录、注册、找回密码、账户页这些关键表单都是原生 POST,关掉 JavaScript 也能用。这对搜索引擎和弱网环境都是更省事的做法。

主题走模板接口,不走插件。 主题包就是一堆 html/template 模板加一份声明文件。必需模板只有四个,缺一个会整页回退到内置主题,而不是报错或渲染出空白页。

插件目前不执行代码。 插件系统的第一期是纯声明式的:清单 + 设置 + 生命周期,没有代码执行。WASM 运行时在路线上,但不在现在。

技术底座

选型
语言 Go 1.26+,全链路 -tags nodynamic
数据库 PostgreSQL 17+(pgx + bun + goose 迁移)
后台前端 React 19 + Vite + TypeScript strict + Tailwind v4
路由与接口 chi 三平面路由 + huma,OpenAPI 3.1 由代码生成
前台渲染 html/template + Hugo 式 layout / partial 约定
内容格式 Markdown 与规范 HTML 并为一等公民
编辑器 TipTap v3(块编辑)与 Milkdown 7(Markdown)

后台的 TypeScript 类型从 OpenAPI 规范生成,不手写。规范与生成物都进版本库,所以前端构建不依赖后端在跑。

架构上几个刻意的决定

模块是编译期的。 十四个功能模块各自持有自己的数据库迁移和独立的版本表(goose_db_version_<模块>),彼此不引用内部实现,只通过 internal/app 的 Module 契约装配。cmd/lumo/modules.go 是唯一的装配点,顺序即依赖顺序。

接口分三个平面,前缀与鉴权策略固定。 后台面 console 默认强制认证;公开面 public 匿名可读已发布内容;扩展面 extension 留给插件的自定义模型。所有接口都经 huma 注册,错误一律是 RFC 9457 的 application/problem+json

正文按权限净化。 没有 content:unsafe_html 权限的角色,正文在保存时就按允许列表净化;有这个权限的(默认只有管理员与超级管理员)才能写入可执行内容。把这条权限授予编辑,等于允许他构造针对管理员的脚本。

凭据加密入库。 SMTP 口令与对象存储密钥在后台填、用 AES-256-GCM 加密存下来,接口永不回传明文。主密钥是 data/secret.key

数据库连接串只走环境变量。 这一条是硬线:DSN 不会出现在任何配置文件里,也不会出现在会被渲染或导出的内容里。首次安装时它写在 data/install.json(权限 0600),备份时要连 data/ 一起备——否则库里的那些口令解不开。

刻意不做的事

  • 不做功能阉割版。 没有「社区版 / 专业版」的功能差。程序本体怎么用都行,商业使用也不收费。
  • 不把使用者当收入来源。 项目未来的收入来自主题市场抽成和作者自己的付费主题,不来自站点运营者。
  • 不追求做一站式平台。 不做建站托管服务,不做可视化拖拽编辑,不做多租户。
  • 不为了兼容而兼容。 目前没有从其他 CMS 迁移的工具,也不打算做「假装别的系统的模板能直接跑」。

现在到哪一步

已经打了 v0.1.0 标签:九个开发阶段全部完成,十四个功能模块齐备,外部安全审查提出的 26 项问题全部处置。

但还没有经过生产环境检验,也仍然缺少自动化测试——原有用例已于 2026-09-15 整体清空,go test 现在只是空跑。欢迎试用与反馈,上生产请自行评估风险。缺什么、做到哪了,见路线图

接着看什么

评论

还没有评论,来说两句。