# X³M Notes 的实现技术栈

> X³M Notes 采用 Markdown-first、Git-native 的静态架构：Astro 负责生成站点，Content Collections 与 Zod 负责内容边界，Pagefind 负责本地全文搜索，Cloudflare Pages 负责部署。

## 结论

这套知识库的核心资产不是某个后台系统，而是可读的 Markdown 文件、可追踪的 Git 历史和一组确定性的检查脚本。网站只是这些内容经过筛选、渲染和验证后的公开视图。

当前 V1 不使用数据库、CMS 或 MDX。AI 可以协助理解、整理和编辑内容，但是否能进入公开构建由文章 Schema、状态与可见性规则、隐私扫描和生产构建共同决定。

最后核验：2026-07-26。

## 技术栈总览

| 层次       | 技术                                                    | 在本项目中的职责                                       |
| ---------- | ------------------------------------------------------- | ------------------------------------------------------ |
| 内容源     | UTF-8 Markdown、Git                                     | 保存正文、记录修改、保持可迁移                         |
| 站点生成   | Astro，静态输出                                         | 将文章、页面和布局构建为静态文件                       |
| 内容模型   | Astro Content Collections、Zod                          | 加载 Markdown，并校验 frontmatter、状态和发布边界      |
| 页面组件   | Astro、React 19                                         | 负责页面模板、导航、文章布局和交互组件                 |
| 视觉效果   | `@react-three/fiber`、Three.js                          | 为首页的知识场景提供低功耗 Canvas 装饰，不承载知识正文 |
| 全文搜索   | Pagefind                                                | 在生产构建后为公开页面生成本地搜索索引                 |
| 自动化检查 | Node.js ESM、TypeScript、ESLint、Prettier、markdownlint | 检查代码、Markdown、链接、Schema 和发布前约束          |
| 浏览器验收 | Playwright                                              | 验证桌面端、移动端、搜索、主题、字体和公开边界         |
| 部署       | Cloudflare Pages                                        | 构建并托管 `dist/` 静态产物                            |

## 内容与数据流

### 1. Markdown 是唯一正文格式

文章放在 `src/content/articles/`，文件名包含日期和 slug，例如：

```text
src/content/articles/2026/2026-07-26-x3m-notes-tech-stack.md
```

原始输入、来源摘记、私密知识和已处理材料分别放在 `content/inbox/`、`content/source-notes/`、`content/private/` 和 `content/archive/`。这些目录不参与生产构建，避免把采集过程误当成公开内容。

### 2. Content Collections 加载文章，Zod 定义边界

`src/content.config.ts` 使用 Astro 的 `glob` loader 读取文章，再交给 `src/lib/article-schema.mjs` 中的 Zod Schema。Schema 统一校验：

- ID、slug、标题、描述、语言、类型、分类和标签格式。
- `status`、`visibility`、`originality` 和 `confidence` 等受控字段。
- 创建、更新和发布时间的顺序。
- 已发布文章必须有 `published_at`；草稿和审核中文章不能有发布时间。
- `unlisted` 必须设置 `noindex: true`；派生内容必须记录来源。

这一步解决的是“内容是否结构正确”，不是“内容是否应该公开”。后者由发布过滤器和构建检查继续处理。

### 3. 页面和索引使用不同的公开白名单

`src/lib/content.ts` 中有两条重要规则：

- `isRoutable`：只为 `status: published` 且 `visibility` 为 `public` 或 `unlisted` 的文章生成直接页面。
- `isPublicIndexable`：在此基础上只保留 `visibility: public` 且 `noindex: false` 的文章，用于首页、文章列表、分类、标签、搜索、RSS 和 Sitemap。

因此，文章存在于 Git 仓库并不等于它会出现在网站上。草稿、私密文章和测试材料不会通过客户端样式隐藏，而是在构建输入和路由生成阶段被排除。

## 前端与搜索

页面由 Astro 组件和布局组成，正文保持普通 Markdown。只有需要浏览器运行时的局部功能才使用 React；首页的 `KnowledgeField` 是一个遵守低功耗和减少动效设置的 React Three Fiber 视觉组件。

生产命令先运行 `astro build`，再用 Pagefind 扫描 `dist/` 生成搜索索引。由于隐藏文章没有生成页面，它们也不会进入搜索索引；RSS 和 Sitemap 同样从公开白名单读取。

站点字体从 `public/fonts/` 自托管，使用 Inter、Noto Sans SC、Source Serif 4、Noto Serif SC 和 JetBrains Mono。运行时不请求远程字体 CDN，字体许可证和来源记录在仓库文档中。

## 开发、检查与部署

当前项目的目标运行时是 Node.js `24.18.0`，包管理器是 pnpm `11.9.0`。常用检查分为三层：

```bash
pnpm format:check
pnpm lint
pnpm typecheck
pnpm kb:check
pnpm check:secrets
pnpm build
pnpm test:smoke
```

其中，`kb:check` 负责文章 Schema、文件名、H1、日期、来源、图片和内部链接；`check:private` 与生产构建验证最终产物没有泄漏私密或隐藏内容；Playwright 再从浏览器层面检查页面行为。

部署目标是 Cloudflare Pages，生产分支为 `main`，构建输出目录为 `dist`，目标域名是 `https://md.xxxm.dev/`。GitHub 仓库和 Cloudflare 凭据属于部署基础设施，不写入文章或代码。

## 这套选择解决什么问题

- **可迁移**：Markdown 可以被编辑器、命令行工具和其他静态生成器继续读取。
- **可审查**：Git diff 能直接显示正文、元数据和发布状态的变化。
- **可验证**：Schema、隐私扫描、构建验证和浏览器测试可以重复执行。
- **边界清晰**：采集、私密、草稿和公开内容不依赖 CSS 或客户端逻辑区分。
- **运维简单**：没有数据库和长驻服务，部署的是构建后的静态文件。

## 风险与边界

- 依赖版本和框架 API 会变化；升级 Astro、Pagefind 或字体包后，需要重新执行完整检查。
- AI 协助写作不等于事实已经核验。涉及金融、医疗、法律和安全的内容仍需来源、地区、日期和人工审核。
- 静态构建不能替代账户权限管理。GitHub 应保持私有，部署 Token 只能配置在平台 Secret 中。
- 本文记录的是当前仓库的实现，不是对 Astro、Cloudflare Pages 或其他依赖的通用选型结论。