chore: 初始化官网白标基座项目(含设计文档)

This commit is contained in:
lzy
2026-07-23 18:45:51 +08:00
commit 8c33f4dcb0
3 changed files with 342 additions and 0 deletions
@@ -0,0 +1,268 @@
# 官网 + 轻量自助 CMS 白标基座 设计文档
> **产品线**:一人公司开源项目选型清单 §5「建站(官网)」升级方案(产品线 E)
> **日期**2026-07-23
> **状态**:设计已确认,待写实施计划
> **关联**:升级自 [一人公司开源项目选型清单](../../../一人公司开源项目选型清单.md) §5 / §9-E
---
## 一、背景与目标
### 1.1 原方案的三个缺口
一人公司选型清单中,官网搭建(产品线 E)原方案是「Astro + Astro Wind」纯 SSG,存在三个缺口:
1. **基座复用没落地** —— 文档第③条选型原则「一套基座吃多客户」在官网线未体现,每次都 fork 第三方模板,变成一锤子买卖。
2. **缺「官网 + 自助 CMS」混合方案** —— 纯 SSG 客户改内容只能走你,内容代维护变成长期负担,吃掉利润。
3. **未覆盖国内部署** —— 文档建议的 Vercel / Cloudflare Pages 在国内访问慢且常被墙,国内客户官网必须备案 + 国内 CDN。
### 1.2 目标
打造一套**可复用的官网白标基座**:
- 客户在可视化后台**自助改内容**(公司 / 产品 / 新闻 / 案例 / 招聘 / 下载 / 留言)
- **客户侧零服务器** —— 访客访问的是 OSS + CDN 纯静态站
- **一套基座复制给多客户** —— 换设计 token + 换内容即可交付新客户
- **国内合规上线** —— ICP 备案 + 阿里云 OSS/CDN
### 1.3 非目标(YAGNI 边界)
- ❌ 多语言 i18n(除非客户明确付费要求)
- ❌ 电商 / 支付(那是产品线 A,CRMEB)
- ❌ 会员 / 工单 / 审批(那是产品线 B,若依 / 低代码)
- ❌ 富后台 / 多角色 CMS(预留 Payload 适配器接口,遇到高预算客户再加,不在首期实现)
---
## 二、已确认的关键决策
| # | 决策点 | 结论 |
|---|--------|------|
| 1 | 定位 | 白标基座 + 首客户驱动(先跑通一个真实客户,再沉淀复用资产) |
| 2 | Git 后端 + CI | **自建一台 Gitea**(含 Gitea Actions),所有客户共用,多租户 |
| 3 | 内容板块 | company / products / news / cases / pages + **jobs(招聘)/ downloads(下载)/ messages(留言表单)** |
| 4 | 云厂商 | **阿里云**OSS + CDN + 域名 + ICP 备案) |
---
## 三、技术栈选型(License 全部原文核实)
| 层 | 选型 | License | 核实来源 | 选型理由 |
|----|------|---------|----------|----------|
| 官网框架 | **Astro**SSG | ✅ MIT | withastro/astro LICENSE | 零运行时、SEO 满分、Content Collections 类型安全 |
| 官网主题 | **Astro Wind** 起步,逐步沉淀**自有主题** | ✅ MIT | onwidget/astrowind LICENSE | 半天换皮;基座化后替换为自有 token 主题 |
| 自助 CMS | **Sveltia CMS** | ✅ MIT | sveltia/sveltia-cms `LICENSE.txt` + 官方 FAQ | Decap 的现代替代、原生支持 Gitea、活跃;Keystatic 锁 GitHub 不适合国内 |
| Git 后端 + CI | **自建 Gitea**+ Gitea Actions | ✅ MIT | go-gitea/gitea LICENSE | 单二进制极轻、被 Sveltia 原生支持、一台服务多客户、完全自控 |
| 表单后端 | **自研轻量微服务** | 自研(MIT | — | 复用 Gitea 那台轻量云,零额外服务器 |
| 对象存储 + CDN | **阿里云 OSS + CDN** | 商业 | — | 国内访问快、抗刷、备案友好 |
| 域名 / 备案 | 阿里云域名 + ICP 备案 | 商业 | — | 国内合规必须 |
> **技术验证结论(已查实)**Sveltia CMS / Decap CMS 都**不原生支持 Gitee**(要走自建 git-gateway + OAuth 代理,复杂且脆);GitHub 国内 OAuth 不稳。**Gitea 是两大 CMS 都原生支持**的国内可用后端,且自带 Actions CI,故选自建 Gitea。
全部为 🟢 MIT / 商业服务,**无 AGPL / GPL / BSL 传染风险**,白标转售安全。
---
## 四、整体架构
```
① 客户编辑 ② 构建发布 ③ 访客访问
┌────────────┐ 提交 ┌─────────────────┐ 同步 ┌──────────────┐
│ Sveltia │────────▶│ 自建 Gitea │────────▶│ 阿里云 │
│ /admin │ │ + Gitea Actions │ │ OSS + CDN │
│ (可视化) │◀────────│ (构建 Astro) │ │ (纯静态) │
└────────────┘ OAuth └─────────────────┘ └──────────────┘
│ │
│ ┌────────┴────────┐
└──────────────┤ 一台轻量云 │
表单提交 │ ① Gitea + CI │
│ ② 表单微服务 │ ← 服务【所有客户】
│ ③ SQLite 留底 │ 多租户共用
└─────────────────┘
```
**三层职责**
- **编辑层**:客户在 `https://<客户域名>/admin`Sveltia CMS 单页应用)可视化编辑,OAuth 登录自建 Gitea。
- **构建 / 存储层**:自建 Gitea(一台轻量云)。客户提交 → Gitea Actions 自动构建 Astro → `ossutil` 同步到该客户的 OSS bucket → 刷新 CDN。表单微服务也跑在这台机上。
- **访客层**:阿里云 OSS 托管静态站 + CDN 加速,访客全程不碰服务器,快、稳、抗刷。
---
## 五、内容模型(Astro Content Collections
每个集合配 Zod schema 校验,客户在 Sveltia 填错会自动报错。
| 集合 | 类型 | 字段 | 说明 |
|------|------|------|------|
| `company` | 单例 | name / intro / logo / phone / email / address / icp | 全站公共信息(页头页脚) |
| `products` | 集合 | title / cover / summary / body / category / sort | 产品或服务 |
| `news` | 集合 | title / date / category / cover / body | 新闻动态(带分页 + RSS |
| `cases` | 集合 | client / industry / cover / result / body | 客户案例 |
| `pages` | 集合 | slug / title / body / showInNav | 关于我们、联系等静态页 |
| `jobs` | 集合 | title / location / department / requirement / body | 招聘岗位 |
| `downloads` | 集合 | name / description / fileUrl / category / size | 下载资源(文件存 OSS,见 §七) |
| `messages` | 表单 | name / phone / email / message / createdAt | 留言(见 §六,由表单微服务写入) |
> `messages` 不由客户手动编辑,而是由访客提交的留言表单经微服务写入(通过 Gitea API 落成 Markdown 文件到该集合),客户在 `/admin` 查看,同时收到邮件通知。
---
## 六、留言表单方案(messages
纯静态站(OSS + CDN)无法处理后端逻辑,故**复用 Gitea 那台轻量云**,跑一个自研的极轻表单微服务。
### 6.1 技术栈
- **运行时**Node.js + Hono(或 Express
- **写内容**:通过 Gitea API 把留言写成 Markdown 提交到 `messages` 集合(Git 即留底,无需额外数据库)
- **邮件**nodemailer + 阿里云邮件推送(DirectMailSMTP,或腾讯企业邮 SMTP
- **失败兜底**:Gitea 写失败时记本地日志文件,保证不丢留言
- **部署**systemd 或 docker,跑在 Gitea 同机
- **凭据**:微服务持有一个专用 Gitea token,仅对该客户仓库有写权限(最小权限)
### 6.2 处理流程
```
访客填表 → POST https://forms.<你的服务域名>/api/submit
→ ① 蜜罐字段检查(机器人会填隐藏字段 → 丢弃)
→ ② IP 限流(每 IP 每分钟 ≤5 次)
→ ③ 字段校验(Zod)
→ ④ 经 Gitea API 写入 `messages` 集合(Markdown,客户在 /admin 查看)
→ ⑤ SMTP 发邮件通知客户(含留言内容)
→ 返回成功页
```
### 6.3 多租户
一个微服务服务所有客户:配置文件映射 `form_id → { 客户邮箱, 跳转页 }`。新客户加一行配置即可。前端表单的 `action` 带上该客户的 `form_id`
### 6.4 防垃圾
- 蜜罐字段(必填陷阱)
- IP 限流
- 可选:阿里云验证码 / hCaptcha(垃圾严重时再加,YAGNI
---
## 七、下载文件方案(downloads
下载文件(PDF 手册、驱动、视频)**不进 Git 仓库**(大文件不友好),统一存 OSS:
- 文件手动或脚本上传到该客户 OSS bucket 的 `/downloads/` 目录
- `downloads` 内容集合只记录元信息:`name / description / fileUrlOSS URL/ category / size`
- 客户在 Sveltia 编辑下载项的描述,文件本身由你或客户用 OSS 工具上传(Sveltia 的媒体库只给图片用,不混用)
> 小文件(<2MB 的 PDF)可直接 Sveltia 上传到 Gitea 仓库;大文件走 OSS。以 OSS 为主,避免仓库膨胀。
---
## 八、白标复用(新客户上线流程)
基座 = 一个 Astro 主题仓库(含组件区段 + Content Collections schema + Sveltia 配置模板 + Gitea Action 工作流)。
新客户交付 = 7 步:
1. **fork 基座** → 在自建 Gitea 建新仓库(独立组织/权限隔离)
2. **改设计 token** → 改一个 CSS 变量文件(主色 / 字体 / 圆角),整站换皮
3. **配 Sveltia** `config.ts` → 勾选该客户需要的内容板块(如纯展示型客户去掉 jobs/downloads
4. **客户填内容** → 在 `/admin` 用 Sveltica 录入
5. **域名 + 备案** → 阿里云买域名 + ICP 备案(约 7-20 工作日)
6. **建 OSS bucket + CDN** → 配静态站托管 + 绑定自定义域名
7. **配 Gitea Action** → 构建后 `ossutil` 上传 + 刷新 CDN → 上线,转月度维护续费
> 每个客户 = 一个 Gitea 仓库 + 一个 OSS bucket + 一个域名 + 一行表单配置;**基座代码复用、配置隔离**。
---
## 九、国内部署(阿里云)
- [ ] **ICP 备案**:客户域名必须备案,否则 CDN / 解析受阻(备案约 7-20 工作日,提前启动)
- [ ] **OSS 静态站托管**:开 bucket 的静态网站托管 + 绑定自定义域名(HTTPS)
- [ ] **CDN 加速**:回源 OSS,缓存策略 —— HTML 短缓存(1-5 分钟,便于内容更新生效)、JS/CSS/图片长缓存 + 文件名 hash
- [ ] **CI 发布脚本**Gitea Action 构建后用 `ossutil cp -rf dist/ oss://<bucket>/` 上传 + 调 OpenAPI 刷新 CDN
- [ ] **HTTPS**:阿里云免费 SSL 证书(或 Let's Encrypt),绑 OSS / CDN
- [ ] ⚠️ **不要用 Vercel / Cloudflare Pages**(国内访问慢 / 常被墙)
---
## 十、成本测算
| 项 | 金额 | 说明 |
|----|------|------|
| 固定:轻量云(Gitea + CI + 表单微服务) | ≈ 60-100 元/月 | **所有客户共用**2H2G 推荐 |
| 每客户:OSS + CDN | ≈ 5-15 元/月 | 按量,企业官网流量小 |
| 每客户:域名 | ≈ 55 元/年 | — |
| 每客户:备案 | 0 | 阿里云免费备案 |
| 每客户:邮件推送 | 极低 | DirectMail 按发信量,几毛/月 |
| **客单价**(参考文档 E 线) | **5k-2 万 + 月度维护续费** | 半天换皮、长期续费 |
**结论**:新增一个客户的边际成本 ≈ 60-100 元/年(域名 + OSS/CDN),客单价 5k 起,毛利极高。
---
## 十一、风险与先验证点(Phase 0 必须跑通)
| # | 风险 / 验证点 | 应对 |
|---|--------------|------|
| 1 | Gitea Actions 能否跑 Astro 构建 | 兼容 GitHub Actions 语法,Phase 0 用 node runner 镜像验证 |
| 2 | Sveltia + Gitea OAuth 登录 / 提交全链路 | Phase 0 配 Gitea OAuth App 跑通 |
| 3 | CDN 刷新延迟 | 秒-分钟级,HTML 配短缓存可接受 |
| 4 | 多租户 Gitea 权限隔离 | 每客户独立组织 / 仓库权限 |
| 5 | 表单微服务防垃圾 / 可用性 | 蜜罐 + 限流先上,验证码按需 |
| 6 | 备案周期长阻塞交付 | 合同里写明备案周期,提前启动或先用临时域名 |
---
## 十二、实施阶段
| 阶段 | 目标 | 产出 |
|------|------|------|
| **Phase 0** 技术验证 | 最小链路跑通:Astro + Sveltia + 自建 Gitea → 构建 → OSS → 访问;表单微服务跑通 | 一个可编辑、可留言的 demo 站 |
| **Phase 1** 基座化 | 沉淀自有主题 + Content Collections7 个集合)+ Sveltia 配置模板 + 白标脚本(换 token / 建 bucket | 可复用基座仓库 |
| **Phase 2** 首客户上线 | 用真实客户驱动,验证商业闭环 + 续费 | 第一个交付 + 月度维护合同 |
| **Phase 3**(可选) | 加 Payload 适配器,接富后台 / 多角色高预算客户 | 双档产品线(轻量 / 富后台) |
---
## 十三、CMS 适配器(预留,兼容未来 Payload)
把内容获取抽象成统一接口,保护 Astro 层不随 CMS 变化:
```ts
// 概念接口
interface ContentAdapter {
getCollection<T>(name: string): Promise<T[]>;
getSingleton<T>(name: string): Promise<T>;
}
```
- **默认实现**`MarkdownAdapter` —— 读本地 MarkdownGitea + Sveltia 路线,首期实现)
- **预留实现**`PayloadAdapter` —— 调 Payload REST/GraphQL APIPhase 3,遇到富后台客户再加)
切换 CMS 只换适配器,Astro 页面层与 Content Collections schema 不变。
---
## 十四、交付前检查清单(沿用选型清单 §十)
每个客户上线前:
- [ ] 该客户仓库的 LICENSE 文件原文我读了吗?(基座 + 依赖)
- [ ] 有没有子目录独立 LICENSEee/ / server/ / enterprise/)?
- [ ] 我的交付方式(私有部署 / SaaS / 转售)会触发哪个条款?
- [ ] Sveltia / Gitea / Astro 的 License 变更记录复查了吗?
**把 LICENSE 原文 + 近 3 年 license 变更记录存档到客户合同附件。**
---
## 参考资料
- [一人公司开源项目选型清单](../../../一人公司开源项目选型清单.md)
- [Astro 官网](https://astro.build/) · [Astro Wind](https://github.com/onwidget/astrowind)
- [Sveltia CMS 官网](https://sveltiacms.app/) · [Sveltia CMS Backends 文档](https://sveltiacms.app/en/docs/backends) · [官方 FAQMIT](https://sveltiacms.app/en/docs/faq)
- [Gitea 官网](https://gitea.io/) · [Gitea Actions 文档](https://docs.gitea.com/usage/actions/overview)
- [阿里云 OSS 静态网站托管](https://help.aliyun.com/product/31815.html) · [阿里云 CDN](https://help.aliyun.com/product/27099.html) · [阿里云邮件推送 DirectMail](https://help.aliyun.com/product/29412.html)
- [Decap CMS Backend 概览](https://decapcms.org/docs/backends-overview/)(对照为何选 Sveltia + Gitea 而非 Gitee