diff --git a/app/components/home/Hero.tsx b/app/components/home/Hero.tsx
index 0afeedb5..af399d95 100644
--- a/app/components/home/Hero.tsx
+++ b/app/components/home/Hero.tsx
@@ -53,7 +53,7 @@ export function Hero() {
,
text: '使用文档',
description: '了解 Mix Space 如何使用',
- url: '/docs/usage',
+ url: '/docs/use',
menu: {
className: 'md:row-span-2',
},
@@ -75,7 +75,7 @@ export const baseOptions: BaseLayoutProps = {
icon:
,
text: '后端部署',
description: '部署 Mix Space 的后端部分',
- url: '/docs/core',
+ url: '/docs/deploy',
menu: {
className: 'lg:col-start-2',
},
@@ -93,7 +93,7 @@ export const baseOptions: BaseLayoutProps = {
icon:
,
text: '文档撰写',
description: '了解 Mix Space 的文档撰写规范',
- url: '/docs/document',
+ url: '/docs/use/writing',
menu: {
className: 'lg:col-start-3 lg:row-start-1',
},
@@ -102,7 +102,7 @@ export const baseOptions: BaseLayoutProps = {
icon:
,
text: '开发指南',
description: '了解如何为 Mix Space 开发后端和前端',
- url: '/docs/development',
+ url: '/docs/develop',
menu: {
className: 'lg:col-start-3',
},
diff --git a/content/docs/configure/account-security.mdx b/content/docs/configure/account-security.mdx
new file mode 100644
index 00000000..0abf12d8
--- /dev/null
+++ b/content/docs/configure/account-security.mdx
@@ -0,0 +1,113 @@
+---
+title: 账号与安全
+description: 管理站点所有者信息、API Token、Passkey 和 OAuth 登录
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 的账号系统围绕「所有者」概念设计。每个 Mix Space 实例只有一个所有者(Owner),所有者拥有完整的管理权限。
+
+## 所有者信息
+
+登录后台,进入「设定 → 个人信息」页面。你可以设置以下信息:
+
+| 字段 | 说明 |
+|------|------|
+| **昵称** | 显示名称 |
+| **头像** | 头像图片 URL |
+| **邮箱** | 联系邮箱 |
+| **个人介绍** | 一段简短的个人介绍 |
+| **社交链接** | GitHub、Twitter、Bilibili 等社交账号链接 |
+
+这些信息会被前端主题读取并展示在首页的博主信息区域。
+
+## API Token
+
+API Token 是访问 Mix Space API 的凭证。第三方工具(如 Obsidian 插件、API 客户端)需要 Token 才能调用需要认证的 API。
+
+### 管理 Token
+
+进入「设定 → 账号与安全 → API Token」:
+
+| 操作 | 说明 |
+|------|------|
+| **创建 Token** | 设置名称和过期时间,生成新的 Token |
+| **查看 Token** | 创建时显示完整的 Token 值,请妥善保存 |
+| **删除 Token** | 吊销指定 Token,所有使用该 Token 的请求将被拒绝 |
+
+
+Token 仅在创建时显示一次完整值。如果忘记 Token,需要删除后重新创建。请勿将 Token 提交到公开的代码仓库。
+
+
+### Token 的用途
+
+- **Obsidian 插件**:配置 API Token 以同步内容
+- **API 客户端**:`@mx-space/api-client` SDK 使用 Token 认证
+- **自动化脚本**:CI/CD 或自定义脚本调用 API
+
+## Passkey(通行密钥)
+
+Mix Space 支持使用 Passkey(WebAuthn)进行无密码登录,更加安全便捷。
+
+### 添加 Passkey
+
+
+
+### 进入账号设置
+
+前往「设定 → 账号与安全 → Passkey」。
+
+
+
+### 注册新密钥
+
+点击「添加 Passkey」,浏览器会弹出安全密钥注册窗口。根据设备不同,可能需要:
+- 使用指纹识别(Touch ID / Windows Hello)
+- 使用面部识别
+- 插入硬件安全密钥(如 YubiKey)
+
+
+
+### 命名密钥
+
+为 Passkey 设置一个便于识别的名称(如「MacBook Touch ID」),方便管理。
+
+
+
+
+Passkey 与设备和浏览器绑定。如果你更换设备,需要在旧设备上仍然可以登录时添加新的 Passkey。
+
+
+## OAuth 第三方登录
+
+Mix Space 支持通过 GitHub、Google 等第三方账号登录后台。
+
+### 配置 OAuth
+
+前往「设定 → OAuth」页面。详细配置步骤请参考 [OAuth 2.0 登录](/docs/configure/oauth)。
+
+### 将 OAuth 账号设为所有者
+
+首次通过 OAuth 登录后,需要在「设定 → 账号与安全」中点击「设为所有者」,将该 OAuth 账号与站点所有者身份绑定。
+
+## 安全设置
+
+### 禁用密码登录
+
+如果你已经配置了 Passkey 或 OAuth 登录,可以在「认证安全设置」中禁用密码登录,提高安全性。
+
+
+禁用密码登录前,请确保你至少有一种可用的替代登录方式(Passkey 或 OAuth)。否则你将无法登录后台。
+
+
+## 登录会话
+
+在账号与安全页面,你可以查看当前所有活跃的登录会话:
+
+- 设备和浏览器信息
+- 登录 IP 地址
+- 登录时间
+- 当前会话标记
+
+你可以手动结束其他设备的会话。
diff --git a/content/docs/usage/search.mdx b/content/docs/configure/algolia.mdx
similarity index 88%
rename from content/docs/usage/search.mdx
rename to content/docs/configure/algolia.mdx
index 21bb1e25..0cd2e6ae 100644
--- a/content/docs/usage/search.mdx
+++ b/content/docs/configure/algolia.mdx
@@ -1,5 +1,5 @@
---
-title: Algolia Search
+title: Algolia 站内搜索
description: 使用 Algolia 搜索
---
@@ -75,7 +75,7 @@ Algolia 是一个数据库实时搜索服务,能够提供毫秒级的数据库
### 后台配置
-进入后台,设定->系统->Algolia Search,将“开启 Algolia Search”开关打开,将前面准备的 `IndexName`、`Application ID(AppID)` 和 `Admin API Key(ApiKey)` 填入对应的框中,右上角保存即可。
+进入后台,设定->系统->Algolia Search,将"开启 Algolia Search"开关打开,将前面准备的 `IndexName`、`Application ID(AppID)` 和 `Admin API Key(ApiKey)` 填入对应的框中,右上角保存即可。
-至此,Algolia 搜索的配置就完成了。稍等一会,就可以尝试在主页用 `Ctrl + K` 调用 Algolia* 进行站内搜索了。*
\ No newline at end of file
+至此,Algolia 搜索的配置就完成了。稍等一会,就可以尝试在主页用 `Ctrl + K` 调用 Algolia 进行站内搜索了。
diff --git a/content/docs/usage/security.mdx b/content/docs/configure/encryption.mdx
similarity index 96%
rename from content/docs/usage/security.mdx
rename to content/docs/configure/encryption.mdx
index 26d7e63f..26408a3d 100644
--- a/content/docs/usage/security.mdx
+++ b/content/docs/configure/encryption.mdx
@@ -1,6 +1,6 @@
---
-title: Key 加密与安全性
-description: 加密你的 MixSpace
+title: 数据加密
+description: 加密你的 Mix Space
---
在 v3.41.0 后续版本,加入了敏感 Key 加密功能。默认为关。
diff --git a/content/docs/configure/environment.mdx b/content/docs/configure/environment.mdx
new file mode 100644
index 00000000..aa6aa793
--- /dev/null
+++ b/content/docs/configure/environment.mdx
@@ -0,0 +1,56 @@
+---
+title: 环境变量参考
+description: 所有环境变量的完整说明
+---
+
+
+ 如果你不确定某个变量的作用,保持默认值即可。
+
+
+以下环境变量适用于 Mix Space Core 后端服务。Docker 用户在 `docker-compose.yml` 的 `environment` 中设置;源码用户在 `.env` 或 `ecosystem.config.js` 中设置。
+
+## 核心必填
+
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `JWT_SECRET` | JWT 签名密钥 | - | `my-secret-key` |
+| `ALLOWED_ORIGINS` | 允许的跨域域名 | - | `example.com,www.example.com` |
+| `SNOWFLAKE_WORKER_ID` | 工作节点 ID(单实例填 1)| - | `1` |
+
+## PostgreSQL 数据库
+
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `PG_URL` | 完整连接字符串(推荐)| - | `postgresql://mx:mx@localhost:5432/mx_core` |
+| `PG_HOST` | 数据库地址 | `127.0.0.1` | `localhost` |
+| `PG_PORT` | 端口 | `5432` | `5432` |
+| `PG_USER` | 用户名 | `mx` | `mx` |
+| `PG_PASSWORD` | 密码 | `mx` | `secret` |
+| `PG_DATABASE` | 数据库名 | `mx_core` | `mx_core` |
+| `PG_MAX_POOL_SIZE` | 连接池大小 | `20` | `20` |
+| `PG_SSL` | 启用 SSL | `false` | `true` |
+
+## Redis
+
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `REDIS_HOST` | 地址 | `localhost` | `redis` |
+| `REDIS_PORT` | 端口 | `6379` | `6379` |
+| `REDIS_PASSWORD` | 密码 | - | `secret` |
+
+## 安全
+
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `ENCRYPT_ENABLE` | 启用加密 | `false` | `true` |
+| `ENCRYPT_KEY` | 加密密钥(64 位 hex)| 自动获取 machine-id | `abc...` |
+
+## 其他
+
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `PORT` | 服务端口 | `2333` | `3000` |
+| `TZ` | 时区 | `Asia/Shanghai` | `UTC` |
+| `DISABLE_CACHE` | 禁用 Redis 缓存 | `false` | `false` |
+| `THROTTLE_TTL` | 限流窗口(秒)| `10` | `10` |
+| `THROTTLE_LIMIT` | 限流次数 | `100` | `100` |
diff --git a/content/docs/configure/image-storage.mdx b/content/docs/configure/image-storage.mdx
new file mode 100644
index 00000000..17388a47
--- /dev/null
+++ b/content/docs/configure/image-storage.mdx
@@ -0,0 +1,96 @@
+---
+title: 图床与存储
+description: 配置 S3 兼容对象存储作为图床,自定义存储路径与 CDN 加速
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 支持将图片和文件存储到 S3 兼容的对象存储服务(如 Cloudflare R2、AWS S3、阿里 OSS、腾讯 COS 等),替代默认的本地存储。
+
+## 配置 S3 图床
+
+
+
+### 进入图床设置
+
+登录后台,前往「设定 → 图床设置」。
+
+
+
+### 开启 S3 图床
+
+打开「开启 S3 图床」开关。
+
+
+
+### 填写 S3 配置
+
+| 字段 | 说明 |
+|------|------|
+| **S3 服务端点** | S3 兼容服务的 Endpoint(如 `https://.r2.cloudflarestorage.com`) |
+| **Access Key ID** | 访问密钥 ID |
+| **Secret Access Key** | 访问密钥(加密存储) |
+| **Bucket** | 存储桶名称 |
+| **Region** | 地域(Cloudflare R2 填 `auto`) |
+
+
+
+
+### 配置自定义域名(推荐)
+
+填写「自定义域名 (CDN)」字段,用于替换默认的 S3 URL。例如你的 CDN 域名是 `cdn.example.com`,则上传后的文件 URL 为 `https://cdn.example.com/{路径}/{文件名}`。
+
+
+
+### 设置文件路径前缀(可选)
+
+填写「文件路径前缀」来组织上传的文件。支持占位符:
+
+| 占位符 | 说明 |
+|--------|------|
+| `{Y}` | 年份(4 位) |
+| `{m}` | 月份 |
+| `{d}` | 日期 |
+| `{type}` | 文件类型 |
+| `{md5}` | 随机 MD5 |
+
+示例:`blog/{Y}/{m}/{d}` → 文件上传到 `blog/2024/01/15/` 路径下。
+
+
+
+
+开启 S3 图床后,新上传的文件会存储到 S3。之前上传到本地的文件不会自动迁移,但仍然可以正常访问。
+
+
+## 常用 S3 服务配置参考
+
+### Cloudflare R2
+
+| 字段 | 值 |
+|------|-----|
+| S3 服务端点 | `https://
.r2.cloudflarestorage.com` |
+| Region | `auto` |
+| 自定义域名 | R2 绑定的自定义域名或 `r2.dev` 公开访问地址 |
+
+### AWS S3
+
+| 字段 | 值 |
+|------|-----|
+| S3 服务端点 | 留空(使用默认)或区域端点 |
+| Region | 如 `us-east-1`、`ap-southeast-1` |
+| 自定义域名 | CloudFront 分发域名 |
+
+### 阿里 OSS / 腾讯 COS
+
+按照对应服务的 S3 兼容接口文档填写 Endpoint 和 Region 即可。
+
+## 评论图片专用前缀
+
+在「评论图片路径前缀」字段中,可以为读者评论上传的图片设置独立的存储路径前缀。该字段额外支持 `{readerId}` 占位符,按读者 ID 组织目录。
+
+留空则使用默认路径:`comments/{readerId}/{Y}/{m}/{md5}.{ext}`
+
+## 备份到 S3
+
+在「设定 → 备份」中也可以配置 S3 信息,将数据库备份文件同时上传到 S3 存储,实现异地备份。详见 [备份与恢复](/docs/use/backup-restore)。
diff --git a/content/docs/configure/index.mdx b/content/docs/configure/index.mdx
new file mode 100644
index 00000000..d050b1d0
--- /dev/null
+++ b/content/docs/configure/index.mdx
@@ -0,0 +1,44 @@
+---
+title: 功能配置概览
+description: 快速找到你需要的配置文档
+---
+
+import { Card, Cards } from 'fumadocs-ui/components/card';
+
+## 我想实现的功能
+
+| 我想实现... | 查看文档 |
+| --- | --- |
+| 设置第三方登录(GitHub/Google)| [OAuth 2.0](/docs/configure/oauth) |
+| 配置 SEO 和搜索引擎推送 | [SEO 与站点优化](/docs/configure/seo) |
+| 管理 API Token 和 Passkey | [账号与安全](/docs/configure/account-security) |
+| 配置 S3 图床和 CDN | [图床与存储](/docs/configure/image-storage) |
+| 添加站内搜索 | [Algolia Search](/docs/configure/algolia) |
+| 加密敏感配置 | [Key 加密](/docs/configure/encryption) |
+| 了解所有环境变量 | [环境变量参考](/docs/configure/environment) |
+
+## 快速导航
+
+
+
+ 查看所有支持的环境变量及其说明
+
+
+ SEO 元数据、Sitemap、RSS、百度/Bing 推送
+
+
+ 所有者信息、API Token、Passkey、OAuth 绑定
+
+
+ S3 对象存储配置、CDN 加速、自定义存储路径
+
+
+ 配置 GitHub、Google 等第三方登录
+
+
+ 为站点添加 Algolia 站内搜索
+
+
+ 加密数据库中的敏感配置项
+
+
diff --git a/content/docs/configure/meta.json b/content/docs/configure/meta.json
new file mode 100644
index 00000000..2510d559
--- /dev/null
+++ b/content/docs/configure/meta.json
@@ -0,0 +1,16 @@
+{
+ "title": "配置",
+ "description": "配置 Mix Space 的各项功能",
+ "icon": "Settings",
+ "root": true,
+ "pages": [
+ "index",
+ "environment",
+ "seo",
+ "oauth",
+ "account-security",
+ "image-storage",
+ "algolia",
+ "encryption"
+ ]
+}
diff --git a/content/docs/configure/oauth.mdx b/content/docs/configure/oauth.mdx
new file mode 100644
index 00000000..0bf4bd88
--- /dev/null
+++ b/content/docs/configure/oauth.mdx
@@ -0,0 +1,128 @@
+---
+title: OAuth 2.0 登录
+description: 配置 GitHub、Google 等第三方 OAuth 登录
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 支持通过第三方 OAuth 账号登录后台,免去记忆密码的麻烦。目前支持 GitHub 和 Google 两种 OAuth 服务商。
+
+
+OAuth 登录基于 better-auth 实现,不走 Clerk 等第三方认证服务,所有数据存储在你自己的数据库中。
+
+
+## 前置条件
+
+在配置 OAuth 之前,请确保:
+
+- 后端服务已正常运行
+- 前端和后端都已配置好 HTTPS(OAuth 回调要求 HTTPS)
+- 你有 GitHub 或 Google 的开发者账号
+
+## 配置 GitHub 登录
+
+
+
+### 创建 GitHub OAuth 应用
+
+1. 前往 [GitHub Developer Settings](https://github.com/settings/developers)
+2. 点击「New OAuth App」
+3. 填写以下信息:
+
+| 字段 | 填写内容 |
+|------|----------|
+| Application name | 你的站点名称 |
+| Homepage URL | 前端地址(如 `https://example.com`) |
+| Authorization callback URL | 后台提示的回调地址 |
+
+4. 创建完成后,记下 **Client ID**
+5. 点击「Generate a new client secret」,记下 **Client Secret**
+
+
+
+
+### 在后台配置
+
+登录后台,进入「设定 → 登录方式」,在 GitHub 部分填入 Client ID 和 Client Secret,保存。
+
+
+
+### 测试并绑定
+
+在前端登录页面点击 GitHub 登录按钮,完成授权后会提示是否将此账号设为站长。确认后即可通过 GitHub 登录后台。
+
+
+
+## 配置 Google 登录
+
+
+
+### 创建 Google OAuth 客户端
+
+1. 前往 [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
+2. 创建一个项目或选择已有项目
+3. 配置「OAuth 权限请求页面」:
+ - 已获授权的网域填写你的根域名
+ - API 范围选择非敏感范围的三项(email、profile、openid)
+4. 创建「OAuth 客户端 ID」,选择「Web 应用」:
+
+| 字段 | 填写内容 |
+|------|----------|
+| 已获授权的 JavaScript 来源 | 前端地址 |
+| 已获授权的重定向 URI | 后台提示的回调地址 |
+
+5. 记下 **Client ID** 和 **Client Secret**
+
+
+
+
+### 在后台配置
+
+登录后台,进入「设定 → 登录方式」,在 Google 部分填入 Client ID 和 Client Secret,保存。
+
+
+
+### 测试并绑定
+
+在前端登录页面点击 Google 登录按钮,完成授权后绑定站长身份。
+
+
+
+## 获取回调地址
+
+在后台「设定 → 登录方式」页面的 OAuth 部分,每个服务商旁边会显示对应的回调地址(Callback URL)。创建 OAuth 应用时需要将此地址填入。
+
+
+回调地址与你的前端地址和后端地址相关。如果更换了域名,需要同步更新 OAuth 应用的回调地址配置。
+
+
+## 绑定站长身份
+
+首次通过 OAuth 登录时,系统会提示你是否将此 OAuth 账号设为站长(Owner)。确认后,该 OAuth 账号就拥有了完整的管理权限。
+
+如果你后续需要更换绑定的 OAuth 账号,可以在后台「设定 → 账号与安全」中操作。
+
+## 同时使用多种登录方式
+
+你可以同时启用 GitHub 和 Google 登录。登录页面会显示所有已启用的登录方式,用户可以选择任意一种登录。
+
+如果同时配置了密码登录和 OAuth 登录,建议在「设定 → 认证安全设置」中考虑是否禁用密码登录以提高安全性。详见 [账号与安全](/docs/configure/account-security)。
+
+## 常见问题
+
+### 回调后提示错误
+
+- 确认回调地址完全一致(包括末尾的斜杠)
+- 确认 `ALLOWED_ORIGINS` 环境变量中包含前端域名
+- 确认 OAuth 应用的 Client ID 和 Secret 正确
+
+### GitHub 提示「Application suspended」
+
+- 检查 GitHub OAuth 应用的状态,可能因为长时间未使用被暂停
+- 确认 Client Secret 未过期(GitHub Secret 有过期时间设置)
+
+### Google 提示「未验证应用」
+
+- 在 Google Cloud Console 中将应用发布为「正式版」
+- 或者添加测试用户账号
diff --git a/content/docs/configure/seo.mdx b/content/docs/configure/seo.mdx
new file mode 100644
index 00000000..efdfb64d
--- /dev/null
+++ b/content/docs/configure/seo.mdx
@@ -0,0 +1,84 @@
+---
+title: SEO 与站点优化
+description: 配置 SEO 元数据、搜索引擎推送和 RSS/Sitemap
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 内置了 SEO 基础功能,包括自定义站点元数据、自动生成 Sitemap 和 RSS Feed,以及百度/Bing 搜索引擎推送。
+
+## SEO 基础设置
+
+进入后台「设定 → SEO 优化」,配置以下信息:
+
+| 配置项 | 说明 |
+|--------|------|
+| **网站标题** | 站点名称,显示在浏览器标签和搜索结果中 |
+| **网站描述** | 一段简短的站点描述,用于搜索引擎结果摘要 |
+| **浅色图标 URL** | 浅色模式下的站点图标 |
+| **深色图标 URL** | 深色模式下的站点图标 |
+| **关键字** | 站点关键词列表,用于搜索引擎识别站点主题 |
+
+这些信息会自动应用到前端页面的 `` 标签中。
+
+## 网站地址
+
+进入后台「设定 → 网站设置」,正确填写站点地址:
+
+| 配置项 | 说明 |
+|--------|------|
+| **前端地址** | 你的前端主题地址(如 `https://example.com`) |
+| **管理后台地址** | 后台管理地址(如 `https://example.com/proxy/qaqdmin`) |
+| **API 地址** | 后端 API 地址 |
+| **Gateway 地址** | WebSocket 网关地址 |
+
+
+「前端地址」非常重要,Sitemap 和 RSS 中的链接都基于此地址生成。请确保填写正确的完整 URL(包含 `https://`)。
+
+
+## Sitemap
+
+Mix Space 自动生成 Sitemap 文件,无需额外配置。
+
+访问 `https://你的API地址/sitemap` 即可获取标准的 XML Sitemap,其中包含所有已发布内容的 URL 和更新时间。
+
+Sitemap 缓存 1 小时,内容更新后会自动刷新。
+
+## RSS Feed
+
+Mix Space 自动生成 RSS Feed,无需额外配置。
+
+访问以下地址即可获取 RSS 订阅源:
+
+- `https://你的API地址/feed`
+- `https://你的API地址/atom.xml`
+
+RSS Feed 包含最新的文章内容,支持全文输出(Markdown 文章)和链接跳转(富文本文章)。
+
+## 搜索引擎推送
+
+### 百度推送
+
+进入后台「设定 → 百度推送设定」:
+
+| 配置项 | 说明 |
+|--------|------|
+| **开启推送** | 启用百度搜索引擎推送 |
+| **Token** | 百度站长平台提供的推送 Token |
+
+在 [百度搜索资源平台](https://ziyuan.baidu.com/) 注册并验证你的站点后,可以在「链接提交」中获取 Token。
+
+### Bing 推送
+
+进入后台「设定 → Bing 推送设定」:
+
+| 配置项 | 说明 |
+|--------|------|
+| **开启推送** | 启用 Bing 搜索引擎推送 |
+| **Bing API 密钥** | Bing Webmaster Tools 的 API 密钥 |
+
+在 [Bing Webmaster Tools](https://www.bing.com/webmasters) 中注册并验证站点后,可以在 API 设置中获取密钥。
+
+
+搜索引擎推送会在内容创建和更新时自动触发,无需手动操作。
+
diff --git a/content/docs/core/advanced.mdx b/content/docs/core/advanced.mdx
deleted file mode 100644
index f6a38bfe..00000000
--- a/content/docs/core/advanced.mdx
+++ /dev/null
@@ -1,112 +0,0 @@
----
-title: 进阶部署
-description: 通过源码部署 Mix-Space 后端
-icon: Pickaxe
----
-
-import { Configurator } from 'app/components/Configurator';
-import { Step, Steps } from 'fumadocs-ui/components/steps';
-
-
-在您进行进阶部署前,我们给予最后的警告:如果你**不是开发者**,或者**不想折腾**,请不要选择**进阶部署**,因为它需要你具备一定的开发能力。
-
-由于自身技术原因导致的问题,我们将**不会提供任何技术支持**。情节严重者,我们将**永久拉黑**您的账号。
-
-
-
-## 要求
-
-- 已安装 [Node.js](https://nodejs.org/zh-cn/) 20.0.0 或以上版本
-- 已安装 [Git](https://git-scm.com/downloads), [PNPM](https://pnpm.io/installation), [PM2](https://pm2.keymetrics.io/docs/usage/quick-start/)
-- 已安装 [MongoDB](https://www.mongodb.com/try/download/community), [Redis](https://redis.io/download) 并正常运行
-
-
-
-### 克隆并安装
-
-```bash
-git clone https://github.com/mx-space/core.git --depth=1
-cd core
-pnpm i
-```
-
-
-
-### 构建 & Bundle
-
-```bash
-pnpm build
-pnpm bundle
-```
-
-
-
-### 配置 ecosystem.config.js
-
-
-
-
-
-### 启动
-
-1. 进入 `./apps/core`,修改 `ecosystem.config.js` 文件
-2. 将上方复制的内容覆盖进去,然后执行以下命令启动服务
-
-```bash
-pm2 start ecosystem.config.js
-```
-
-
-
-### 反向代理 or ...
-
-剩下的就是你的事了,你可以使用 [Nginx](https://nginx.org/en/download.html) 或者 [Caddy](https://caddyserver.com/download) 等反向代理工具,也可以使用 [Cloudflare](https://www.cloudflare.com/) 等 CDN 服务。本文不再赘述。
-
-
-
\ No newline at end of file
diff --git a/content/docs/core/docker.mdx b/content/docs/core/docker.mdx
deleted file mode 100644
index 8d1b1d92..00000000
--- a/content/docs/core/docker.mdx
+++ /dev/null
@@ -1,150 +0,0 @@
----
-title: Docker 部署
-description: 通过 Docker 部署 Mix-Space 后端
-icon: Container
----
-
-import { ExternalLink } from 'lucide-react'
-import { ArrowUpCircle } from 'lucide-react'
-import { Step, Steps } from 'fumadocs-ui/components/steps';
-import { EnvVariableConfig } from 'app/components/EnvVariableConfig'
-
-
-
-
-### 安装 Docker
-
-如果你的服务器在国内,建议使用阿里云的安装脚本,安装命令如下:
-
-```bash
-curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
-```
-
-在国外,可以直接使用官方脚本安装:
-
-```bash
-curl -fsSL https://get.docker.com | bash -s docker
-```
-
-如果您成功安装了 Docker 和 Docker-Compose,可以通过以下命令查看版本:
-
-```bash
-docker -v
-
-docker compose version
-```
-
-
-
-
-
-### 拉取配置文件
-
-
-自 Core v5.7.5 版本开始,Docker 相关配置发生重大变化,请重新阅读本文档(尤其是填入配置文件环节,配置有所变化)
-
-
-```bash
-cd && mkdir -p mx-space/core && cd $_
-
-# 拉取 docker-compose.yml 文件
-wget https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
-```
-
-
-
-
-
-### 配置 Core 启动配置文件
-
-在下方的表格里填入你的配置,然后点击复制,在 `docker-compose.yml` 里 `environment` 字段对应部分的内容后加入,调整细节使其符合 yaml 语法,保存即可。
-
-
-鼠标悬停在下方的表格中,可以查看对应的配置项名字。
-
-
-
-
-- **`JWT 密钥`**:需要填写长度不小于 16 个字符,不大于 32 个字符的字符串,用于加密用户的 JWT,务必保存好自己的密钥,不要泄露给他人。
-- **`被允许的域名`**:需要填写被允许的域名,通常是前端的域名,如果允许多个域名访问,用英文逗号,分隔。
-- **`是否开启加密`**:如果你确定要开启加密,将 false 改为 true,开启加密后,你需要在下方填写加密密钥。
-- **`加密密钥`**:如果你不知道这是什么,那么不建议开启此功能,具体内容可参考 [Key 加密与安全性](https://mx-space.js.org/docs/usage/security.html)
-
-
- 若开启加密,则需注意密钥长度**必须为 64 位且只有小写字母和数字**,不然会在初始化时报错。注意这是**不可逆**的,务必保存自己的秘钥。所以并不是非常推荐使用,除非你真的需要加密
- API Key.
-
-密钥可以通过 `openssl rand -hex 32` 命令生成。请务必牢记。
-
-
-
-
-
-
-
-### 启动 Core
-
-
-
-如果你的服务器在国内,无法拉取镜像或拉取速度过慢可自行使用代理或在 `docker-compose.yml` 里的 image 前添加镜像域名,比如 `docker.1panel.top/innei/mx-server:latest`。
-
-镜像域名可参考 [国内 Docker 服务状态 & 镜像加速监控](https://status.1panel.top/status/docker)
-
-
-```bash
-docker compose up -d
-```
-
-
-
-
-
-### 完成
-
-恭喜你完成了 Core 部署,不过仅仅如此是不够的,你需要配置好[反向代理](/docs/core/extra#反向代理)之后通过绑定域名登录后台(`你的域名/proxy/qaqdmin`)进行初始化,这里不再赘述具体过程。除此之外,如引言所述还需要部署一个**前端**主题用于展示,请参考 [前端主题文档](https://mx-space.js.org/docs/themes) 继续完成部署前端主题的步骤。
-
-
-
-
-## 相关链接
-
-
- }
- />
- }
- />
- }
- />
-
diff --git a/content/docs/core/extra.mdx b/content/docs/core/extra.mdx
deleted file mode 100644
index 2d07fb29..00000000
--- a/content/docs/core/extra.mdx
+++ /dev/null
@@ -1,487 +0,0 @@
----
-title: 拓展内容
-description: 此部分内容将说明一些额外的操作流程,请根据自己需要进行配置
-icon: Ellipsis
----
-
-## 反向代理
-
-在这里提供 **Mix-Space** 的反代配置步骤。
-
-当然不管使用哪种方法,都建议用控制面板(如宝塔、1Panel 等)完成配置,手写反代配置的大佬随意。
-
-另外,不管是前端还是后端的域名,都需要**配置好 HTTPS 证书**以保证网站能正常访问。
-
-### 图形化界面
-
-现代服务器面板(如 `1Panel` 和`宝塔面板`)自带的**反向代理**已足以满足 Mix-Space 所需的反代要求(包括 Websocket),因此我们更建议非高级用户使用图形化界面来操作和维护
-
-#### 宝塔面板
-
-进入`网站`,在`反向代理`栏目下点击`添加反代`
-
-`域名`填入你将要使用的域名,`目标`填写`URL地址` + `http://127.0.0.1:2333`
-
-#### 1Panel
-
-进入`网站 > 网站`,并创建一个新网站,选择`反向代理`
-
-`主域名`填入你将要使用的域名,并勾选`监听 IPV6`,代理类型选择 `http` ,地址填入 `127.0.0.1:2333`
-
-#### Vane
-
-由于 **Vane** 是一个新开发的反向代理(2025-09-09),**所以请做好出现异常问题的准备**,但是不要担心,出现任何代理问题的时候请携带**日志**给我们,我们会听取你们的反馈,目前已经测试过了 `mx-server` + `Shiroi` 请放心使用
-
-
-[Vane](https://github.com/canmi21/vane) 是一个现代的,100% 使用 Rust 编写的反向代理,其优势是大约 1.5-3MB 的内存占用,整 docker 镜像部署大约占用 5MB 磁盘大小
-详细步骤:
-
-首先使用 `SSL` 需要先获取证书,`Vane` 目前不包含 SSL 证书管理,有2个办法是:
- - `1panel` & '宝塔面板' 这些 GUI 运维工具自带了 acme.sh 可以GUI管理了给 Vane 导入证书文件
- - [lazy-acme](https://github.com/canmi21/lazy-acme) 这是 Vane 配套的管理工具,后端使用 [Lego](https://github.com/go-acme/lego), 目前只支持 `Cloudfalre` DNS 验证 + 少量主流免费 CA.
-
-如果使用`方法1`的话,需要你自行映射证书目录给 `~/vane/cert` 或者映射其他任何你喜欢的位置,内部存在的 `pem` 格式证书在下面 `zonefile` 内部修改使用
-
-关于 `Vane` 部署,推荐使用 [docker-compose.yml](https://github.com/canmi21/vane?tab=readme-ov-file#installation-and-usage) 部署
-
-然后需要编写一个 `Zone File` 采用 **TOML** 语法, 配置文件默认存放在 "~/vane/config.toml",Vane 虽然支持 `*` wildcard 匹配,但是还是建议分离域名管理会方便一些,例如:
-
-```toml
-# Vane main configuration file
-# This file maps hostnames to their specific configuration files.
-[domains]
-"example.com" = "example.com.toml"
-"api.example.com" = "api.example.com.toml"
-```
-
-这样就创建好了2个独立的域名,接下来,在该文件夹内分别创建 `example.com.toml` 和 `api.example.com.toml` 注意请替换为实际域名
-
-
-```toml
-# Vane domain configuration for example.com
-
-# --- Core Protocol Settings ---
-# Enable HTTPS on the standard port (443 by default).
-https = true
-# Enable HTTP/3 over QUIC on the HTTPS UDP port. Requires `https` to be true.
-http3 = true
-# Enable HSTS (HTTP Strict Transport Security) header to enforce HTTPS on clients.
-hsts = true
-# Behavior for plain HTTP requests on port 80:
-# "upgrade" (redirects to HTTPS), "reject" (blocks), or "allow".
-http_options = "reject"
-
-# --- TLS Certificate Settings ---
-[tls]
-# Path to the PEM-encoded TLS certificate file. Supports '~' for the home directory.
-cert = "~/vane/cert/example.com.pem"
-# Path to the PEM-encoded private key file. Supports '~' for the home directory.
-key = "~/vane/cert/example.com.key"
-
-# --- Method Filtering ---
-# Optional: Restrict which HTTP methods are allowed for this entire domain.
-# This check happens before CORS or routing. Use "*" to allow all methods.
-[methods]
-allow = "GET, POST, OPTIONS, HEAD"
-
-# --- CORS (Cross-Origin Resource Sharing) ---
-# Optional: Fine-grained CORS configuration.
-# If this section is present, Vane will override any CORS headers from the backend.
-[cors]
-# Map of allowed origins to their allowed methods.
-[cors.origins]
-# For methods, use a comma-separated string (e.g., "GET, POST"), or use "*" to allow all methods from that origin.
-"https://canmi.net" = "GET, POST, OPTIONS"
-
-# --- Rate Limiting ---
-[rate_limit]
-# Default rate limit applied to all requests for this domain unless a more specific rule matches.
-[rate_limit.default]
-# The time window for the rate limit (e.g., "1s", "10m", "1h").
-period = "1s"
-# Number of requests allowed in the period. Set to 0 to disable.
-requests = 20
-
-# --- Routing Rules ---
-# Define how incoming paths are proxied to backend targets.
-# Rules are matched from top to bottom.
-# [[routes]]
-# The URL path to match. Supports wildcards (*) at the end.
-# path = "/api/*"
-# A list of backend servers. Vane will try them in order.
-# If the first target fails (connection error or 5xx response), it will try the second, and so on.
-# targets = ["http://12.0.0.1:8000", "http://127.0.0.1:33433"] # Primary and fallback targets
-
-[[routes]]
-path = "/"
-websocket = true
-targets = ["http://127.0.0.1:2323"]
-```
-
-以及后端 `mx-server`
-
-```toml
-# Vane domain configuration for api.example.com
-
-https = true
-http_options = "reject"
-hsts = true
-http3 = false
-
-[tls]
-cert = "~/vane/cert/api.example.com.pem"
-key = "~/vane/cert/api.example.com.key"
-
-[methods]
-allow = "GET, POST, OPTIONS, HEAD"
-
-[rate_limit.default]
-period = "1s"
-requests = 20
-
-[[routes]]
-path = "/*"
-websocket = true
-targets = ["http://localhost:2333"]
-```
-
-注意这里 `2333` 和 `2323` 端口可能会需要按照你实际部署的 `mx-space` 来决定端口,如果你自己修改了的话, 以及端口,这里例示使用了
-`example.com` 这个裸域名作为前端,`api.example.com` 具体域名可能需要按照实际情况修改,当然如果你前端想要部署在三级域名上比如 `blog.example.com`上也是可以的,按照上述配置修改即可
-
-### Cloudflare Tunnel
-
-除非你在**非完整服务器环境**(如在 Sealos 或 Huggingface Space 上部署),否则我们不推荐在容器内使用该功能,而应在宿主机内配置 **Cloudflare Tunnel** 以避免后期出现管理不方便等问题
-
-
-启动该功能需要两个环境变量
- - `ENABLE_CLOUDFLARED` = **true**
- - `CF_ZERO_TRUST_TOKEN` = **Tunnel 给的令牌(删掉 cloudflared.exe service install,只保留令牌部分)**
-
-#### 详细步骤:
-1.申请 Cloudflare Zero Trust,关于申请方式请自行查找
-
-2.添加一条隧道,连接方式选择 Cloudflared,名称任意
-
-3.添加一个 Public Hostname,回源选择 HTTP,端口选择 2333
-
-一旦启动成功,你应当在日志中看到如下输出,并在 Cloudflare 后台看到客户端正常上线:
-```
-============================================
-Starting Cloudflared Tunnel
-============================================
-
-============================================
-2025-06-06T02:22:40Z INF Using SysV
-2025-06-06T02:22:41Z INF Linux service for cloudflared installed successfully
-```
-
-### 手写配置
-
-
-手写配置文件需要较高的**技术功底**,请量力而行
-
-
-#### 双域名
-
-这里假定前端域名为 `www.example.com`,后端为 `server.example.com`。
-
-以下是后端 `server.example.com` 反代配置部分
-
-```nginx
-server {
- ## 反向代理开始
- ## WebSocket
- location /socket.io {
- proxy_pass http://127.0.0.1:2333/socket.io;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header REMOTE-HOST $remote_addr;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- proxy_buffering off;
- proxy_http_version 1.1;
- add_header Cache-Control no-cache;
- }
- ## Others
- location / {
- proxy_pass http://127.0.0.1:2333;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header REMOTE-HOST $remote_addr;
- add_header X-Cache $upstream_cache_status;
- }
- ## 反向代理结束
-}
-```
-
-前端 `www.example.com` 反代部分
-
-```nginx
-server{
- location ~* \.(gif|png|jpg|css|js|woff|woff2)$ {
- proxy_pass http://127.0.0.1:2323;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header REMOTE-HOST $remote_addr;
- expires 30d;
- }
- location / {
- proxy_pass http://127.0.0.1:2323;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header REMOTE-HOST $remote_addr;
- add_header X-Cache $upstream_cache_status;
- add_header Cache-Control no-cache;
- proxy_intercept_errors on;
- }
-}
-```
-
-
-如果您使用此部分示例配置 Nginx 反向代理,您的:
-- API 地址为 `https://server.example.com/api/v2`
-- 前端(Kami/Shiro)地址为 `https://www.example.com`
-- GateWay 为 `https://server.example.com`
-- 本地后台为 `https://server.example.com/proxy/qaqdmin`
-
-
-#### 单域名
-
-以下配置文件以 Nginx 为例,请自行修改 SSL 证书路径以及自己的网站域名。
-
-若使用 Caddy 进行配置可参考 [Caddyfile 文件示例](https://github.com/mx-space/docker/blob/master/Caddyfile.example)进行相应修改。
-
-```nginx
-server {
- ## 反向代理开始
- ## WebSocket 地址
- location /socket.io {
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_buffering off;
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_pass http://127.0.0.1:2333/socket.io;
- }
- ## API 地址
- location /api/v2 {
- proxy_pass http://127.0.0.1:2333/api/v2;
- }
- ## 简读 render 地址
- location /render {
- proxy_pass http://127.0.0.1:2333/render;
- }
- ## Kami 地址
- location / {
- proxy_pass http://127.0.0.1:2323;
- }
- ## 后台地址
- location /proxy {
- proxy_pass http://127.0.0.1:2333/proxy;
- }
- location /qaqdmin {
- proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
- }
- ## 反向代理结束
-}
-```
-
-完整示例如下
-
-```nginx
-server {
- listen 80;
- listen 443 ssl http2 ;
- ## 绑定域名
- server_name www.example.com;
- index index.html;
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Host $server_name;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- error_log /www/sites/www.example.com/log/error.log;
- access_log /www/sites/www.example.com/log/access.log;
- location /socket.io {
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_pass http://127.0.0.1:2333/socket.io;
- }
- location /api/v2 {
- proxy_pass http://127.0.0.1:2333/api/v2;
- }
- location /render {
- proxy_pass http://127.0.0.1:2333/render;
- }
- location / {
- proxy_pass http://127.0.0.1:2323;
- }
- location /qaqdmin {
- proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
- }
- location /proxy {
- proxy_pass http://127.0.0.1:2333/proxy;
- }
-
- ssl_certificate /www/sites/www.example.com/ssl/fullchain.pem;
- ssl_certificate_key /www/sites/www.example.com/ssl/privkey.pem;
- ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
- ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
- ssl_prefer_server_ciphers on;
- ssl_session_cache shared:SSL:10m;
- ssl_session_timeout 10m;
- error_page 497 https://$host$request_uri;
- limit_conn perserver 300;
- limit_conn perip 25;
- limit_rate 512k;
-}
-```
-
-
-如果您使用此部分示例配置 Nginx 反向代理,您的:
-- API 地址为 `https://www.example.com/api/v2`
-- 前端(Kami/Shiro)地址为 `https://www.example.com`
-- GateWay 为 `https://www.example.com`
-- 本地后台为 `https://www.example.com/proxy/qaqdmin`
-
-
-## 配置其他 Redis 服务
-
-如果你需要使用来自 (远端 / 非容器) 的 Redis 服务,你可以通过使用 `argv` 来动态传入对应的配置项。
-
-支持传入如下值:
-
-- `redis_host` Redis 服务地址,域名、IP 都可以
-- `redis_port` Redis 服务端口
-- `redis_password` Redis 服务密码
-- `disable_cache` 是否禁用缓存,默认不启用
-
-在默认情况下,我们认为这样已经足够了。
-
-### 对于 Docker 部署
-
-和编辑其他环境变量一样,在 `service.app` 的 `environment` 部分添加你需要传入的值,如下所示:
-
-```yml
-services:
- app:
- container_name: mx-server
- image: innei/mx-server:latest
- environment:
- - TZ=Asia/Shanghai
- - NODE_ENV=production
- - DB_HOST=mongo
- - REDIS_HOST=远端地址 // [!code highlight]
- - REDIS_PASSWORD=redis?passwd // [!code highlight]
- - ALLOWED_ORIGINS=localhost
- - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
- volumes:
- - ./data/mx-space:/root/.mx-space
-```
-
-修改完成后 `docker compose up -d` 重启服务即可。
-
-### 对于进阶部署
-
-针对这种部署方式,我们可以修改 `ecosystem.config.js` 在 12 行,也就是 `script` 这一项,添加你需要传入的值,如下所示:
-
-```diff
-const { cpus } = require('os')
-const { execSync } = require('child_process')
-const nodePath = execSync(`npm root --quiet -g`, { encoding: 'utf-8' }).split(
- '\n',
-)[0]
-
-const cpuLen = cpus().length
-module.exports = {
- apps: [
- {
- name: 'mx-server',
-- script: 'out/index.js,
-+ script: 'out/index.js --redis_host=远端地址 --redis_password=redis?passwd',
- autorestart: true,
- exec_mode: 'cluster',
-```
-
-当你修改完成,你需要重启服务:
-
-```bash
-pnpm prod:pm2
-```
-
-## 配置其他 MongoDB 服务
-
-如果你需要使用来自 (远端 / 非容器) 的 MongoDB 服务,你可以通过使用 `argv` 来动态传入对应的配置项。
-
-支持传入如下值:(除 `collection_name` 外其余变量名在 Docker 中变量均为对应大写)
-
-- `collection_name` 数据库集合名字(Docker 对应变量为 `DB_COLLECTION_NAME`)
-- `db_host` MongoDB 服务地址,域名、IP 都可以
-- `db_port` MongoDB 服务端口
-- `db_user` MongoDB 服务用户名
-- `db_password` MongoDB 服务密码
-- `db_connection_string` MongoDB 数据库连接地址(以 `mongodb://` 开头的一串内容),此配置项优先级大于上述五项
-- `db_options` MongoDB 数据库连接选项
-
-
-如果你需要使用密码登录,你不仅仅需要传入 password,还需要传入 user,建议你对数据库集合划分好用户权限
-
-
-### 对于 Docker 部署
-
-和编辑其他环境变量一样,在 `services.app` 的 `environment` 部分添加你需要传入的值,如下所示:
-
-```yml
-services:
- app:
- container_name: mx-server
- image: innei/mx-server:latest
- environment:
- - TZ=Asia/Shanghai
- - NODE_ENV=production
- - DB_HOST=远端地址 // [!code highlight]
- - DB_USER=mongodb-test // [!code highlight]
- - DB_PASSWORD=db?passwd // [!code highlight]
- - REDIS_HOST=redis
- - ALLOWED_ORIGINS=localhost
- - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
- volumes:
- - ./data/mx-space:/root/.mx-space
-```
-
-修改完成后 `docker compose up -d` 重启服务即可。
-
-### 对于进阶部署
-
-和 Redis 一样,我们可以修改 `ecosystem.config.js` 在 12 行,也就是 `script` 这一项,添加你需要传入的值,如下所示:
-
-```javascript
-const { cpus } = require('os')
-const { execSync } = require('child_process')
-const nodePath = execSync(`npm root --quiet -g`, { encoding: 'utf-8' }).split(
- '\n',
-)[0]
-
-const cpuLen = cpus().length
-module.exports = {
- apps: [
- {
- name: 'mx-server',
-+ script: 'out/index.js --db_host=远端地址 --db_user=mongodb-test --db_password=db?passwd',
- autorestart: true,
- exec_mode: 'cluster',
-```
-
-当你修改完成,你需要重启服务:
-
-```bash
-pnpm prod:pm2
-```
diff --git a/content/docs/core/features.mdx b/content/docs/core/features.mdx
deleted file mode 100644
index 9f78ec61..00000000
--- a/content/docs/core/features.mdx
+++ /dev/null
@@ -1,61 +0,0 @@
----
-title: 主要功能
-icon: SquareFunction
----
-
-## 日记
-
-作为个人空间,日记是必不可少的功能。Mix Space 的日记功能非常强大,它支持:
-
-- 标记「回顾日记」,并自动将其归档到「回顾日记」页面
-- 私人日记密码保护,只有知道密码的人才能查看
-- 定时发布,可以将日记定时发布到未来的某个时间点
-
-## 评论
-
-评论是一个网站的重要组成部分,Mix Space 的评论功能非常强大,它支持:
-
-- 反垃圾评论,使用 Mix Space 的反垃圾评论系统配合多种自定义规则,可以有效的防止垃圾评论
-- 邮件通知,当有人评论时,会发送邮件通知给文章作者
-
-## xLog 集成
-
-通过 Mix Space 的 xLog 功能,你可以将你的博客文章同步到 [xLog 平台](https://xlog.app)。并且当你没有为文章写摘要的时候,可以直接使用 xLog 平台生成的摘要,当然你也可以使用自己的 GPT API Key 去调用 GPT 生成文章摘要。
-
-> [xLog](https://xlog.app/about) 是面向所有人的最棒的链上、开源的博客社区。
-
-## 文件管理
-
-你可以使用 Mix Space 上传文件,然后在任意地方中使用,比如文章中,或者是日记中。你可以使用 Markdown 语法插入图片,也可以使用 HTML 语法插入图片。
-
-## 通知
-
-Mix Space 支持多种通知方式,让你不错过任何一条重要的通知。
-
-- 邮件通知,当有人评论时,会发送邮件通知给文章作者
-- Bark 通知支持
-
-## 友链
-
-Mix Space 的友链系统支持自助申请,你可以在后台设置是否需要审核,如果需要审核,你可以在后台设置通过 OR 拒绝理由。并且在后台可以看到友链的可用性检查结果。
-
-## 计划任务
-
-Mix Space 有着强大的计划任务功能,它们都被统一管理,你可以在后台执行计划任务:
-
-- 备份数据库
-- 清除缓存、访问记录、临时文件
-- 推送百度搜索
-- 推送 Algolia 搜索
-- 删除过期的数据
-- etc...
-
-## 其他
-
-Mix Space 还有很多其他功能,比如:
-
-- 动态化配置前端,你可以在后台设置前端的配置,比如网站名称,网站描述,网站图标等等
-- 云函数,你可以在后台设置云函数,让你的网站更加强大
-- Algolia Search,你可以在后台设置 Algolia Search,让你的网站支持站内搜索功能
-- 项目展示功能,你可以向访客展示你的项目,展现你的技术能力
-- 迁移,Mix Space 支持从 Markdown 导入文章,也支持导出文章为 Markdown。
\ No newline at end of file
diff --git a/content/docs/core/index.mdx b/content/docs/core/index.mdx
deleted file mode 100644
index 40de9c2a..00000000
--- a/content/docs/core/index.mdx
+++ /dev/null
@@ -1,71 +0,0 @@
----
-title: 引言
-icon: CirclePlay
----
-
-
-在本章节,我们将完成的是 **后端** 的安装,而 **前端** 的安装则需要你阅读 [前端主题文档](/docs/themes)。
-
-
-**Mix Space** 是一个一款简洁而不简单的个人博客系统,它够快,够现代。你可以利用它构建一个属于自己的个人空间,记录生活,分享知识。
-
-import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
-
-
-
-
-- **Linux** / **macOS**
-- Linux 内核版本 >= **4.19**
-- Memory >= **1G**
-
-
-
-
-## 快速开始
-
-
-我们提供了两种部署方式,社区贡献了一种自动脚本模式,同时社区用户也分享了更多的部署方式,你可以根据自己的喜好选择一种部署方式。
-
-
-import { Container, SquareTerminal, Pickaxe, Share2, Ellipsis, Paintbrush } from 'lucide-react';
-
-
- }>使用 Docker 部署后端
- }>使用传统方式部署后端
- }>使用 Bash 自动脚本一键部署后端
- }>部署常见问题与拓展内容
- }>了解社区用户们分享的部署方式
-
-
-还有更多部署方式吗?欢迎您向文档提交 [Pull Request](https://github.com/mx-space/docs/pulls) 以分享您的部署方式。按上方**后端部署文档**完成你的部署后,你可以通过下面的方式继续部署 Mix Space **前端** *(为什么分开部署?请查看 [一些你需要知道的事情](#一些你需要知道的事情))*
-
-
- } />
-
-
-## 一些你需要知道的事情
-
-### 遇到报错怎么办?
-
-新时代新风气,我们遇到了一个人工智能蓬勃发展的时代,所以在你遇到了问题的时候请**先询问** 各种 Ai 助手程序,它们会帮助你解决大部分疑问。
-
-如果你遇到了一些**人工智能解决不了**的问题,那么请**再次阅读文档**,如果文档依旧没有解决你的问题,那么请在**对应仓库**的 **GitHub Issues** 中提出你的问题,我们会尽快解决。
-
-### Mix Space 的组成结构
-
-import { File, Folder, Files } from 'fumadocs-ui/components/files';
-
-
-
-
-
-
-
-
-所以,**Mix Space** 由两部分组成:**后端** 和 **前端**。如果你没法理解的话,请**先询问** 各种 Ai 助手程序关于前后端分离博客程序的定义,比如`ChatGPT`、`Claude`、`Gemini`、`Kimi` 等等,以此来了解它们、以及知道它们的区别。
-
-总之你需要知道的便是:这不是像 **Typecho**、**WordPress** 这样的「一步曲」就搞定的系统,而是需要 **「两步曲」** 才能完成安装。
-
-但万幸的是,我们开发者已经为你准备好了一切,你只需要按照文档**推荐的步骤**来操作即可,即使你不是开发者,也可以轻松完成安装。
-
-知道了这些,你就可以避免掉大部分的问题了,开始安装体验吧!
diff --git a/content/docs/core/meta.json b/content/docs/core/meta.json
deleted file mode 100644
index c98cfb21..00000000
--- a/content/docs/core/meta.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "title": "后端部署",
- "description": "部署 Mix Space 的后端部分",
- "icon": "Server",
- "root": true,
- "pages": [
- "---信息---",
- "index",
- "features",
- "---部署---",
- "docker",
- "advanced",
- "bash",
- "extra",
- "community"
- ]
-}
\ No newline at end of file
diff --git a/content/docs/deploy/agent.mdx b/content/docs/deploy/agent.mdx
new file mode 100644
index 00000000..44dac385
--- /dev/null
+++ b/content/docs/deploy/agent.mdx
@@ -0,0 +1,215 @@
+---
+title: 使用 AI Agent 部署
+description: 用 AI 编程助手(如 Claude Code、Codex、Cursor 等)自动化部署 Mix Space
+icon: Bot
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+如果你不熟悉 Linux 运维,或者不想手动执行命令,可以使用 AI 编程助手来帮你完成整个部署过程。你只需要用自然语言描述需求,Agent 会自动在服务器上执行操作。
+
+## 支持的 Agent 工具
+
+| 工具 | 说明 | 适用场景 |
+|------|------|----------|
+| **Claude Code** | Anthropic 的终端编程助手,支持远程执行 | 推荐新手使用 |
+| **Codex CLI** | OpenAI 的命令行 Agent | 习惯 OpenAI 生态的用户 |
+| **Cursor** | AI 代码编辑器,支持终端 | 想在编辑器里操作的用户 |
+| **其他 MCP/SSH Agent** | 任何能 SSH 到服务器的 AI 工具 | 高级用户 |
+
+
+以下以 Claude Code 为例,其他 Agent 工具的流程类似——核心都是让 Agent 通过 SSH 连接到你的服务器并执行部署命令。
+
+
+## 准备工作
+
+
+
+### 准备一台服务器
+
+你需要一台已安装 Linux 的服务器(推荐 Ubuntu 22.04+),并确保:
+
+- 可以通过 SSH 连接
+- 有 root 或 sudo 权限
+- 80 和 443 端口未占用
+
+记录以下信息:
+- 服务器 IP 地址
+- SSH 端口(默认 22)
+- 登录用户名和密码(或 SSH 密钥)
+
+
+
+### 准备域名
+
+将你的域名 A 记录指向服务器 IP:
+
+| 记录类型 | 名称 | 值 |
+|----------|------|-----|
+| A | `@` | 你的服务器 IP |
+| A | `www` | 你的服务器 IP(可选) |
+
+
+
+### 安装 Agent 工具
+
+以 Claude Code 为例,在本地电脑上安装:
+
+```bash
+npm install -g @anthropic-ai/claude-code
+```
+
+其他工具请参考各自的安装文档。
+
+
+
+## 开始部署
+
+
+
+### 将 Mix Space 文档交给 Agent
+
+为了让 Agent 了解 Mix Space 的部署方式,先让它读取文档。在 Agent 对话中发送:
+
+```
+请帮我部署 Mix Space。先阅读以下文档了解部署方式:
+- https://mx-space.js.org/llm.txt(项目概览)
+- https://mx-space.js.org/docs/deploy/docker(Docker 部署指南)
+- https://mx-space.js.org/docs/deploy/reverse-proxy(反向代理配置)
+- https://mx-space.js.org/docs/deploy/ssl(SSL 证书配置)
+```
+
+或者如果你使用 Claude Code,可以直接让它读取 Agent Skill:
+
+```
+请读取 https://mx-space.js.org/agent-skills/mix-space-expert.md,
+然后帮我完成 Mix Space 的完整部署。
+```
+
+
+
+### 告诉 Agent 你的信息
+
+将以下信息提供给 Agent(请替换为你的实际值):
+
+```
+我的服务器信息:
+- IP: 123.456.789.0
+- SSH 用户: root
+- SSH 端口: 22
+- 域名: example.com
+
+请帮我:
+1. SSH 连接到服务器
+2. 安装 Docker
+3. 用 Docker 部署 Mix Space 后端
+4. 配置 Nginx 反向代理
+5. 配置 SSL 证书(使用 Let's Encrypt)
+6. 验证服务可以正常访问
+```
+
+
+不要将服务器密码直接发送给云端的 AI 服务。建议使用 SSH 密钥认证,或使用 Agent 的本地模式(如 Claude Code 的 `--dangerously-skip-permissions` 模式)。
+
+
+
+
+### Agent 自动执行
+
+Agent 会依次执行以下操作:
+
+1. **SSH 连接**到你的服务器
+2. **安装 Docker**(如果尚未安装)
+3. **克隆配置文件**并编辑环境变量
+4. **启动服务** `docker compose up -d`
+5. **安装 Nginx** 并配置反向代理
+6. **申请 SSL 证书**(Certbot 或其他方式)
+7. **验证**服务可以通过 HTTPS 访问
+
+你只需要在 Agent 询问时确认操作即可。
+
+
+
+### 验证部署
+
+让 Agent 帮你确认:
+
+```
+请帮我验证:
+1. 访问 https://example.com/api/v2/ping 是否返回 pong
+2. 访问 https://example.com/proxy/qaqdmin 是否能打开后台
+3. 检查 Docker 容器状态是否全部 healthy
+```
+
+
+
+## 部署后配置
+
+部署完成后,你可以继续让 Agent 帮你:
+
+```
+请帮我完成以下初始配置:
+1. 在后台「设定 → SEO」中设置网站标题和描述
+2. 在「设定 → 网站设置」中填写前端地址
+3. 配置 GitHub OAuth 登录(Client ID: xxx, Secret: xxx)
+4. 开启 AI 功能并配置 Provider(API Key: xxx)
+```
+
+
+Agent 可以帮你执行命令行操作和调用 API,但涉及敏感信息(如 API Key)时请谨慎操作。
+
+
+## 常用 Prompt 模板
+
+### 一键完整部署
+
+```
+你是 Mix Space 部署专家。请 SSH 到我的服务器(IP: ___,用户: root),
+帮我完成以下操作:
+1. 安装 Docker 和 Docker Compose
+2. 下载 Mix Space 的 docker-compose.yml
+3. 设置 JWT_SECRET 为随机字符串,ALLOWED_ORIGINS 为我的域名
+4. 启动所有服务
+5. 配置 Nginx 反向代理,将 ___ 域名指向 localhost:2333
+6. 用 Certbot 申请 SSL 证书
+7. 验证 https://___ 可以正常访问
+
+我的域名是:___
+```
+
+### 仅部署后端
+
+```
+请 SSH 到我的服务器,帮我用 Docker 部署 Mix Space 后端。
+只需要部署后端,不需要配置 Nginx 和 SSL。
+我的服务器 IP: ___,域名: ___
+```
+
+### 排查问题
+
+```
+我的 Mix Space 部署后无法访问,请帮我排查:
+1. 检查 Docker 容器状态
+2. 检查端口 2333 是否在监听
+3. 检查 Nginx 配置是否正确
+4. 查看 Mix Space 日志是否有报错
+```
+
+### 更新版本
+
+```
+请 SSH 到我的服务器,帮我更新 Mix Space 到最新版本。
+部署目录在 ~/mx-space/core。
+```
+
+## 注意事项
+
+- **安全性**:不要将密码、API Key 等敏感信息直接发送给云端 AI 服务。建议使用 SSH 密钥认证。
+- **备份**:让 Agent 执行重大操作前,先让它做一次数据库备份。
+- **验证**:每次 Agent 完成操作后,自己也要验证结果。
+- **回滚**:如果 Agent 操作出错,可以通过 `docker compose down` 和恢复备份来回滚。
+
+
+Agent 部署是全新的方式,适合不想折腾命令行的用户。如果你更喜欢手动操作,请参考 [Docker 部署](/docs/deploy/docker) 页面。
+
diff --git a/content/docs/core/community.mdx b/content/docs/deploy/community.mdx
similarity index 99%
rename from content/docs/core/community.mdx
rename to content/docs/deploy/community.mdx
index da098b3d..4a2ff017 100644
--- a/content/docs/core/community.mdx
+++ b/content/docs/deploy/community.mdx
@@ -1,5 +1,5 @@
---
-title: 社区分享
+title: 社区部署方案
description: 社区用户分享的部署方式
icon: Share2
---
@@ -130,5 +130,4 @@ import { FileText, Video } from "lucide-react";
Mix Space 后端部署博文教程 | By 极夜System | 平台:Selfhost
-
diff --git a/content/docs/deploy/docker.mdx b/content/docs/deploy/docker.mdx
new file mode 100644
index 00000000..660126c5
--- /dev/null
+++ b/content/docs/deploy/docker.mdx
@@ -0,0 +1,120 @@
+---
+title: Docker 部署
+description: 通过 Docker 部署 Mix Space 后端
+icon: Container
+---
+
+import { Step, Steps } from 'fumadocs-ui/components/steps';
+import { Callout } from 'fumadocs-ui/components/callout';
+import { Card, Cards } from 'fumadocs-ui/components/card';
+import { ExternalLink } from 'lucide-react';
+import { EnvVariableConfig } from 'app/components/EnvVariableConfig'
+
+
+
+
+### 安装 Docker
+
+如果你的服务器在国内,建议使用阿里云的安装脚本:
+
+```bash
+curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
+```
+
+在国外,可以直接使用官方脚本:
+
+```bash
+curl -fsSL https://get.docker.com | bash -s docker
+```
+
+验证安装:
+
+```bash
+docker -v
+docker compose version
+```
+
+
+
+
+### 拉取配置文件
+
+```bash
+cd && mkdir -p mx-space/core && cd $_
+
+# 拉取 docker-compose.yml 文件
+wget https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
+```
+
+
+
+
+### 配置环境变量
+
+在下方的表格中填入配置,点击复制后粘贴到 `docker-compose.yml` 的 `environment` 字段中。
+
+
+
+- **`JWT 密钥`**:长度 16-32 个字符,用于加密用户 JWT,务必保存好不要泄露。
+- **`被允许的域名`**:通常是前端的域名,多个用英文逗号分隔。
+- **`是否开启加密`**:如需开启,将 `false` 改为 `true`。
+- **`加密密钥`**:开启加密后必填,长度必须为 64 位且只有小写字母和数字。可用 `openssl rand -hex 32` 生成。**此操作不可逆,请谨慎。**
+
+
+
+
+### 启动服务
+
+
+如果服务器在国内,拉取镜像速度过慢,可在 `docker-compose.yml` 的 image 前添加镜像域名,例如 `docker.1panel.top/innei/mx-server:latest`。
+
+
+```bash
+docker compose up -d
+```
+
+
+
+
+### 验证
+
+启动后,请按以下清单确认服务正常:
+
+- [ ] `docker compose ps` 显示所有服务状态为 healthy
+- [ ] `curl http://localhost:2333/api/v2/ping` 返回 `pong`
+- [ ] 浏览器能打开后台初始化页面 `http://你的域名/proxy/qaqdmin`
+
+
+
+
+
+## 下一步
+
+
+ }>
+ 将域名指向你的服务,并配置 HTTPS
+
+ }>
+ 部署前端主题完成整套系统
+
+
diff --git a/content/docs/deploy/external-services.mdx b/content/docs/deploy/external-services.mdx
new file mode 100644
index 00000000..ba5ba14a
--- /dev/null
+++ b/content/docs/deploy/external-services.mdx
@@ -0,0 +1,114 @@
+---
+title: 使用外部数据库
+description: 配置外部 Redis 或 PostgreSQL 服务
+icon: Database
+---
+
+如果你需要使用来自远端或非容器内的 Redis / PostgreSQL 服务,可以通过环境变量或启动参数传入配置。
+
+## 外部 Redis
+
+支持传入的参数:
+
+| 参数 | 说明 |
+|------|------|
+| `redis_host` | Redis 服务地址,域名或 IP |
+| `redis_port` | Redis 服务端口 |
+| `redis_password` | Redis 服务密码 |
+| `disable_cache` | 是否禁用缓存,默认不启用 |
+
+### Docker 部署
+
+在 `docker-compose.yml` 的 `services.app.environment` 中添加:
+
+```yaml
+services:
+ app:
+ container_name: mx-server
+ image: innei/mx-server:latest
+ environment:
+ - TZ=Asia/Shanghai
+ - NODE_ENV=production
+ - REDIS_HOST=远端地址
+ - REDIS_PASSWORD=redis?passwd
+ - ALLOWED_ORIGINS=localhost
+ - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
+ volumes:
+ - ./data/mx-space:/root/.mx-space
+```
+
+修改完成后执行 `docker compose up -d` 重启服务。
+
+### 源码部署
+
+修改 `ecosystem.config.js`,在 `script` 项中添加参数:
+
+```diff
+ script: 'out/index.js',
++ script: 'out/index.js --redis_host=远端地址 --redis_password=redis?passwd',
+```
+
+然后重启服务:
+
+```bash
+pnpm prod:pm2
+```
+
+## 外部 PostgreSQL
+
+支持传入的参数:(Docker 中为对应大写环境变量)
+
+| 参数 | 说明 |
+|------|------|
+| `pg_host` | PostgreSQL 服务地址 |
+| `pg_port` | PostgreSQL 服务端口 |
+| `pg_user` | PostgreSQL 用户名 |
+| `pg_password` | PostgreSQL 密码 |
+| `pg_database` | PostgreSQL 数据库名 |
+| `pg_connection_string` | 连接地址(`postgresql://` 或 `postgres://` 开头),优先级高于以上五项 |
+| `pg_ssl` | 是否启用 SSL 连接,`true` 为启用 |
+| `pg_max_pool_size` | 连接池大小,默认 `20` |
+
+
+如果使用密码登录,必须同时传入 `user` 和 `password`,建议对数据库划分好用户权限。
+
+
+### Docker 部署
+
+在 `docker-compose.yml` 的 `services.app.environment` 中添加:
+
+```yaml
+services:
+ app:
+ container_name: mx-server
+ image: innei/mx-server:latest
+ environment:
+ - TZ=Asia/Shanghai
+ - NODE_ENV=production
+ - PG_HOST=远端地址
+ - PG_USER=postgres-test
+ - PG_PASSWORD=db?passwd
+ - PG_DATABASE=mx_core
+ - REDIS_HOST=redis
+ - ALLOWED_ORIGINS=localhost
+ - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
+ volumes:
+ - ./data/mx-space:/root/.mx-space
+```
+
+修改完成后执行 `docker compose up -d` 重启服务。
+
+### 源码部署
+
+修改 `ecosystem.config.js`,在 `script` 项中添加参数:
+
+```diff
+ script: 'out/index.js',
++ script: 'out/index.js --pg_host=远端地址 --pg_user=postgres-test --pg_password=db?passwd --pg_database=mx_core',
+```
+
+然后重启服务:
+
+```bash
+pnpm prod:pm2
+```
diff --git a/content/docs/deploy/index.mdx b/content/docs/deploy/index.mdx
new file mode 100644
index 00000000..86ae116a
--- /dev/null
+++ b/content/docs/deploy/index.mdx
@@ -0,0 +1,51 @@
+---
+title: 选择部署方式
+description: 根据你的技术背景选择合适的 Mix Space 部署方式
+icon: GitBranch
+---
+
+import { Card, Cards } from 'fumadocs-ui/components/card';
+import { Bot, Container, Pickaxe, SquareTerminal } from 'lucide-react';
+
+Mix Space 提供四种部署方式。根据你的技术背景选择最合适的一种。
+
+## 部署方式对比
+
+| 方式 | 难度 | 维护成本 | 适合谁 |
+|------|------|----------|--------|
+| AI Agent 部署 | ⭐ | 低 | 不熟悉命令行的用户,想用 AI 帮忙 |
+| Docker | ⭐⭐ | 低 | 有基础 Linux 知识的用户,推荐 |
+| 一键脚本 | ⭐ | 中 | 想自动化部署的用户 |
+| 源码编译 | ⭐⭐⭐ | 高 | 开发者,需要二次开发 |
+
+## 快速开始
+
+
+ }>
+ 让 AI 助手帮你全自动部署,适合新手
+
+ }>
+ 推荐大多数用户使用,简单稳定
+
+ }>
+ 自动化安装,适合懒人
+
+ }>
+ 面向开发者,完全可控
+
+
+
+## 如何选择
+
+- **不想碰命令行** → 选择 [AI Agent 部署](/docs/deploy/agent),用自然语言让 AI 帮你完成全部操作
+- **有一定 Linux 基础** → 选择 [Docker 部署](/docs/deploy/docker),稳定、可维护、社区支持最好
+- **想在服务器上一键搞定** → 选择 [一键脚本部署](/docs/deploy/one-script),自动安装依赖并配置
+- **想改后端代码或深度定制** → 选择 [源码部署](/docs/deploy/source),完全可控但维护成本更高
+
+## 部署后必做
+
+无论选择哪种方式,部署完成后都需要:
+
+1. 配置 [反向代理](/docs/deploy/reverse-proxy) — 将域名指向服务
+2. 配置 [SSL 证书](/docs/deploy/ssl) — 启用 HTTPS
+3. 部署 [前端主题](/docs/themes) — 完成整套系统
diff --git a/content/docs/deploy/meta.json b/content/docs/deploy/meta.json
new file mode 100644
index 00000000..49402eb4
--- /dev/null
+++ b/content/docs/deploy/meta.json
@@ -0,0 +1,17 @@
+{
+ "title": "部署",
+ "description": "将 Mix Space 部署到你的服务器",
+ "icon": "Server",
+ "root": true,
+ "pages": [
+ "index",
+ "docker",
+ "agent",
+ "one-script",
+ "source",
+ "reverse-proxy",
+ "ssl",
+ "external-services",
+ "community"
+ ]
+}
diff --git a/content/docs/core/bash.mdx b/content/docs/deploy/one-script.mdx
similarity index 69%
rename from content/docs/core/bash.mdx
rename to content/docs/deploy/one-script.mdx
index e6eeea10..87fb675a 100644
--- a/content/docs/core/bash.mdx
+++ b/content/docs/deploy/one-script.mdx
@@ -1,13 +1,16 @@
---
-title: Bash 自动脚本
-description: 一种自动部署 MixSpace 后端的 Bash 脚本
+title: 一键脚本部署
+description: 使用 Bash 脚本自动部署 Mix Space 后端
icon: SquareTerminal
---
-本脚本由社区用户“[Mikuの鬆](https://github.com/PaloMiku)”维护,如遇问题请前往对应的 Github 仓库提出Issue。
+此脚本由社区维护,官方文档仅作引用。如遇问题请前往对应的 GitHub 仓库提出 Issue。
+
+本脚本由社区用户“[Mikuの鬆](https://github.com/PaloMiku)”维护。
+
import { ToGithub } from '@/app/components/ToGithub';
@@ -15,7 +18,7 @@ import { ToGithub } from '@/app/components/ToGithub';
## 介绍
-这是一种在服务器自动安装 Docker 和进行 MixSpace 后端部署的 Bash 脚本,它可以帮助你交互式快速部署 MixSpace 后端。
+这是一种在服务器自动安装 Docker 和进行 Mix Space 后端部署的 Bash 脚本,它可以帮助你交互式快速部署 Mix Space 后端。
注意脚本会自动根据是否为中国大陆网络环境按需修改服务器 Docker 安装源和镜像源。
@@ -41,7 +44,7 @@ curl -sSL https://github.moeyy.xyz/https://raw.githubusercontent.com/PaloMiku/Mx
## 预配置文件
-参考下方示例修改并粘贴到`mxshell.env`文件,并将其与脚本置于同一目录后运行脚本,脚本会根据配置文件内容自动完成前后端部署。
+参考下方示例修改并粘贴到 `mxshell.env` 文件,并将其与脚本置于同一目录后运行脚本,脚本会根据配置文件内容自动完成前后端部署。
### 配置文件示例
@@ -50,10 +53,10 @@ curl -sSL https://github.moeyy.xyz/https://raw.githubusercontent.com/PaloMiku/Mx
JWT_SECRET=
# 需要填写被允许访问前端的域名,如果允许多个域名访问,用英文逗号,分隔。
ALLOWED_ORIGINS=
-# MixSpace 容器文件存储目录
+# Mix Space 容器文件存储目录
TARGET_DIR="/opt/mxspace"
```
- **`JWT 密钥`**:需要填写长度不小于 16 个字符,不大于 32 个字符的字符串,用于加密用户的 JWT,务必保存好自己的密钥,不要泄露给他人。
- **`被允许的域名`**:需要填写被允许访问容器的域名,通常是前端的域名,如果允许多个域名访问,用英文逗号,分隔。
-- **`MixSpace 容器文件存储目录`**:指定文件存储路径,通常是 `/opt/mxspace`。
\ No newline at end of file
+- **`Mix Space 容器文件存储目录`**:指定文件存储路径,通常是 `/opt/mxspace`。
diff --git a/content/docs/deploy/reverse-proxy.mdx b/content/docs/deploy/reverse-proxy.mdx
new file mode 100644
index 00000000..bef49957
--- /dev/null
+++ b/content/docs/deploy/reverse-proxy.mdx
@@ -0,0 +1,260 @@
+---
+title: 反向代理
+description: 配置反向代理以通过域名访问 Mix Space
+icon: Network
+---
+
+## 为什么需要反向代理
+
+Mix Space 默认运行在本地端口(后端 `2333`,前端 `2323`),反向代理可以将域名请求转发到对应端口,并提供 HTTPS、WebSocket 支持。
+
+## 图形化面板
+
+现代服务器面板(如 1Panel、宝塔面板)自带的反向代理已足以满足 Mix Space 的需求(包括 WebSocket),非高级用户建议使用图形化界面操作。
+
+### 宝塔面板
+
+进入 `网站`,在 `反向代理` 栏目下点击 `添加反代`。
+
+- `域名` 填入你将要使用的域名
+- `目标` 填写 `URL 地址` + `http://127.0.0.1:2333`
+
+### 1Panel
+
+进入 `网站 > 网站`,创建一个新网站,选择 `反向代理`。
+
+- `主域名` 填入你将要使用的域名,并勾选 `监听 IPV6`
+- 代理类型选择 `http`,地址填入 `127.0.0.1:2333`
+
+## Vane
+
+
+Vane 是一个较新的反向代理项目,请做好出现异常问题的准备。目前已测试过 mx-server + Shiro,如遇问题请携带日志反馈。
+
+
+[Vane](https://github.com/canmi21/vane) 是一个使用 Rust 编写的现代反向代理,内存占用约 1.5-3MB,Docker 镜像约 5MB。
+
+### 获取证书
+
+Vane 目前不包含 SSL 证书管理,可通过以下方式获取:
+- 使用 1Panel / 宝塔面板自带的 acme.sh 生成证书,导入到 Vane
+- 使用 [lazy-acme](https://github.com/canmi21/lazy-acme)(Vane 配套工具,支持 Cloudflare DNS 验证)
+
+### 部署配置
+
+推荐使用 [docker-compose.yml](https://github.com/canmi21/vane?tab=readme-ov-file#installation-and-usage) 部署。
+
+编写主配置文件 `~/vane/config.toml`:
+
+```toml
+[domains]
+"example.com" = "example.com.toml"
+"api.example.com" = "api.example.com.toml"
+```
+
+前端域名配置 `example.com.toml`:
+
+```toml
+https = true
+http3 = true
+hsts = true
+http_options = "reject"
+
+[tls]
+cert = "~/vane/cert/example.com.pem"
+key = "~/vane/cert/example.com.key"
+
+[methods]
+allow = "GET, POST, OPTIONS, HEAD"
+
+[rate_limit.default]
+period = "1s"
+requests = 20
+
+[[routes]]
+path = "/"
+websocket = true
+targets = ["http://127.0.0.1:2323"]
+```
+
+后端域名配置 `api.example.com.toml`:
+
+```toml
+https = true
+http_options = "reject"
+hsts = true
+http3 = false
+
+[tls]
+cert = "~/vane/cert/api.example.com.pem"
+key = "~/vane/cert/api.example.com.key"
+
+[methods]
+allow = "GET, POST, OPTIONS, HEAD"
+
+[rate_limit.default]
+period = "1s"
+requests = 20
+
+[[routes]]
+path = "/*"
+websocket = true
+targets = ["http://localhost:2333"]
+```
+
+注意根据实际部署情况修改端口和域名。
+
+## Cloudflare Tunnel
+
+
+除非你在非完整服务器环境(如 Sealos 或 Huggingface Space)部署,否则不推荐在容器内使用 Cloudflare Tunnel,而应在宿主机配置以避免管理不便。
+
+
+启动该功能需要两个环境变量:
+- `ENABLE_CLOUDFLARED` = `true`
+- `CF_ZERO_TRUST_TOKEN` = Tunnel 给的令牌(删掉 `cloudflared.exe service install`,只保留令牌部分)
+
+### 详细步骤
+
+1. 申请 Cloudflare Zero Trust
+2. 添加一条隧道,连接方式选择 Cloudflared,名称任意
+3. 添加一个 Public Hostname,回源选择 HTTP,端口选择 `2333`
+
+启动成功后,日志中应看到:
+
+```
+============================================
+Starting Cloudflared Tunnel
+============================================
+```
+
+## Nginx 手写配置
+
+
+手写配置文件需要较高的技术功底,请量力而行。
+
+
+### 双域名配置
+
+假定前端域名为 `www.example.com`,后端为 `server.example.com`。
+
+后端配置:
+
+```nginx
+server {
+ location /socket.io {
+ proxy_pass http://127.0.0.1:2333/socket.io;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_buffering off;
+ proxy_http_version 1.1;
+ add_header Cache-Control no-cache;
+ }
+
+ location / {
+ proxy_pass http://127.0.0.1:2333;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ add_header X-Cache $upstream_cache_status;
+ }
+}
+```
+
+前端配置:
+
+```nginx
+server {
+ location ~* \.(gif|png|jpg|css|js|woff|woff2)$ {
+ proxy_pass http://127.0.0.1:2323;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ expires 30d;
+ }
+
+ location / {
+ proxy_pass http://127.0.0.1:2323;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ add_header X-Cache $upstream_cache_status;
+ add_header Cache-Control no-cache;
+ proxy_intercept_errors on;
+ }
+}
+```
+
+
+使用双域名配置时:
+- API 地址为 `https://server.example.com/api/v2`
+- 前端地址为 `https://www.example.com`
+- Gateway 为 `https://server.example.com`
+- 后台为 `https://server.example.com/proxy/qaqdmin`
+
+
+### 单域名配置
+
+```nginx
+server {
+ listen 80;
+ listen 443 ssl http2;
+ server_name www.example.com;
+ index index.html;
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Host $server_name;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+
+ location /socket.io {
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:2333/socket.io;
+ }
+
+ location /api/v2 {
+ proxy_pass http://127.0.0.1:2333/api/v2;
+ }
+
+ location /render {
+ proxy_pass http://127.0.0.1:2333/render;
+ }
+
+ location / {
+ proxy_pass http://127.0.0.1:2323;
+ }
+
+ location /qaqdmin {
+ proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
+ }
+
+ location /proxy {
+ proxy_pass http://127.0.0.1:2333/proxy;
+ }
+
+ ssl_certificate /path/to/fullchain.pem;
+ ssl_certificate_key /path/to/privkey.pem;
+ ssl_protocols TLSv1.3 TLSv1.2;
+ error_page 497 https://$host$request_uri;
+}
+```
+
+
+使用单域名配置时:
+- API 地址为 `https://www.example.com/api/v2`
+- 前端地址为 `https://www.example.com`
+- Gateway 为 `https://www.example.com`
+- 后台为 `https://www.example.com/proxy/qaqdmin`
+
diff --git a/content/docs/deploy/source.mdx b/content/docs/deploy/source.mdx
new file mode 100644
index 00000000..48fe8d25
--- /dev/null
+++ b/content/docs/deploy/source.mdx
@@ -0,0 +1,104 @@
+---
+title: 源码部署
+description: 通过源码编译部署 Mix Space 后端
+icon: Pickaxe
+---
+
+import { Step, Steps } from 'fumadocs-ui/components/steps';
+
+
+如果你**不是开发者**,或者**不想折腾**,请不要选择源码部署。由于自身技术原因导致的问题,我们将**不会提供任何技术支持**。
+
+
+## 要求
+
+- [Node.js](https://nodejs.org/zh-cn/) 22+
+- [PostgreSQL](https://www.postgresql.org/download/) 16+
+- [Redis](https://redis.io/download)
+- [Git](https://git-scm.com/downloads)、[PNPM](https://pnpm.io/installation)、[PM2](https://pm2.keymetrics.io/docs/usage/quick-start/)
+
+
+
+
+### 克隆并安装
+
+```bash
+git clone https://github.com/mx-space/core.git --depth=1
+cd core
+pnpm i
+```
+
+
+
+### 构建 & Bundle
+
+```bash
+pnpm build
+pnpm bundle
+```
+
+
+
+### 配置 ecosystem.config.js
+
+在 `./apps/core` 目录下创建 `ecosystem.config.js`:
+
+```js
+const { cpus } = require('os')
+const { execSync } = require('child_process')
+const nodePath = execSync(`npm root --quiet -g`, { encoding: 'utf-8' }).split(
+ '\n',
+)[0]
+
+const cpuLen = cpus().length
+module.exports = {
+ apps: [
+ {
+ name: 'mx-server',
+ script: './out/index.js',
+ autorestart: true,
+ exec_mode: 'cluster',
+ watch: false,
+ instances: cpuLen,
+ max_memory_restart: '520M',
+ args: '',
+ env: {
+ NODE_ENV: 'production',
+ NODE_PATH: nodePath,
+ // 必填:允许跨域的域名,多个用逗号分隔
+ ALLOWED_ORIGINS: 'your-domain.com',
+ // 必填:JWT 密钥,16-32 个字符
+ JWT_SECRET: 'your-jwt-secret',
+ // 可选:加密密钥,开启加密时填写
+ MX_ENCRYPT_KEY: '',
+ },
+ },
+ ],
+}
+```
+
+
+
+
+### 启动
+
+```bash
+pm2 start ecosystem.config.js
+```
+
+查看运行状态:
+
+```bash
+pm2 logs mx-server
+```
+
+
+
+
+## 环境变量
+
+更多环境变量配置请参考 [环境变量说明](/docs/configure/environment)。
+
+## 下一步
+
+部署完成后,请配置 [反向代理](/docs/deploy/reverse-proxy) 和 [SSL 证书](/docs/deploy/ssl)。
diff --git a/content/docs/deploy/ssl.mdx b/content/docs/deploy/ssl.mdx
new file mode 100644
index 00000000..fbd9f986
--- /dev/null
+++ b/content/docs/deploy/ssl.mdx
@@ -0,0 +1,138 @@
+---
+title: HTTPS / SSL 证书
+description: 为 Mix Space 配置 HTTPS 证书
+icon: Lock
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 的后台管理、OAuth 登录等功能要求使用 HTTPS。现代浏览器也会标记 HTTP 站点为不安全,影响访问体验。本页介绍几种常见的 SSL 证书获取和配置方式。
+
+## 获取证书
+
+### 自动证书(Let's Encrypt + Certbot)
+
+Let's Encrypt 提供免费、自动化的 SSL 证书,有效期 90 天,支持自动续期。
+
+**使用服务器面板(推荐):**
+
+大部分服务器面板(1Panel、宝塔)都内置了自动证书申请功能,推荐在面板中一键申请并开启自动续期。
+
+**使用 Certbot 命令行:**
+
+```bash
+# 安装 Certbot
+apt install certbot python3-certbot-nginx # Debian/Ubuntu
+yum install certbot python3-certbot-nginx # CentOS
+
+# 申请证书(Nginx 插件自动配置)
+certbot --nginx -d example.com -d www.example.com
+
+# 测试自动续期
+certbot renew --dry-run
+```
+
+Certbot 会自动修改 Nginx 配置并设置定时任务续期。
+
+### Cloudflare Origin Certificates
+
+如果你使用 Cloudflare CDN,可以申请 Cloudflare Origin Certificates:
+
+- 有效期最长 15 年
+- 仅用于 Cloudflare 回源到服务器的加密
+- 访客看到的是 Cloudflare 的 Edge 证书
+
+操作步骤:
+
+1. 登录 Cloudflare 后台,进入 `SSL/TLS → 源服务器`
+2. 点击「创建证书」,选择 RSA,有效期 15 年
+3. 下载 PEM(证书)和 Key(私钥)文件
+4. 在 Nginx 中配置这两个文件
+
+
+使用 Cloudflare Origin Certificates 时,Cloudflare 的 SSL/TLS 加密模式应设为「完全(严格)」,以确保端到端加密。
+
+
+### 手动上传证书
+
+如果你已从其他 CA(如 DigiCert、Sectigo)购买或申请了证书,将证书文件和私钥上传到服务器,然后在 Nginx 中指定路径即可。
+
+## Nginx SSL 配置
+
+### 基础配置
+
+```nginx
+server {
+ listen 443 ssl http2;
+ server_name example.com;
+
+ ssl_certificate /etc/ssl/certs/fullchain.pem;
+ ssl_certificate_key /etc/ssl/private/privkey.pem;
+}
+```
+
+### 推荐的安全配置
+
+```nginx
+server {
+ listen 443 ssl http2;
+ server_name example.com;
+
+ # 证书路径
+ ssl_certificate /etc/ssl/certs/fullchain.pem;
+ ssl_certificate_key /etc/ssl/private/privkey.pem;
+
+ # 仅使用 TLS 1.2 和 1.3
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
+ ssl_prefer_server_ciphers on;
+
+ # 会话缓存
+ ssl_session_cache shared:SSL:10m;
+ ssl_session_timeout 10m;
+
+ # HSTS(可选,启用后浏览器强制 HTTPS)
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+
+ # HTTP 自动跳转
+ error_page 497 https://$host$request_uri;
+}
+
+# HTTP 跳转 HTTPS
+server {
+ listen 80;
+ server_name example.com;
+ return 301 https://$host$request_uri;
+}
+```
+
+### 安全响应头(可选)
+
+```nginx
+add_header X-Frame-Options "SAMEORIGIN" always;
+add_header X-Content-Type-Options "nosniff" always;
+add_header X-XSS-Protection "1; mode=block" always;
+add_header Referrer-Policy "strict-origin-when-cross-origin" always;
+```
+
+## 常见问题
+
+### 证书续期后未生效
+
+Certbot 续期证书后需要重载 Nginx:
+
+```bash
+nginx -s reload
+```
+
+Certbot 的 `deploy-hook` 可以自动执行此操作。
+
+### 浏览器提示证书不匹配
+
+- 确认证书覆盖了所有访问域名(包括 `www` 子域名)
+- 检查证书是否过期
+- 如果使用 Cloudflare,确认 SSL 模式不是「灵活」(灵活模式会导致重定向循环)
+
+### 混合内容警告
+
+确保前端页面中所有资源(图片、脚本、样式表)都使用 HTTPS 地址。检查 HTML 中是否有硬编码的 `http://` 链接。
diff --git a/content/docs/development/admin.mdx b/content/docs/develop/admin.mdx
similarity index 82%
rename from content/docs/development/admin.mdx
rename to content/docs/develop/admin.mdx
index 9916507b..c3fa7817 100644
--- a/content/docs/development/admin.mdx
+++ b/content/docs/develop/admin.mdx
@@ -37,9 +37,9 @@ VITE_APP_GATEWAY=https://server.test.cn
## 构建
-构建 mx-admin 需要的内存至少为 2 Gib,如果你服务器内存不足,你可以在本地构建成功后,将产物上传到服务器。
+ 构建 mx-admin 需要的内存至少为 2 GiB,如果你服务器内存不足,你可以在本地构建成功后,将产物上传到服务器。
-在 Windows 系统上,mx-admin 无法正常构建,你可以使用 WSL2 或者 Linux 系统。
+ 在 Windows 系统上,mx-admin 无法正常构建,你可以使用 WSL2 或者 Linux 系统。
```bash
@@ -68,7 +68,7 @@ pnpm build
```yaml
# THIS ENV FILE EXAMPLE ONLY FOR DOCKER COMPOSE
# SEE https://docs.docker.com/compose/environment-variables/#the-env-file
-JWT_SECRET=7294c34e0b28ad28 #此处填写一个长度不小于 16 个字符,不大于 32 个字符的字符串
+JWT_SECRET=7294c34e0b28ad28 # 此处填写一个长度不小于 16 个字符,不大于 32 个字符的字符串
ALLOWED_ORIGINS=test.cn,www.test.cn,admin.test.cn
```
diff --git a/content/docs/develop/backend.mdx b/content/docs/develop/backend.mdx
new file mode 100644
index 00000000..228c2d1e
--- /dev/null
+++ b/content/docs/develop/backend.mdx
@@ -0,0 +1,107 @@
+---
+title: 后端开发
+description: Mix Space 后端开发指南
+---
+
+## 项目结构
+
+`apps/core/src/` 是后端的核心源码目录,主要结构如下:
+
+```
+src/
+├── modules/ # 业务模块(Post、Note、User 等)
+├── processors/ # 全局处理器(Database、Gateway、Redis 等)
+├── common/ # 公共工具(装饰器、过滤器、拦截器、管道)
+├── database/ # 数据库 schema 与迁移文件
+├── constants/ # 常量定义
+├── types/ # 全局类型声明
+├── utils/ # 工具函数
+├── app.module.ts # 根模块
+└── main.ts # 应用入口
+```
+
+每个业务模块通常包含 `module.ts`、`controller.ts`、`service.ts` 三个标准文件,遵循 NestJS 的模块化设计。
+
+## 添加新模块
+
+标准的 NestJS 模块结构如下:
+
+```
+src/modules/example/
+├── example.module.ts
+├── example.controller.ts
+├── example.service.ts
+└── dto/
+ └── example.dto.ts
+```
+
+然后在 `app.module.ts` 中导入新模块即可。如果模块需要数据库支持,先在 `database/schema/` 中定义表结构,再通过 Drizzle ORM 进行操作。
+
+## 数据库
+
+Mix Space 使用 [Drizzle ORM](https://orm.drizzle.team/) 管理 PostgreSQL 数据库。
+
+- **Schema 位置**: `apps/core/src/database/schema/`
+- **迁移文件位置**: `apps/core/src/database/migrations/`
+- **配置文件**: `apps/core/drizzle.config.ts`
+
+### 常用命令
+
+```bash
+# 生成迁移
+pnpm drizzle-kit generate
+
+# 执行迁移
+pnpm drizzle-kit migrate
+```
+
+Schema 中统一使用 `snake_case` 命名字段,Drizzle 配置已开启 `casing: 'snake_case'` 以确保自动映射。
+
+## API 设计
+
+### RESTful 规范
+
+- 使用标准的 HTTP 方法:`GET`、`POST`、`PATCH`、`DELETE`
+- URL 使用名词复数,如 `/posts`、`/notes`
+- 嵌套资源通过路径表达,如 `/posts/:id/comments`
+
+### 响应格式
+
+接口返回统一使用 `snake_case`,结构如下:
+
+```json
+{
+ "data": {},
+ "pagination": {
+ "page": 1,
+ "per_page": 10,
+ "total": 100
+ }
+}
+```
+
+### 分页
+
+列表接口默认支持分页查询,通过 `page` 和 `per_page` 参数控制,最大 `per_page` 通常限制为 50。
+
+## 测试
+
+后端使用 [Vitest](https://vitest.dev/) 进行测试,测试文件位于 `apps/core/test/` 目录。
+
+```bash
+# 运行测试
+pnpm test
+
+# 监听模式
+pnpm test:watch
+```
+
+测试环境通过 `test/setup.ts` 完成初始化,包括内存数据库和其他依赖的启动。编写测试时请注意保持测试的独立性,避免测试之间产生状态污染。
+
+## 代码规范
+
+- **ESLint**: 统一代码风格,提交前运行 `pnpm lint`
+- **Prettier**: 自动格式化,建议开启编辑器保存时自动格式化
+- **Commit Message**: 请遵守 [Conventional Commits](https://www.conventionalcommits.org/) 规范,仓库内可使用 `pnpm commit` 引导生成
+
+更多关于文档贡献的规范,请参阅 [贡献文档](/docs/develop/contribute)。
diff --git a/content/docs/document/index.mdx b/content/docs/develop/contribute.mdx
similarity index 60%
rename from content/docs/document/index.mdx
rename to content/docs/develop/contribute.mdx
index d1f69210..793cda89 100644
--- a/content/docs/document/index.mdx
+++ b/content/docs/develop/contribute.mdx
@@ -1,33 +1,61 @@
---
-title: 文档撰写
+title: 贡献文档
description: Mix Space 的文档撰写规范
---
我们随时欢迎你对 Mix Space 的文档做出贡献,但撰写文档是一件不易之事,我们更加希望你能规范贡献内容,减少我们的工作量。
-部分内容来自于 https://github.com/mx-space/docs-archived/pull/163
+ 部分内容来自于 https://github.com/mx-space/docs-archived/pull/163
在撰写本文档之前,请确保你有基础的 Markdown 知识,并了解 Markdown 的语法,如果你不够了解,请使用 Typora 等 Markdown 编辑器进行撰写。
-我们在目前 Mix Space 的 V3 文档中,使用的文档框架是 FumaDocs,它的文档地址是:https://fumadocs.vercel.app/
+目前 Mix Space 的文档使用的框架是 [Fumadocs](https://fumadocs.vercel.app/),请在撰写之前详细阅读它的文档,并在本地运行开发服务器检查效果,确保符合预期后再提交 Pull Request。
-请在撰写之前详细阅读它,并且在你设备本地完成撰写之后,在本地运行开发服务器进行工作情况检查,确保它符合你的预期,减少你 Pull Request 之后我们的检查工作量。
+## 本地预览
-## 一些规范
+```bash
+# 安装依赖
+pnpm i
-撰写 Git Commit Message 时,请尽可能遵守 Git Commit Message 的规范,具体可在网络查询,如果你不了解,可以在本仓库使用 `pnpm commit` 命令在修改完成后引导生成它。
+# 启动开发服务器
+pnpm dev
+```
-中英文之间请使用空格隔开,这基本上是撰写中英文混合文本时大家所认同的基本规范。
+在浏览器中打开 `http://localhost:3000` 预览你的修改。
-## 一些问题
+## 添加新页面
+
+文档内容位于 `content/docs/` 目录下,添加新页面的步骤如下:
+
+1. 在对应章节文件夹下新建文件夹或 `.mdx` 文件
+2. 如果新建了文件夹,在文件夹内创建 `meta.json` 定义标题和页面顺序
+3. 编写 `.mdx` 文件内容
+4. 在 `meta.json` 的 `pages` 数组中添加新页面路径
+
+示例 `meta.json`:
+
+```json
+{
+ "title": "章节标题",
+ "pages": ["index", "new-page"]
+}
+```
+
+## 规范
+
+- 文档只写最容易理解的方式,不要教别人改源码
+- 中英文之间加空格
+- 撰写 Git Commit Message 时尽可能遵守 [Conventional Commits](https://www.conventionalcommits.org/) 规范,不了解可使用 `pnpm commit` 引导生成
+
+## 常见问题
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
-
+
为什么要写这么全面呢?甚至教别人改动源码。
这是极不正确的文档写法。
@@ -53,7 +81,7 @@ import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
如果你有魔改方面的内容,可以提交到对应区域的社区部署教程内。
-
+
这些面板程序随时都有可能会发生变化,我们无法保证文档的时效性。
@@ -66,4 +94,13 @@ import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
-我们希望文档的结构能够更加简洁易用,这样对开发者,对用户都有好处。
\ No newline at end of file
+## 提交 PR
+
+文档仓库地址:[github.com/mx-space/docs](https://github.com/mx-space/docs)
+
+1. Fork 仓库到你的账号
+2. 在功能分支上进行修改
+3. 本地预览确认无误后提交
+4. 向原仓库发起 Pull Request
+
+我们希望文档的结构能够更加简洁易用,这样对开发者,对用户都有好处。
diff --git a/content/docs/development/frontend.mdx b/content/docs/develop/frontend.mdx
similarity index 50%
rename from content/docs/development/frontend.mdx
rename to content/docs/develop/frontend.mdx
index bb3e512a..6ebd6329 100644
--- a/content/docs/development/frontend.mdx
+++ b/content/docs/develop/frontend.mdx
@@ -1,5 +1,5 @@
---
-title: 前端开发指南
+title: 前端开发
description: 开发 Mix Space 的前端
---
@@ -7,47 +7,49 @@ description: 开发 Mix Space 的前端
>
> 我希望不再是只有 Kami 一个风格,能有更多主题可供选择。
-此系统采用了前后端分离的形式,并没有提供模板渲染的选择,所以前端项目可以使用任何框架和架构设计。但是虽然开发比较自由,但是也存在诸多不便,比如接口调用和数据定义,路由约定上。所以在这一节,具体讲讲如何开发前端项目。
+Mix Space 采用前后端分离架构,后端不提供模板渲染,因此前端项目可以使用任何框架和架构设计。前端与后端完全解耦,你可以自由选择 React、Vue、Svelte 或其他技术栈来构建自己的主题。
+
+虽然开发比较自由,但在接口调用、数据定义和路由约定上仍需保持一致。本节将具体说明前端项目的开发规范。
## 路由约定
-[Kami](https://github.com/mx-space/kami) 是由 NextJS、React 开发的,作为最最原始的项目,至今(截止 2021.12)已有近两年的历史,经过这些时间的沉淀,我希望前端项目路由的组织上能够遵守这一个约定。
+[Kami](https://github.com/mx-space/kami) 是由 Next.js、React 开发的原始项目,经过长时间的沉淀,前端项目路由的组织上建议遵守以下约定:
-> 路由的约定能很大程度保证网站因更换不同前端主题导致 SEO 异常,死链接等问题。
+> 路由的约定能很大程度保证网站因更换不同前端主题导致 SEO 异常、死链接等问题。
约定如下:
-| Path | Descrition | Mark |
-| ------------------------ | ------------------------------- | -------- |
-| `/` | 主页 | 强制要求 |
-| `/posts` | 博文列表 | 强制要求 |
-| `/posts/:category/:slug` | 博文详情页 | 强制要求 |
-| `/pages/:slug` | 独立页面详情页 | 强制要求 |
-| `/notes/:nid` | 日记详情页 | 强制要求 |
-| `/feed` | RSS 订阅 | 强制要求 |
-| `/:category/:slug` | 302 -> `/posts/:category/:slug` | 建议 |
-| `/category/:slug` | 分类中文章列表页 | 建议 |
-| `/notes` | 日记列表或者跳转最新日记页 | 建议 |
-| `/notes/latest` | 最新日记详情页 | 建议 |
-| `/friends` | 友链 | 建议 |
-| `/says` | 一言详情页 | 可选 |
-| `/sitemap` | 站点地图 | 建议 |
-| `/timeline` | 时间线 | 可选 |
-| `/recently` | 动态页 | 可选 |
-| `/favorite/:type` | 附加页 | 可选 |
-| `/projects` | 项目页 | 可选 |
-| `/projects/:id` | 项目详情页 | 可选 |
-
-## 框架上的选择与建议
+| Path | Description | Mark |
+| ------------------------ | -------------------------------- | -------- |
+| `/` | 主页 | 强制要求 |
+| `/posts` | 博文列表 | 强制要求 |
+| `/posts/:category/:slug` | 博文详情页 | 强制要求 |
+| `/pages/:slug` | 独立页面详情页 | 强制要求 |
+| `/notes/:nid` | 日记详情页 | 强制要求 |
+| `/feed` | RSS 订阅 | 强制要求 |
+| `/:category/:slug` | 302 -> `/posts/:category/:slug` | 建议 |
+| `/category/:slug` | 分类中文章列表页 | 建议 |
+| `/notes` | 日记列表或者跳转最新日记页 | 建议 |
+| `/notes/latest` | 最新日记详情页 | 建议 |
+| `/friends` | 友链 | 建议 |
+| `/says` | 一言详情页 | 可选 |
+| `/sitemap` | 站点地图 | 建议 |
+| `/timeline` | 时间线 | 可选 |
+| `/recently` | 动态页 | 可选 |
+| `/favorite/:type` | 附加页 | 可选 |
+| `/projects` | 项目页 | 可选 |
+| `/projects/:id` | 项目详情页 | 可选 |
+
+## 框架选择建议
建议选择附带 SSR 功能的现代化框架:
-- React:NextJS, [RakkasJS](https://github.com/rakkasjs/rakkasjs), umi
-- Vue: Vite (vite-ssr), NuxtJS
+- React:Next.js、[RakkasJS](https://github.com/rakkasjs/rakkasjs)、umi
+- Vue: Vite (vite-ssr)、NuxtJS
小程序:
-- React: Remax, taro
+- React: Remax、taro
- Vue: uni-app
## 接口调用与 SDK 的使用
@@ -56,4 +58,4 @@ description: 开发 Mix Space 的前端
> SDK 仍在 beta 阶段,未来接口可能出现变化。
-详见:[api-client](https://github.com/mx-space/core/tree/master/packages/api-client)
\ No newline at end of file
+详见:[api-client](https://github.com/mx-space/core/tree/master/packages/api-client)
diff --git a/content/docs/develop/index.mdx b/content/docs/develop/index.mdx
new file mode 100644
index 00000000..5c2dd5fe
--- /dev/null
+++ b/content/docs/develop/index.mdx
@@ -0,0 +1,60 @@
+---
+title: 开发指南
+description: 开发 Mix Space 的指南
+---
+
+Mix Space 是完全开源的,欢迎每一位开发者参与贡献。无论你是想修复 Bug、添加新功能,还是基于我们的 API 开发自己的前端主题,这里都能帮助你快速上手。
+
+## 技术栈
+
+| 层级 | 技术 |
+|------|------|
+| 后端框架 | [NestJS](https://nestjs.com/) 11 + Fastify |
+| 语言 | [TypeScript](https://www.typescriptlang.org/) |
+| 数据库 | [PostgreSQL](https://www.postgresql.org/) 16 + [Drizzle ORM](https://orm.drizzle.team/) |
+| 缓存 | [Redis](https://redis.io/) 7 |
+| 前端框架 | [React](https://react.dev/) / [Vue 3](https://vuejs.org/) |
+| 容器化 | [Docker](https://www.docker.com/) |
+
+## 环境要求
+
+在开始之前,请确保你的开发环境已安装以下工具:
+
+- [ ] [Node.js](https://nodejs.org/) >= 22(推荐使用 `.nvmrc` 中的版本)
+- [ ] [pnpm](https://pnpm.io/)(通过 Corepack 启用:`corepack enable`)
+- [ ] [PostgreSQL](https://www.postgresql.org/) >= 16
+- [ ] [Redis](https://redis.io/) >= 7
+- [ ] [Git](https://git-scm.com/)
+
+## 快速开始(后端)
+
+```bash
+# 克隆仓库
+git clone https://github.com/mx-space/core
+cd core
+
+# 安装依赖
+pnpm i
+
+# 启动 PostgreSQL 和 Redis
+docker compose up -d postgres redis
+
+# 启动开发服务器(端口 2333)
+pnpm dev
+```
+
+
+ 提交 PR 时请确保使用 pnpm 安装依赖,项目根目录只保留 `pnpm-lock.yaml`。
+
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Card, Cards } from 'fumadocs-ui/components/card'
+
+## 了解更多
+
+
+
+
+
+
+
diff --git a/content/docs/develop/meta.json b/content/docs/develop/meta.json
new file mode 100644
index 00000000..5e18c45f
--- /dev/null
+++ b/content/docs/develop/meta.json
@@ -0,0 +1,13 @@
+{
+ "title": "开发",
+ "description": "开发 Mix Space 及其生态",
+ "icon": "Code2",
+ "root": true,
+ "pages": [
+ "index",
+ "backend",
+ "frontend",
+ "admin",
+ "contribute"
+ ]
+}
diff --git a/content/docs/development/index.mdx b/content/docs/development/index.mdx
deleted file mode 100644
index 658b1bb7..00000000
--- a/content/docs/development/index.mdx
+++ /dev/null
@@ -1,60 +0,0 @@
----
-title: 开发指南
-description: 开发 Mix Space 的指南
----
-
-为了方便开发者快速上手,我们提供了一些开发指南,帮助开发者快速了解和使用我们的产品。
-
-## 项目技术栈
-
-- [React](https://reactjs.org/)
-- [NestJS](https://nestjs.com/)
-- [TypeScript](https://www.typescriptlang.org/)
-- [MongoDB](https://www.mongodb.com/)
-- [Redis](https://redis.io/)
-- [Docker](https://www.docker.com/)
-
-你可以点击上面的链接了解更多有关这些技术的信息。
-
-## 启动开发环境
-
-此系统采用了前后端分离的形式,因此需要分别启动前端和后端的开发环境。
-
-但是由于不同的前端不同写法,我们认为作为一名开发者都应该知道如何 **`「举一反三」`**,并且不同的前端可能步骤会 **大相径庭** ,因此我们不会提供如何启动前端开发环境的指南。
-
-
-有关前端开发设计指南,你可以在侧边栏中找到。
-
-
-你需要确定好你的开发环境中已经安装了以下工具:
-
-- [Node.js](https://nodejs.org/en/) (>= 20)
-- [PNPM](https://pnpm.js.org/)
-- [MongoDB](https://www.mongodb.com/)
-- [Redis](https://redis.io/)
-- [Git](https://git-scm.com/)
-
-### 启动后端
-
-首先,你需要克隆本仓库到你的本地(你可能需要 fork 一份到你的仓库中,并且使用 `--depth=1` 来加速克隆):
-
-```bash
-git clone https://github.com/mx-space/core
-```
-
-然后,你需要安装依赖,我们使用了 PNPM 作为包管理器,并不建议你使用其他的管理器安装。
-
-
-在您提交相关 PR 时,我们也会检查您是否使用了 PNPM,如果没有,我们将会拒绝您的 PR(一个项目多个 lock 总不是一个好的选择)。
-
-
-```bash
-cd core
-pnpm i
-```
-
-接下来,我们就可以开始启动后端的开发环境了。
-
-```bash
-pnpm run dev
-```
\ No newline at end of file
diff --git a/content/docs/development/meta.json b/content/docs/development/meta.json
deleted file mode 100644
index c2970159..00000000
--- a/content/docs/development/meta.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "index": "开发指南",
- "description": "探索 MixSpace 的开发部署",
- "icon": "Cpu",
- "root": true,
- "pages": [
- "---文档---",
- "admin",
- "frontend"
- ]
-}
diff --git a/content/docs/document/meta.json b/content/docs/document/meta.json
deleted file mode 100644
index a6b0af0b..00000000
--- a/content/docs/document/meta.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "index": "文档撰写",
- "description": "了解 Mix Space 的文档撰写规范",
- "icon": "Pencil",
- "root": true,
- "pages": [
- "---文档---",
- "index"
- ]
- }
-
\ No newline at end of file
diff --git a/content/docs/getting-started/index.mdx b/content/docs/getting-started/index.mdx
new file mode 100644
index 00000000..8a021f29
--- /dev/null
+++ b/content/docs/getting-started/index.mdx
@@ -0,0 +1,57 @@
+---
+title: Mix Space 是什么
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Card, Cards } from 'fumadocs-ui/components/card'
+import { Files, File, Folder } from 'fumadocs-ui/components/files'
+
+Mix Space 是一个简洁、现代、高性能的个人博客系统,采用前后端分离架构。
+
+## 系统组成
+
+Mix Space 由两大部分组成:
+
+
+
+
+
+
+
+
+
+
+
+
+
+- **后端 (Core)**:提供数据存储、业务逻辑、RESTful API 以及后台管理界面。你可以通过后台管理文章、页面、笔记、评论等所有内容。
+- **前端 (Theme)**:面向访客的展示站点,通过调用后端 API 获取数据并渲染页面。
+
+这种分离设计让你可以自由搭配前端主题,而后端数据始终保持一致。
+
+## 官方主题
+
+目前官方维护的前端主题有:
+
+- **Shiro** —— 最受欢迎的现代化主题,设计精致,功能丰富
+- **Yohaku** —— 简约留白风格,注重阅读体验
+- **Kami** —— 经典风格,稳定可靠
+- **Yun** —— 早期主题,轻量简洁
+
+
+ 这不是 WordPress 式的「一键安装」。你需要分别部署后端和前端,但这也带来了更大的灵活性。
+
+
+## 继续阅读
+
+
+
+ 了解你需要准备的服务器、域名和基础知识
+
+
+ 在本地快速启动 Mix Space,无需配置域名
+
+
+ 完整的生产环境部署文档
+
+
diff --git a/content/docs/getting-started/meta.json b/content/docs/getting-started/meta.json
new file mode 100644
index 00000000..3cef22b3
--- /dev/null
+++ b/content/docs/getting-started/meta.json
@@ -0,0 +1,11 @@
+{
+ "title": "新手入门",
+ "description": "第一次使用 Mix Space,从这里开始",
+ "icon": "Rocket",
+ "root": true,
+ "pages": [
+ "index",
+ "what-you-need",
+ "quick-start"
+ ]
+}
diff --git a/content/docs/getting-started/quick-start.mdx b/content/docs/getting-started/quick-start.mdx
new file mode 100644
index 00000000..debcbf16
--- /dev/null
+++ b/content/docs/getting-started/quick-start.mdx
@@ -0,0 +1,85 @@
+---
+title: 5 分钟快速体验
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+本指南的目标是在 **5 分钟** 内让你在本地运行起一个完整的 Mix Space,**无需配置域名,无需填写环境变量**(全部使用默认值)。
+
+
+
+ 确保你的机器已安装 Docker 和 Docker Compose。如果没有,可以执行以下命令一键安装:
+
+ ```bash
+ curl -fsSL https://get.docker.com | bash
+ ```
+
+ 安装完成后,运行 `docker --version` 和 `docker compose version` 确认安装成功。
+
+
+
+ 执行以下命令克隆后端仓库并启动服务:
+
+ ```bash
+ git clone https://github.com/mx-space/core.git --depth=1
+ cd core
+ docker compose up -d
+ ```
+
+ 首次启动会拉取镜像并初始化 PostgreSQL 和 Redis,可能需要几分钟时间。
+
+
+
+ 等待约 30 秒,让数据库和服务完成初始化。可以用以下命令检查状态:
+
+ ```bash
+ docker compose ps
+ ```
+
+ 所有服务状态为 `healthy` 后,打开浏览器访问:
+
+ ```
+ http://localhost:2333/proxy/qaqdmin
+ ```
+
+
+
+ 第一次访问后台时,系统会引导你完成初始化设置:
+
+ - 设置管理员账号和密码
+ - 填写站点基本信息
+
+ 初始化完成后,即可使用刚才设置的账号登录后台管理系统。
+
+
+
+ 确认以下事项均正常:
+
+ - [ ] 后端 API 响应正常(访问 `http://localhost:2333/api/v2` 能返回 JSON)
+ - [ ] 后台管理页面能正常加载和登录
+ - [ ] 可以在后台发布一篇文章并保存成功
+
+
+
+
+ 这只是本地体验。要对外公开访问,你需要继续阅读[部署指南](/docs/deploy),配置域名和反向代理。
+
+
+## 服务架构
+
+本地启动后,以下服务在后台运行:
+
+| 服务 | 端口 | 说明 |
+|------|------|------|
+| **Mix Space 后端** | 2333 | NestJS API 服务 + 后台管理界面 |
+| **PostgreSQL** | 5432 | 数据库(仅容器内可访问) |
+| **Redis** | 6379 | 缓存(仅容器内可访问) |
+
+## 下一步
+
+本地体验完成后,你可以:
+
+1. [部署到服务器](/docs/deploy) — 配置域名和 HTTPS
+2. [部署前端主题](/docs/themes) — 为你的站点选择一个漂亮的前端
+3. [配置 AI 功能](/docs/use/ai-features) — 开启 AI 摘要、翻译等功能
diff --git a/content/docs/getting-started/what-you-need.mdx b/content/docs/getting-started/what-you-need.mdx
new file mode 100644
index 00000000..c6f6a75a
--- /dev/null
+++ b/content/docs/getting-started/what-you-need.mdx
@@ -0,0 +1,55 @@
+---
+title: 准备工作
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+## 你需要什么
+
+在正式开始之前,请确认你已准备好以下事项:
+
+- [ ] 一台服务器(Linux / macOS,内存 >= 1GB,推荐 2GB)
+- [ ] 一个域名(推荐,但本地体验可以不要)
+- [ ] 基础的命令行知识(会复制粘贴命令即可)
+- [ ] 预计费用:服务器 ~ 几十元/月,域名 ~ 几十元/年
+
+## 基础知识自查
+
+如果你知道以下概念是什么,那么你已经具备了部署 Mix Space 的基础:
+
+- **Docker** —— 容器化运行环境,帮你自动处理依赖
+- **Docker Compose** —— 多容器编排工具,一键启动所有服务
+- **反向代理** —— 如 Nginx、Caddy,用于将域名指向服务并配置 HTTPS
+
+如果以上术语对你来说比较陌生,不用担心,选择 **Docker 部署** 是最简单的方式,只需要复制粘贴命令即可完成。
+
+## 系统架构
+
+Mix Space 由以下几个部分组成:
+
+| 组件 | 说明 | 必需 |
+|------|------|------|
+| **Core(后端)** | NestJS API 服务,提供所有后端功能 | ✅ |
+| **PostgreSQL** | 关系型数据库,存储所有业务数据 | ✅ |
+| **Redis** | 缓存,用于会话、队列、实时数据 | ✅ |
+| **前端主题** | 用户访问的网站界面(Shiro、Yohaku 等) | ✅ |
+| **Admin** | 后台管理系统(内嵌在 Core 中) | ✅ |
+
+
+PostgreSQL 和 Redis 可以使用 Docker 内置的服务,也可以连接外部已有的实例。
+
+
+## 两种部署路径
+
+| 方式 | 难度 | 适合谁 | 预计时间 |
+| :--- | :--- | :--- | :--- |
+| Docker | 简单 | 大多数用户 | 15 分钟 |
+| 源码编译 | 较难 | 开发者 / 想折腾的用户 | 1 小时 |
+
+Docker 方式会帮你自动处理 PostgreSQL、Redis 和运行环境;源码编译则需要你手动安装 Node.js、数据库等依赖,并进行编译构建。
+
+
+ 如果你不确定选哪个,选 Docker。
+
+
+准备好了?继续阅读 [5 分钟快速体验](/docs/getting-started/quick-start),在本地先跑起来看看。
diff --git a/content/docs/meta.json b/content/docs/meta.json
index 92cf5862..76f0dd32 100644
--- a/content/docs/meta.json
+++ b/content/docs/meta.json
@@ -1,3 +1,15 @@
{
- "pages": ["core", "themes", "usage", "development", "document"]
-}
\ No newline at end of file
+ "title": "文档",
+ "description": "Mix Space 官方文档",
+ "root": true,
+ "pages": [
+ "getting-started",
+ "deploy",
+ "configure",
+ "themes",
+ "use",
+ "migrate",
+ "develop",
+ "reference"
+ ]
+}
diff --git a/content/docs/migrate/from-wordpress.mdx b/content/docs/migrate/from-wordpress.mdx
new file mode 100644
index 00000000..ad0ac7d7
--- /dev/null
+++ b/content/docs/migrate/from-wordpress.mdx
@@ -0,0 +1,167 @@
+---
+title: 从 WordPress 迁移
+description: 将 WordPress 站点内容迁移到 Mix Space 的完整指南
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 原生支持 Markdown 文件导入,这让从 WordPress 迁移变得相对简单。本指南将帮助你完成从导出到导入的完整流程。
+
+## 迁移前准备
+
+在开始之前,建议你:
+
+- [ ] 备份 WordPress 站点的所有数据和文件
+- [ ] 准备好 Mix Space 的运行环境(参考 [快速开始](/docs/getting-started/quick-start))
+- [ ] 确认 Mix Space 后台可以正常访问
+
+
+Mix Space 目前没有直接导入 WordPress WXR 格式的功能,需要先将内容转换为 Markdown 格式。
+
+
+## 迁移步骤
+
+
+
+### 导出 WordPress 内容
+
+在 WordPress 后台,进入「工具 → 导出」,选择「所有内容」,下载得到一个 XML 文件(WXR 格式)。
+
+如果你使用的是 WordPress.com,可以在「工具 → 导出」中导出站点内容。
+
+
+
+### 转换为 Markdown
+
+使用社区工具将 WordPress XML 转换为带有 Frontmatter 的 Markdown 文件。推荐工具:
+
+| 工具 | 说明 |
+|------|------|
+| [wordpress-export-to-markdown](https://github.com/lonekorean/wordpress-export-to-markdown) | 自动生成 Frontmatter,支持分类和标签 |
+| [wp2md](https://github.com/axdiamond/wp2md) | 轻量级转换工具 |
+
+以 `wordpress-export-to-markdown` 为例:
+
+```bash
+npx wordpress-export-to-markdown \
+ --input=wordpress.xml \
+ --output=markdown \
+ --frontmatter=true \
+ --save-attached-images=true
+```
+
+转换后会得到一组 `.md` 文件,每个文件的 Frontmatter 中包含标题、日期、分类、标签等信息。
+
+
+
+### 在 Mix Space 创建分类
+
+登录 Mix Space 后台,进入「分类」页面,提前创建好你在 WordPress 中使用的分类。确保分类名称一致,导入时系统才能正确匹配。
+
+
+如果导入时找不到对应分类,系统会自动创建新分类。
+
+
+
+
+### 导入 Markdown 文件
+
+登录 Mix Space 后台,进入「文章」页面,点击「导入」按钮,批量选择上一步生成的 Markdown 文件。
+
+系统会自动解析 Frontmatter 中的以下字段:
+
+| Frontmatter 字段 | 映射到 |
+|-------------------|--------|
+| `title` | 文章标题 |
+| `date` | 创建时间 |
+| `categories` | 分类 |
+| `tags` | 标签 |
+| `slug` | URL 路径 |
+| `status` | 发布状态(`publish` → 已发布) |
+
+
+
+### 处理图片
+
+WordPress 文章中的图片通常存放在 `wp-content/uploads/` 目录。迁移图片有三种方案:
+
+**方案一:迁移到 Mix Space 本地存储**
+
+将 WordPress 的 `uploads` 目录中的图片上传到 Mix Space 后台的「文件」管理中,然后批量替换文章中的图片链接。
+
+**方案二:使用对象存储**
+
+在 Mix Space 中配置 S3 图床(详见 [图床与存储](/docs/configure/image-storage)),将图片上传到对象存储,然后批量替换链接。
+
+**方案三:保留原链接**
+
+如果原 WordPress 站点的图片链接仍然可用,可以暂时保留不做处理。但建议最终迁移到 Mix Space 的存储中,避免原站点关闭后图片丢失。
+
+推荐使用批量查找替换的方式更新文章中的图片 URL:
+
+```sql
+-- 在数据库中批量替换图片链接(请先备份!)
+UPDATE posts SET text = REPLACE(text, 'old-domain.com/wp-content/uploads', 'new-domain.com/api/v2/static/image');
+```
+
+
+
+### 验证迁移结果
+
+迁移完成后,逐一检查以下内容:
+
+- [ ] 文章数量是否与原站点一致
+- [ ] 文章内容和格式是否正确(特别是代码块、表格等)
+- [ ] 分类和标签是否正确匹配
+- [ ] 图片是否正常显示
+- [ ] 文章 slug 是否与旧站一致(影响 SEO)
+
+
+
+## 评论迁移
+
+
+Mix Space 目前没有直接导入 WordPress 评论的功能。评论数据需要手动迁移或借助脚本辅助。
+
+
+如果你的站点评论较多,可以考虑:
+
+1. 通过脚本读取 WordPress 导出的 XML 中的评论数据
+2. 调用 Mix Space API 批量创建评论
+3. 或者接受从零开始,不迁移历史评论
+
+## SEO 过渡建议
+
+迁移完成后,建议进行以下 SEO 相关操作:
+
+| 操作 | 说明 |
+|------|------|
+| **301 重定向** | 将旧 WordPress 链接重定向到新的 Mix Space 链接 |
+| **更新 Sitemap** | Mix Space 会自动生成新的 Sitemap |
+| **提交搜索引擎** | 在百度/Bing 站长工具中重新提交站点地图 |
+| **保留 robots.txt** | 确保新的 robots.txt 配置正确 |
+
+### URL 映射规则
+
+WordPress 和 Mix Space 的 URL 结构不同,需要做重定向映射:
+
+| WordPress URL | Mix Space URL |
+|---------------|---------------|
+| `/?p=123` | `/{分类 slug}/{文章 slug}` |
+| `/2024/01/hello-world/` | `/{分类 slug}/{文章 slug}` |
+
+建议在 Nginx 中配置 rewrite 规则:
+
+```nginx
+# 示例:将 WordPress 固定链接重定向到 Mix Space
+location / {
+ # 如果旧文章有固定链接格式,可以逐条重定向
+ # rewrite ^/2024/01/hello-world/$ /coding/hello-world permanent;
+}
+```
+
+## 参考资源
+
+- [社区博文:从 WordPress 迁移数据到 Mix Space](https://blog.fosky.top/2024/10/09/wordpress-to-mix-space.html)
+- [GitHub: wordpress-export-to-markdown](https://github.com/lonekorean/wordpress-export-to-markdown)
diff --git a/content/docs/migrate/index.mdx b/content/docs/migrate/index.mdx
new file mode 100644
index 00000000..cea51e19
--- /dev/null
+++ b/content/docs/migrate/index.mdx
@@ -0,0 +1,29 @@
+---
+title: 迁移概览
+description: 从旧版本或其他平台迁移到 Mix Space 的指南
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Card, Cards } from 'fumadocs-ui/components/card'
+import { ArrowUp, Globe } from 'lucide-react'
+
+
+ }
+ href={'/docs/migrate/v11-to-v12'}
+ title="v11 → v12 升级"
+ >
+ 数据库从 MongoDB 迁移到 PostgreSQL 的完整指南
+
+ }
+ href={'/docs/migrate/from-wordpress'}
+ title="从 WordPress 迁移"
+ >
+ 将 WordPress 内容导出并导入到 Mix Space
+
+
+
+
+迁移前务必备份。数据无价。
+
diff --git a/content/docs/migrate/meta.json b/content/docs/migrate/meta.json
new file mode 100644
index 00000000..dd612b27
--- /dev/null
+++ b/content/docs/migrate/meta.json
@@ -0,0 +1,11 @@
+{
+ "title": "迁移",
+ "description": "从旧版本或其他平台迁移到 Mix Space",
+ "icon": "ArrowLeftRight",
+ "root": true,
+ "pages": [
+ "index",
+ "v11-to-v12",
+ "from-wordpress"
+ ]
+}
diff --git a/content/docs/migrate/v11-to-v12.mdx b/content/docs/migrate/v11-to-v12.mdx
new file mode 100644
index 00000000..8434dd68
--- /dev/null
+++ b/content/docs/migrate/v11-to-v12.mdx
@@ -0,0 +1,366 @@
+---
+title: v11 升级到 v12
+description: 从 v11 升级到 v12 的完整指南,包含 MongoDB 到 PostgreSQL 的迁移步骤
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Card, Cards } from 'fumadocs-ui/components/card'
+import { AlertTriangle, CheckCircle, Container, Pickaxe, RotateCcw } from 'lucide-react'
+
+
+v12 是一次**重大版本升级**,底层数据库从 MongoDB 更换为 PostgreSQL。虽然你的文章、评论、配置等数据都会保留,但升级过程中需要执行一次数据迁移,且需要短暂的停站维护。
+
+**如果你当前版本低于 v11,请先升级到 v11,再执行本指南。**
+
+
+## 升级前必读(3 分钟)
+
+### 这次升级会变什么?
+
+- **数据库**:MongoDB → PostgreSQL(性能更好,数据关系更安全)
+- **备份方式**:以后用 `pg_dump` 代替 `mongodump`
+- **环境变量**:旧的 `DB_HOST`、`MONGO_CONNECTION` 等变量失效
+
+### 什么不会变?
+
+- 前端页面、API 接口和之前完全一致
+- 你的文章、评论、图片、配置全部保留
+- 登录方式、密码、API Key 不受影响
+
+### 我需要停站多久?
+
+| 数据规模 | 预估时间 |
+|---------|---------|
+| 文章 < 100 篇,评论 < 1000 条 | 5–10 分钟 |
+| 文章 < 1000 篇,评论 < 1 万条 | 10–30 分钟 |
+| 大型站点 | 30–60 分钟 |
+
+---
+
+## 升级 Checklist
+
+开始前,请确认:
+
+- [ ] 当前版本是 **v11.x**
+- [ ] 服务器剩余磁盘空间 **> 当前数据量的 2 倍**
+- [ ] 已准备好至少 30 分钟的维护窗口(期间不要发文章/评论)
+
+---
+
+## 第一步:备份(必须)
+
+无论你用 Docker 还是源码部署,先执行备份:
+
+```bash
+# 进入你放 docker-compose.yml 的文件夹,或者 core 源码文件夹
+cd ~/mx-space/core
+
+# 备份 MongoDB 数据
+docker exec -i $(docker ps -q -f name=mongo) mongodump --archive > backup-mongo-$(date +%Y%m%d).archive
+
+# 同时打包整个数据目录(包含配置文件、图片等)
+tar czvf mx-space-full-backup-$(date +%Y%m%d).tar.gz ./data
+```
+
+**验证备份**:
+- `backup-mongo-YYYYMMDD.archive` 文件大小不为 0
+- `mx-space-full-backup-YYYYMMDD.tar.gz` 包含 `data/mx-space` 目录
+
+---
+
+## 第二步:选择你的升级路径
+
+
+ }>
+ 适合大多数用户,使用 docker compose 部署的
+
+ }>
+ 适合进阶用户,手动编译部署的
+
+
+
+---
+
+## Docker 部署升级
+
+### 1. 停止当前服务
+
+```bash
+cd ~/mx-space/core
+docker compose down
+```
+
+### 2. 更新配置文件
+
+```bash
+# 备份旧配置(以防万一)
+cp docker-compose.yml docker-compose.yml.v11.backup
+
+# 拉取 v12 的 docker-compose.yml(已内置 PostgreSQL)
+wget -O docker-compose.yml https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
+```
+
+### 3. 启动新数据库
+
+```bash
+# 只启动 PostgreSQL 和 Redis,先不启动主服务
+docker compose up -d postgres redis
+```
+
+等待 10 秒后检查状态:
+
+```bash
+docker compose ps
+```
+
+预期看到 `postgres` 和 `redis` 状态都是 `healthy` 或 `Up`。
+
+### 4. 执行数据迁移
+
+
+这是最关键的一步。执行前请确保没有用户在发文章或评论。
+
+
+```bash
+docker compose run --rm app npx tsx scripts/migrate-mongo-to-postgres.ts --mode apply
+```
+
+**预期输出**:
+- 看到 `Rows allocated: XXXX`,数字和你的文章/评论数量接近
+- 看到 `Missing refs: 0`(如果有少量数字,通常不影响)
+- 最后出现 `Migration completed successfully`
+
+**如果报错怎么办?**
+
+| 错误提示 | 原因 | 解决 |
+|---------|------|------|
+| `Connection refused` | PostgreSQL 还没启动好 | 等 30 秒重试 |
+| `Missing refs > 0` | 有孤儿数据 | 通常可忽略,截图记录后继续 |
+| 其他错误 | 未知问题 | **不要继续**,保留日志,回滚到 v11(见下方回滚章节) |
+
+### 5. 启动 v12
+
+```bash
+docker compose up -d
+```
+
+### 6. 验证(逐项检查)
+
+- [ ] 打开首页,文章列表正常显示
+- [ ] 打开一篇文章,内容和评论都在
+- [ ] 登录后台(`你的域名/proxy/qaqdmin`),能正常登录
+- [ ] 后台「其他 → 备份」页面能正常打开
+- [ ] 发一篇测试文章,能正常发布和显示
+- [ ] 删除测试文章,正常删除
+
+**全部通过 = 升级成功。**
+
+---
+
+## 源码 / PM2 部署升级
+
+### 1. 停止服务
+
+```bash
+cd ~/mx-space/core/apps/core
+pm2 stop ecosystem.config.js
+```
+
+### 2. 拉取 v12 代码
+
+```bash
+cd ~/mx-space/core
+git fetch origin
+git checkout v12.x.x # 替换为实际 tag,或 master 上的最新 v12
+pnpm i
+```
+
+### 3. 安装 PostgreSQL
+
+如果你服务器上还没有 PostgreSQL 16+:
+
+```bash
+# Ubuntu / Debian
+sudo apt update
+sudo apt install postgresql-16
+
+# macOS
+brew install postgresql@16
+brew services start postgresql@16
+```
+
+创建数据库:
+
+```bash
+sudo -u postgres psql -c "CREATE USER mx WITH PASSWORD 'mx';"
+sudo -u postgres psql -c "CREATE DATABASE mx_core OWNER mx;"
+```
+
+### 4. 修改环境变量
+
+编辑你的环境配置文件(`.env` 或直接在 `ecosystem.config.js` 里),**删除**旧变量:
+
+```diff
+- DB_HOST=xxx
+- MONGO_CONNECTION=xxx
+```
+
+**添加**新变量:
+
+```bash
+# 方式一:连接字符串(推荐)
+PG_URL=postgresql://mx:mx@localhost:5432/mx_core
+
+# 方式二:分开配置
+PG_HOST=localhost
+PG_PORT=5432
+PG_USER=mx
+PG_PASSWORD=mx
+PG_DATABASE=mx_core
+
+# 必须添加:单实例填 1 即可
+SNOWFLAKE_WORKER_ID=1
+```
+
+### 5. 执行迁移
+
+先试运行(不写入,只检查):
+
+```bash
+cd apps/core
+SNOWFLAKE_WORKER_ID=1 \
+MONGO_URI="mongodb://localhost:27017/mx-space" \
+PG_URL="postgresql://mx:mx@localhost:5432/mx_core" \
+npx tsx scripts/migrate-mongo-to-postgres.ts --mode dry-run
+```
+
+确认无致命错误后,正式迁移:
+
+```bash
+SNOWFLAKE_WORKER_ID=1 \
+MONGO_URI="mongodb://localhost:27017/mx-space" \
+PG_URL="postgresql://mx:mx@localhost:5432/mx_core" \
+npx tsx scripts/migrate-mongo-to-postgres.ts --mode apply
+```
+
+### 6. 构建并启动
+
+```bash
+pnpm build
+pnpm bundle
+cd apps/core
+pm2 start ecosystem.config.js
+```
+
+### 7. 验证
+
+与 Docker 验证清单相同(见上方第 6 步)。
+
+---
+
+## 第三步:清理旧数据库(可选)
+
+
+建议 v12 稳定运行 **48 小时** 后再执行清理。保留旧数据是回滚的最后保障。
+
+
+### Docker 用户
+
+```bash
+cd ~/mx-space/core
+
+# 删除旧 MongoDB 容器
+docker compose rm -f mongo
+
+# 删除 MongoDB 数据卷(名字可能不同,先查看再删)
+docker volume ls
+docker volume rm mx-space_mongo_data # 请替换为实际卷名
+```
+
+### 源码用户
+
+```bash
+# 停止 MongoDB 服务
+sudo systemctl stop mongod
+
+# 是否卸载 MongoDB 请自行决定,建议至少保留备份文件 30 天
+```
+
+---
+
+## 如果失败,如何回滚
+
+### 场景 1:迁移命令就报错了
+
+最简单的回滚,直接恢复 v11:
+
+```bash
+# Docker
+cd ~/mx-space/core
+cp docker-compose.yml.v11.backup docker-compose.yml
+docker compose up -d
+
+# 源码
+cd ~/mx-space/core
+git checkout v11.x.x
+pm2 restart ecosystem.config.js
+```
+
+> 因为迁移过程**只读** MongoDB 不写,所以回滚后数据完全和升级前一样。
+
+### 场景 2:v12 启动了,但发现数据不对或功能异常
+
+立即切回 v11:
+
+```bash
+# Docker
+cd ~/mx-space/core
+docker compose down
+cp docker-compose.yml.v11.backup docker-compose.yml
+docker compose up -d
+
+# 源码
+cd ~/mx-space/core/apps/core
+pm2 stop ecosystem.config.js
+cd ..
+git checkout v11.x.x
+pm2 start ecosystem.config.js
+```
+
+### 场景 3:已经在 v12 写了新数据,又想回滚
+
+这种情况比较麻烦,因为新数据在 PostgreSQL 里,回滚到 v11(MongoDB)会丢失这部分。建议:
+
+1. 优先在 v12 上排查修复问题(推荐)
+2. 如需帮助,带上错误日志发 [GitHub Issue](https://github.com/mx-space/core/issues)
+
+---
+
+## 常见问题
+
+### 迁移会删除我的 MongoDB 数据吗?
+
+**不会。** 迁移是读取 MongoDB → 写入 PostgreSQL,MongoDB 原封不动。这就是回滚安全的根本原因。
+
+### 图片和附件会丢吗?
+
+**不会。** 图片、附件存在文件系统或对象存储里,不在数据库中,完全不受影响。
+
+### 迁移可以中断后再继续吗?
+
+**可以。** 重复执行迁移命令不会重复导入已迁过的数据,所以可以放心重试。
+
+### 我需要改前端吗?
+
+**一般不需要。** 官方主题(Shiro / Kami / Yohaku)直接兼容。只有直接调用 API 的第三方工具可能需要更新 SDK。
+
+### 为什么要换数据库?
+
+PostgreSQL 是更成熟的关系型数据库,数据一致性更好,未来做复杂查询和统计分析也更方便。对日常使用而言,你感觉不到明显变化,但长期更稳定可靠。
+
+---
+
+## 还需要帮助?
+
+- [GitHub Issues](https://github.com/mx-space/core/issues)
+- [Mix Space 文档站](https://mx-space.js.org)
diff --git a/content/docs/reference/common-issues.mdx b/content/docs/reference/common-issues.mdx
new file mode 100644
index 00000000..1f08d60e
--- /dev/null
+++ b/content/docs/reference/common-issues.mdx
@@ -0,0 +1,69 @@
+---
+title: 常见错误与解决
+description: 按症状分类的常见问题速查
+---
+
+## 无法启动服务
+
+### `Error: JWT_SECRET is required`
+
+- **原因**:JWT 签名密钥未设置,这是启动服务的必填项。
+- **解决**:在环境变量中添加 `JWT_SECRET`,设置一个随机字符串即可。
+
+### `Error: SNOWFLAKE_WORKER_ID is required`
+
+- **原因**:Snowflake 工作节点 ID 未设置。
+- **解决**:在环境变量中添加 `SNOWFLAKE_WORKER_ID=1`(单实例部署填 1 即可)。
+
+### `Connection refused to postgres:5432`
+
+- **原因**:PostgreSQL 服务未启动,或连接配置错误。
+- **解决**:
+ 1. 确认 PostgreSQL 容器或服务已正常运行;
+ 2. 检查 `PG_HOST`、`PG_PORT`、`PG_USER`、`PG_PASSWORD` 是否正确;
+ 3. Docker 部署时,注意容器之间的网络是否互通。
+
+## 无法访问后台
+
+### 502 Bad Gateway
+
+- **原因**:反向代理(Nginx/Caddy)配置错误,无法正确代理到后端服务。
+- **解决**:检查反向代理配置中的 upstream 地址和端口,确认后端服务端口是否为 `2333`(或你自定义的 `PORT`)。
+
+### 证书错误
+
+- **原因**:HTTPS/SSL 证书配置有问题,或使用了自签名证书但客户端不信任。
+- **解决**:检查证书是否过期,确认 Nginx/Caddy 的 SSL 配置正确,必要时重新申请证书。
+
+## 功能异常
+
+### 搜索不工作
+
+- **原因**:Algolia 配置缺失或错误,索引未建立。
+- **解决**:
+ 1. 进入后台检查 Algolia 的 `IndexName`、`AppID`、`ApiKey` 是否填写正确;
+ 2. 确认 Algolia 控制台中索引已创建且有数据;
+ 3. 保存配置后等待片刻,让系统自动同步索引。
+
+### 第三方登录失败
+
+- **原因**:OAuth 应用的回调地址(Callback URL)与后台配置不一致。
+- **解决**:
+ 1. 在 GitHub/Google 控制台核对 `Authorization callback URL`;
+ 2. 在 Mix Space 后台复制正确的回调地址并填入 OAuth 应用;
+ 3. 确认 `ALLOWED_ORIGINS` 中包含了你的前端域名。
+
+## 数据相关
+
+### 备份文件无法下载
+
+- **原因**:备份目录权限不足,或备份路径配置错误。
+- **解决**:检查备份目录的读写权限,确认运行服务的用户有权访问该目录。
+
+### 回滚后数据丢失
+
+- **原因**:回滚时使用了错误的备份文件,或备份文件本身已损坏。
+- **解决**:
+ 1. 确认使用的是正确的备份文件(注意时间戳);
+ 2. 回滚前务必先对当前数据做一次备份;
+ 3. 若备份文件损坏,尝试使用更早的备份。
diff --git a/content/docs/reference/index.mdx b/content/docs/reference/index.mdx
new file mode 100644
index 00000000..07ab9297
--- /dev/null
+++ b/content/docs/reference/index.mdx
@@ -0,0 +1,21 @@
+---
+title: 参考手册
+description: 速查手册和常见问题
+---
+
+import { Card, Cards } from 'fumadocs-ui/components/card';
+import { BookOpen, Wrench, ExternalLink } from 'lucide-react';
+
+不需要通读,遇到问题时来查。
+
+
+ }>
+ 所有环境变量的完整列表和说明
+
+ }>
+ 按症状分类的常见问题与解决方案
+
+ }>
+ 在 GitHub 上查看 API Client 文档
+
+
diff --git a/content/docs/reference/meta.json b/content/docs/reference/meta.json
new file mode 100644
index 00000000..a6858a14
--- /dev/null
+++ b/content/docs/reference/meta.json
@@ -0,0 +1,10 @@
+{
+ "title": "参考手册",
+ "description": "速查手册和常见问题",
+ "icon": "BookOpen",
+ "root": true,
+ "pages": [
+ "index",
+ "common-issues"
+ ]
+}
diff --git a/content/docs/themes/shiro/deploy.mdx b/content/docs/themes/shiro/deploy.mdx
index 93878d46..2524b8c2 100644
--- a/content/docs/themes/shiro/deploy.mdx
+++ b/content/docs/themes/shiro/deploy.mdx
@@ -21,7 +21,7 @@ import Image from 'next/image'
自 Core v7 起,已抛弃 Clerk,取而代之的是 GitHub 和 Google 的 OAuth 2.0,
- 配置步骤请参考 [OAuth 2.0](/docs/usage/oauth)
+ 配置步骤请参考 [OAuth 2.0](/docs/configure/oauth)
~~请注意,Shiro 主题的部署教程与初版有所不同,如果你已经部署过 Shiro
主题,请重新阅读本文档(尤其是填入配置文件环节,配置有所变化),并阅读
@@ -62,7 +62,7 @@ export function FAQBox({ title, children }) {
请注意,这份配置你需要自行修改成符合你的需求的配置。直接使用下面的配置可能会导致你的博客无法按照你的预期运行。
- 下面的配置可能不全,更多配置项的信息请移步 [配置项](./config) 了解。
+ 下面的配置可能不全,更多配置项的信息请移步 [配置项](/docs/themes/shiro/config) 了解。
此外,配置也可写成 yaml 格式,此时数据类型应选择 `YAML`。
@@ -313,7 +313,7 @@ import { EnvVariableConfig } from 'app/components/EnvVariableConfig'
## 通过预构建运行 & Docker Compose
-参见 [README 相关部分](https://github.com/Innei/Shiro/blob/main/README.md#whale-运行) 完成对应操作,随后配置[反向代理](/docs/core/extra#反向代理)。
+参见 [README 相关部分](https://github.com/Innei/Shiro/blob/main/README.md#whale-运行) 完成对应操作,随后配置[反向代理](/docs/deploy/reverse-proxy)。
## 完成!
diff --git a/content/docs/usage/backup.mdx b/content/docs/usage/backup.mdx
deleted file mode 100644
index f2d6c72e..00000000
--- a/content/docs/usage/backup.mdx
+++ /dev/null
@@ -1,44 +0,0 @@
----
-title: 备份与回滚
-description: 在 Mix Space 中内有备份功能,并且每日默认自动备份,数据无价请定期手动下载备份包。
----
-
-## 备份
-
-在后端中 其他 - 备份 中点击立即备份,即备份到绝对目录:
-
-`~/mx-space/core/data/mx-space/backup/20xx-xx-xx_xx:xx:xx/backup-20xx-xx-xx_xx:xx:xx.zip`
-
-## 自动备份
-
-目前该功能仅支持备份到支持 S3 协议的云服务,暂不支持其他类型的云服务。当然,你也可以通过设置计划任务等方法达到和此功能一样的效果。
-
-设置入口:设定 - 系统 - 备份,填入云服务所提供的对应参数即可。
-
-## 回滚
-
-
-该操作涉及修改数据库,请多备份几个工作日的 backup,数据无价请谨慎操作!
-
-一般情况下回滚只会导致 analyze 数据页丢失 IP & PV 的数据。
-
-
-
-Linux 和 macOS 可直接上传备份包,并且无需修改包名一致即可回滚,以下操作仅针对使用 Windows 用户访问后端回滚的情况。
-
-
-在后端中 其他 - 备份 中点击立即备份,将之前在电脑里的 `backup.zip` 上传到刚刚生成的备份目录里进行重命名替换。
-
-
-例:假如刚刚生成的备份是 backup-2022-09-01_23:33:33.zip 将想进行回滚的备份包 backup-2022-01-14_05:14:19.zip 修改为刚刚生成的备份一样的名字:
-
-```bash
-mv ~/mx-space/core/data/mx-space/backup/2022-01-14_05:14:19/backup-2022-01-14_05:14:19.zip backup-2022-09-01_23:33:33.zip
-```
-
-
-不要在 Windows 下重命名,Windows 不支持将英文冒号作为文件名的一部分
-
-
-替换完成会提示“数据库有变动,将在 x 秒后重载页面”,重载先检查文章评论等有没有丢失。
-
diff --git a/content/docs/usage/index.mdx b/content/docs/usage/index.mdx
deleted file mode 100644
index b3c3583b..00000000
--- a/content/docs/usage/index.mdx
+++ /dev/null
@@ -1,62 +0,0 @@
----
-title: 使用指南
-description: 探索 MixSpace 的使用方式
----
-
-本章节将会带您了解 Mix Space 的一些功能,以及如何使用它们。
-
-
-
-温馨提示:此指南需要一定的基础知识 & 理解能力,请准备好哦~
-
-
-### 官方指南
-
-import {
- Database,
- Search,
- LifeBuoy,
- Bitcoin,
- History,
- ArrowUp,
- Key,
- Lock
-} from 'lucide-react'
-
-
- }
- href={'/docs/usage/serverless'}
- title="云函数"
- />
- }
- href={'/docs/usage/search'}
- title="Algolia Search"
- />
- }
- href={'/docs/usage/xlog'}
- title="xLog 集成"
- />
- }
- href={'/docs/usage/backup'}
- title="备份与回滚"
- />
- }
- href={'/docs/usage/update'}
- title="更新 Mix Space"
- />
- }
- href={'/docs/usage/security'}
- title="Key 加密与安全性"
- />
- }
- href={'/docs/usage/oauth'}
- title="OAuth 2.0"
- />
-
diff --git a/content/docs/usage/meta.json b/content/docs/usage/meta.json
deleted file mode 100644
index 6591dab3..00000000
--- a/content/docs/usage/meta.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "index": "使用指南",
- "description": "探索 MixSpace 的使用方式",
- "icon": "BookMarked",
- "root": true,
- "pages": [
- "---文档---",
- "serverless",
- "obsidian",
- "xlog",
- "search",
- "backup",
- "update",
- "security",
- "oauth"
- ]
-}
diff --git a/content/docs/usage/oauth.mdx b/content/docs/usage/oauth.mdx
deleted file mode 100644
index c0e58385..00000000
--- a/content/docs/usage/oauth.mdx
+++ /dev/null
@@ -1,29 +0,0 @@
----
-title: OAuth 2.0
-description: 使用 OAuth 2.0 登录 MixSpace
----
-
-在 Core v7.0.0 版本,Mx-Space 重写了第三方登录功能,抛弃了 Clerk,转而直接使用对应的账户授权 SDK 实现第三方登录。
-
-## 如何配置
-
-### 新建应用
-
-参考以下两篇:
-
-- [在 GitHub 新建 OAuth 应用](https://docs.github.com/zh/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app)
-- [在 Google Cloud Console 新建 OAuth 应用](https://developers.google.com/identity/protocols/oauth2/web-server?hl=zh-cn#creatingcred)
-
-对于 GitHub,`Homepage URL` 填写前端地址,`Authorization callback URL` 根据后台提示复制粘贴。
-
-对于 Google,你可能需要先配置好 OAuth 权限请求页面,其中已获授权的网域填写根域名,API 范围选择非敏感范围的三项。OAuth 应用中 `已获授权的 JavaScript 来源` 填写前端地址,`已获授权的重定向 URI` 根据后台提示复制粘贴。
-
-完成后会获取 Client ID 和 Client Secret,将他们复制下来备用。
-
-### 后台设置
-
-进入博客后台 -> 设定 -> 登录方式,在 OAuth 部分对应的平台名称下填写对应的 Client ID 和 Client Secret,保存后测试是否可以调用授权,若可调用即可启用并保存。
-
-### 和主人身份绑定
-
-在测试时通过 OAuth 授权登录后会提示是否将此账号设置为主人,允许即可。
diff --git a/content/docs/usage/obsidian.mdx b/content/docs/usage/obsidian.mdx
deleted file mode 100644
index 70f49107..00000000
--- a/content/docs/usage/obsidian.mdx
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: Obsidian 插件
-description: 使用 Obsidian 插件发布内容到 Mix Space
----
-
-## 介绍
-
-[Obsidian Mix Space Plugin](https://github.com/mx-space/obsidian-mixspace-plugin) 是一个 Obsidian 插件,可以将 Obsidian 笔记直接发布到 Mix Space。
-
-### 功能特性
-
-- 发布/更新内容到 Mix Space(支持 Note 和 Post)
-- 自动识别内容类型
-- 反向链接转换(`[[Obsidian 链接]]` → Mix Space URL)
-- Frontmatter 自动补全
-- 多环境配置(Profile)
-- AI 生成标题和 slug
-
-## 安装与使用
-
-详细的安装步骤和使用说明请参考 GitHub 仓库:
-
-**[https://github.com/mx-space/obsidian-mixspace-plugin](https://github.com/mx-space/obsidian-mixspace-plugin)**
diff --git a/content/docs/usage/serverless.mdx b/content/docs/usage/serverless.mdx
deleted file mode 100644
index e8fd1da6..00000000
--- a/content/docs/usage/serverless.mdx
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: 云函数
-description: 使用 MixSpace 的云函数功能
----
-
-import { ToGithub } from '@/app/components/ToGithub';
-
-
-## 介绍
-
-云函数是 Mix Space 中的一个重要功能,它极大地提升了使用者在 Mix Space 中的体验。通过云函数,Mix Space 可以额外实现实现歌单解析,追番列表等等的功能。
-
-你可以在此处看到 Mix Space 目前收录的云函数 Snappets
-
-
-
-## 使用
-
-有一些前端主题需要使用云函数,这个时候你需要进入到云函数设置界面,将云函数代码填入到对应的位置。
-
-
-### 1. 进入云函数设置界面
-进入后台管理,点击左侧菜单栏的 `其他 - 云函数`,即可进入云函数管理页面。
-
-### 2. 下载扩展包
-
-在右上方,点击 `下载拓展包`,你将会看到一个弹窗。
-
-### 3. 导入
-
-请在弹窗内请找到对应的主题的云函数代码,点击导入,即可完成下载对应的云函数代码。
-
-
-接下来,你可以在云函数管理页面看到你刚刚导入的云函数代码。
-
-## 开发者文档
-
-
\ No newline at end of file
diff --git a/content/docs/usage/update.mdx b/content/docs/usage/update.mdx
deleted file mode 100644
index 1ada6eb8..00000000
--- a/content/docs/usage/update.mdx
+++ /dev/null
@@ -1,43 +0,0 @@
----
-title: 更新 Mix Space
-description: 更新你的 MixSpace
----
-
-import { FileText } from 'lucide-react'
-
-
-开头介绍就说过,Mx-Space 分为前端和后端两个部分,因此,更新的时候二者也需要分开更新。
-
-## Core(后端)更新
-
-根据部署方式的不同,更新方式也有不同。
-
-### Docker 部署
-
-进入 core 所在文件夹,然后 `docker compose pull && docker compose up -d`
-
-### 进阶部署
-
-进入克隆 core 的文件夹,执行 `git pull origin master` 拉取新版本源码,随后正常进行 `pnpm i` -> `pnpm build` -> `pnpm bundle`。
-
-随后 进入 `./apps/core/out`,执行以下命令启动服务 `pm2 start ecosystem.config.js`
-
-## 前端更新
-
-请根据自己所部署的主题跳转到对应的更新部分完成更新。
-
-
- }
- target="_blank"
- />
-
- }
- target="_blank"
- />
-
diff --git a/content/docs/usage/xlog.mdx b/content/docs/usage/xlog.mdx
deleted file mode 100644
index ea57368e..00000000
--- a/content/docs/usage/xlog.mdx
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: xLog 集成
-description: 使用 xLog 集成
----
-
-## 介绍
-
-此功能需要:
-
-- Core: >=3.43.1
-
-xLog 功能可以将你的博客同步到 [xLog 平台](https://xlog.app/)。
-
-具体就是 `此文章已经由它的创作者签名并安全地存储在区块链上。`
-
-当你没有为文章写摘要的时候,可以使用 xLog 平台生成的摘要,当然你也可以使用自己的 GPT API Key 去调用 GPT 去生成摘要。
-
-## 使用
-
-在 系统 - 第三方服务集成,填写 xLog SiteId 即可,然后去 xLog 平台去升级为钱包登录即可。钱包的注册方法请根据 xLog 的引导一步步注册。
-
-SiteId 是一个字符串,可以在 xLog 平台的设置 - 域名找到;例如 example.xlog.app,即 `SiteId = example`。
-
-当你完成钱包的注册,并使用钱包登录 xLog 平台的时候,就完成设置工作了。
-
-接下来你发布文章的时候,会自动的进行同步和签名;当然,需要经过你的同意。
\ No newline at end of file
diff --git a/content/docs/use/ai-features.mdx b/content/docs/use/ai-features.mdx
new file mode 100644
index 00000000..77e92392
--- /dev/null
+++ b/content/docs/use/ai-features.mdx
@@ -0,0 +1,265 @@
+---
+title: AI 功能
+description: 利用 AI 能力增强你的内容工作流——摘要、精读、翻译、写作助手、评论审核与编辑器 Agent
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 内置了一套完整的 AI 功能体系,覆盖内容创作、管理、分发全流程。你只需配置一个 LLM 服务商即可启用。
+
+
+AI 功能需要后台「设定 → AI 设定」中配置至少一个 Provider 并启用对应功能开关。详见下方 [配置 AI Provider](#配置-ai-provider)。
+
+
+## 功能总览
+
+| 功能 | 说明 | 触发方式 |
+|------|------|----------|
+| **AI 摘要** | 自动生成文章摘要,支持多语言 | 手动 / 自动(发布/更新时) |
+| **AI 精读** | 生成深度阅读伴侣(TL;DR、结构图、Mermaid 图、引用锚点) | 手动 / 自动(发布/更新时) |
+| **AI 翻译** | 将文章翻译为多语言版本,保持 Markdown/Lexical 格式完整 | 手动 / 自动(发布/更新时) |
+| **写作助手** | 自动生成标题和 SEO slug,批量回填历史文章 slug | 编辑器内手动 |
+| **评论审核** | AI 自动识别垃圾评论和有害内容 | 自动(评论提交时) |
+| **AI Agent** | 在编辑器中与 AI 对话,辅助写作和修改 | 编辑器内手动 |
+| **任务队列** | 统一管理所有 AI 后台任务的创建、进度和重试 | 后台 AI 页面 |
+
+## 配置 AI Provider
+
+
+
+### 进入设置页面
+
+登录后台,前往「设定 → AI 设定」。
+
+
+
+### 添加 Provider
+
+点击「添加 Provider」,填写以下信息:
+
+| 字段 | 说明 | 示例 |
+|------|------|------|
+| Provider ID | 唯一标识符 | `openai-main`、`deepseek` |
+| 显示名称 | 便于识别的名称 | `OpenAI`、`DeepSeek` |
+| Provider 类型 | 服务商类型 | OpenAI / OpenAI-Compatible / Anthropic / OpenRouter |
+| API Key | 你的 API 密钥 | `sk-...` |
+| 自定义 Endpoint | OpenAI-Compatible 类型必填 | `https://api.deepseek.com` |
+| 默认模型 | 该 Provider 默认使用的模型 | `gpt-4o`、`deepseek-chat` |
+
+
+
+### 为各功能分配模型(可选)
+
+在 Provider 列表下方,可以为摘要、写作、翻译、精读等功能分别指定使用哪个 Provider 和模型。留空则使用第一个启用的 Provider 及其默认模型。
+
+
+
+### 测试连接
+
+配置完成后,点击 Provider 旁的「测试」按钮,验证 API Key 和 Endpoint 是否正确。
+
+
+
+
+你可以同时配置多个 Provider,并将不同的 AI 功能分配给不同的 Provider。例如用 DeepSeek 做翻译(成本低),用 OpenAI 做精读(效果好)。
+
+
+## AI 摘要
+
+AI 摘要可以为你的文章自动生成简短的内容概要,支持多语言输出。
+
+### 开启摘要
+
+在「设定 → AI 设定」中:
+
+1. 打开「可调用 AI 摘要」开关
+2. 设置「AI 摘要目标语言列表」(使用 [ISO 639-1 语言代码](https://www.w3schools.com/tags/ref_language_codes.asp),如 `zh`、`en`、`ja`)
+3. 可选:打开「文章创建时自动生成摘要」和「文章更新时重新生成摘要」
+4. 可选:设置「摘要自动生成最小文本长度」(低于此字符数的文章跳过自动生成)
+
+### 手动生成摘要
+
+进入后台「AI → 摘要」页面,选择文章后点击生成。也可以在文章编辑器中通过侧边栏触发。
+
+### 摘要管理
+
+在「AI → 摘要」页面中,你可以:
+
+- 按文章分组查看所有摘要
+- 编辑已生成的摘要文本
+- 删除不需要的摘要
+- 查看摘要对应的原文信息
+
+## AI 精读(Insights)
+
+AI 精读是比摘要更深入的内容分析功能。它会生成一篇「深度阅读伴侣」,包含 TL;DR、结构化大纲、Mermaid 图表、引用锚点回原文、开放性问题等内容,帮助读者更好地理解文章。
+
+### 开启精读
+
+在「设定 → AI 设定」中:
+
+1. 打开「可调用 AI Insights」开关
+2. 可选:打开「文章创建时自动生成 Insights」和「文章更新时重新生成 Insights」
+3. 可选:设置「Insights 目标语言列表」用于精读内容的多语言翻译
+4. 可选:打开「Insights 生成后自动翻译」
+5. 可选:设置「Insights 自动生成最小文本长度」
+
+### 精读内容包含什么
+
+精读根据文章类型自动选择 3-7 个组件进行生成,可能包含:
+
+| 组件 | 说明 |
+|------|------|
+| TL;DR | 1-3 句话概括核心观点 |
+| 结构图 / 时间线 | 文章的逻辑结构或事件时序 |
+| Mermaid 图表 | 架构图、流程图、因果链等可视化 |
+| 关键概念 | 术语表或背景知识卡片 |
+| 引用锚点 | 精读中的关键论点锚定回原文位置 |
+| 反论与盲点 | 指出作者未涉及的视角 |
+| 开放性问题 | 值得读者进一步思考的问题 |
+
+### 精读翻译
+
+精读内容也支持多语言翻译。设置「Insights 目标语言列表」后,可以在精读页面手动触发翻译,或开启自动翻译。
+
+## AI 翻译
+
+AI 翻译可以将你的文章完整翻译为多语言版本,保持 Markdown 格式、代码块、链接等技术元素不变,同时保持翻译一致性。
+
+### 开启翻译
+
+在「设定 → AI 设定」中:
+
+1. 打开「可调用 AI 翻译」开关
+2. 设置「AI 翻译目标语言列表」(如 `en`、`ja`、`ko`)
+3. 可选:打开「开启 AI 翻译自动生成」(文章发布后自动翻译)
+
+### 翻译特性
+
+- **双策略支持**:Markdown 文章和 Lexical 富文本文章分别使用对应的翻译策略,确保格式完整保留
+- **翻译词表**:系统自动维护分类名称、话题名称、心情、天气等短文本的翻译一致性
+- **多语言批量翻译**:可以一次为多篇文章生成多语言翻译
+- **全量翻译**:支持一键为所有已有文章生成翻译
+
+### 手动翻译操作
+
+进入后台「AI → 翻译」页面:
+
+- 选择文章,点击「翻译」
+- 选择目标语言后开始生成
+- 生成完成后可查看、编辑、删除翻译
+
+### 翻译词表
+
+进入「AI → 翻译词表」页面,可以查看和管理系统自动维护的翻译词表。词表用于确保分类、话题、心情、天气等短文本在不同文章间翻译一致。
+
+支持的管理操作:
+- 按类型(分类名、话题名、心情、天气)筛选查看
+- 手动编辑翻译结果
+- 批量重新生成
+
+## 写作助手
+
+写作助手在编辑器中为你提供 AI 辅助。
+
+### 标题和 Slug 生成
+
+在编辑器中撰写完内容后,可以使用 AI 自动生成:
+- **标题**:根据文章内容生成一个合适的标题
+- **Slug**:生成 SEO 友好的英文 URL 路径
+
+
+确保在 AI 设定中配置了写作助手模型(Writer Model),或在编辑器的 AI 面板中选择了可用的 Provider。
+
+
+### Slug 批量回填
+
+如果你有历史文章缺少 slug,可以使用「AI → Slug 回填」功能:
+
+1. 进入后台「AI → Slug 回填」页面
+2. 查看缺少 slug 的日记条目数量
+3. 点击「开始回填」,系统会为所有缺少 slug 的日记自动生成 SEO slug
+
+## 评论审核
+
+AI 评论审核功能会在读者提交评论时自动进行内容安全检查。
+
+### 配置评论审核
+
+在后台「设定 → 评论设置」中:
+
+1. 打开「开启 AI 审核」开关
+2. 选择审核方式:
+ - **是非模式(Binary)**:AI 判断评论是否为垃圾内容
+ - **评分模式(Score)**:AI 给出风险评分(1-10),超过阈值则判定为垃圾
+3. 如果使用评分模式,设置阈值(默认 5,范围 1-10)
+4. 点击「测试 AI 审核」验证功能
+
+### 检测能力
+
+AI 评论审核可以识别以下类型的违规内容:
+
+- 垃圾评论、广告、诈骗
+- 人身攻击、网络霸凌
+- 仇恨言论和歧视
+- 政治敏感、色情、暴力内容
+- 阴阳怪气和隐性攻击
+- 无意义测试内容
+
+## AI Agent(编辑器内对话)
+
+AI Agent 允许你在编辑器中直接与 AI 对话,辅助写作和内容修改。
+
+### 使用方式
+
+在文章编辑器中,打开右侧的 AI Agent 面板:
+
+1. 选择一个已配置的 Provider 和模型
+2. 在对话框中输入指令,如「帮我润色这段文字」「把这段改成更口语化的风格」
+3. AI 的回复可以应用到编辑器中
+
+
+AI Agent 对话历史会自动保存,你可以在同一篇文章中随时继续之前的对话。
+
+
+## 任务队列
+
+所有 AI 后台任务通过统一的任务队列管理,你可以在「AI → 任务」页面查看和管理。
+
+### 任务类型
+
+| 任务类型 | 说明 |
+|----------|------|
+| 摘要生成 | 为单篇文章生成摘要 |
+| 翻译生成 | 为单篇文章生成翻译 |
+| 批量翻译 | 为多篇文章批量生成翻译 |
+| 全量翻译 | 为所有文章生成翻译 |
+| 精读生成 | 为单篇文章生成精读 |
+| 精读翻译 | 翻译已生成的精读内容 |
+| Slug 回填 | 为历史日记批量生成 slug |
+
+### 任务状态
+
+| 状态 | 说明 |
+|------|------|
+| Pending | 等待执行 |
+| Running | 正在执行 |
+| Completed | 执行完成 |
+| Partial Failed | 部分子任务失败 |
+| Failed | 执行失败 |
+| Cancelled | 已取消 |
+
+### 任务管理
+
+在任务页面中,你可以:
+
+- 按状态和类型筛选任务
+- 查看任务详情(进度、日志、耗时)
+- 重试失败的任务
+- 取消正在运行的任务
+- 批量清理历史任务
+
+
+批量翻译任务会自动分组,你可以在任务列表中展开查看每个子任务的状态。
+
diff --git a/content/docs/use/analytics.mdx b/content/docs/use/analytics.mdx
new file mode 100644
index 00000000..6380c9d0
--- /dev/null
+++ b/content/docs/use/analytics.mdx
@@ -0,0 +1,62 @@
+---
+title: 站点统计与分析
+description: 查看站点访问数据、流量来源、设备分布和内容互动统计
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 内置了站点统计功能,你可以在后台查看访问量、独立访客、流量来源、热门路径等数据,无需集成第三方统计服务。
+
+## 统计概览
+
+登录后台,首页(仪表盘)即展示关键数据概览:
+
+| 指标 | 说明 |
+|------|------|
+| **文章数** | 已发布的文章总数 |
+| **日记数** | 已发布的日记总数 |
+| **评论数** | 评论总数 |
+| **友链数** | 已通过的友链总数 |
+| **在线人数** | 当前 WebSocket 在线连接数 |
+| **总阅读量** | 所有内容的阅读计数 |
+| **总点赞数** | 所有内容的点赞计数 |
+
+## 详细分析
+
+进入后台「分析」页面,可以查看更详细的统计数据。
+
+### 访问趋势
+
+| 视图 | 说明 |
+|------|------|
+| **今日** | 按小时展示今天的 IP 和 PV 数据 |
+| **本周** | 按周几展示近 7 天的 IP 和 PV |
+| **本月** | 按日期展示近 30 天的 IP 和 PV |
+
+### 热门路径
+
+展示访问量最高的页面路径列表,帮助你了解哪些内容最受欢迎。
+
+### 流量来源
+
+展示访客的来源渠道分布(搜索引擎、直接访问、外部链接等)。
+
+### 设备分布
+
+展示访客使用的设备类型和浏览器分布。
+
+## 评论活动
+
+分析页面还展示评论活动趋势图,可以看到评论数量的时间变化。
+
+## 数据管理
+
+在分析页面中,你可以:
+
+- **按时间范围查询**:选择起止日期查看特定时间段的数据
+- **查看今日/本周数据**:快速切换到常用时间范围
+- **清除历史数据**:按时间范围清除分析数据
+
+
+分析数据存储在 Redis 中,具有缓存机制。聚合数据缓存约 1 分钟,流量来源和设备分布数据缓存约 5 分钟。
+
diff --git a/content/docs/use/backup-restore.mdx b/content/docs/use/backup-restore.mdx
new file mode 100644
index 00000000..7f8a1e88
--- /dev/null
+++ b/content/docs/use/backup-restore.mdx
@@ -0,0 +1,66 @@
+---
+title: 备份与恢复
+description: 保护你的 Mix Space 数据,学会备份与回滚
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+## 手动备份
+
+在后台「其他 → 备份」中点击「立即备份」,系统会将数据打包为 zip 文件,保存到服务器的绝对目录:
+
+```
+~/mx-space/core/data/mx-space/backup/20xx-xx-xx_xx:xx:xx/backup-20xx-xx-xx_xx:xx:xx.zip
+```
+
+建议定期手动下载备份包到本地,以防服务器故障导致数据丢失。
+
+## 自动备份
+
+目前该功能仅支持备份到支持 S3 协议的云服务,暂不支持其他类型的云服务。当然,你也可以通过设置计划任务等方法达到和此功能一样的效果。
+
+设置入口:后台「设定 → 系统 → 备份」,填入云服务所提供的对应参数即可。
+
+## 恢复
+
+
+该操作涉及修改数据库,请多备份几个工作日的 backup,数据无价请谨慎操作!
+
+一般情况下回滚只会导致 analyze 数据页丢失 IP & PV 的数据。
+
+
+
+Linux 和 macOS 可直接上传备份包,并且无需修改包名一致即可回滚,以下操作仅针对使用 Windows 用户访问后端回滚的情况。
+
+
+在后台「其他 → 备份」中点击「立即备份」,将之前在电脑里的 `backup.zip` 上传到刚刚生成的备份目录里进行重命名替换。
+
+例:假如刚刚生成的备份是 `backup-2022-09-01_23:33:33.zip`,将想进行回滚的备份包 `backup-2022-01-14_05:14:19.zip` 修改为刚刚生成的备份一样的名字:
+
+```bash
+mv ~/mx-space/core/data/mx-space/backup/2022-01-14_05:14:19/backup-2022-01-14_05:14:19.zip backup-2022-09-01_23:33:33.zip
+```
+
+
+不要在 Windows 下重命名,Windows 不支持将英文冒号作为文件名的一部分。
+
+
+替换完成后会提示「数据库有变动,将在 x 秒后重载页面」,重载后请先检查文章、评论等有没有丢失。
+
+## 命令行备份(v12+)
+
+自 v12 起,Mix Space 使用 PostgreSQL 作为数据库。你可以直接使用 `pg_dump` 进行命令行备份:
+
+```bash
+pg_dump postgresql://mx:mx@localhost:5432/mx_core > backup.sql
+```
+
+恢复时执行:
+
+```bash
+psql postgresql://mx:mx@localhost:5432/mx_core < backup.sql
+```
+
+
+请根据实际情况修改连接字符串中的用户名、密码、主机和数据库名。
+
diff --git a/content/docs/use/comments.mdx b/content/docs/use/comments.mdx
new file mode 100644
index 00000000..4b28e1f4
--- /dev/null
+++ b/content/docs/use/comments.mdx
@@ -0,0 +1,100 @@
+---
+title: 评论管理
+description: 管理读者评论、配置反垃圾策略、开启 AI 审核与评论图片上传
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 提供了完整的评论系统,支持访客留言、登录读者评论、站长回复,以及多层嵌套讨论。你可以在后台对评论进行审核、置顶、标记垃圾等操作,也可以借助 AI 自动审核来减轻管理负担。
+
+## 评论管理界面
+
+登录后台,进入「评论」页面。页面分为三个标签:
+
+| 标签 | 说明 |
+|------|------|
+| **待审** | 未读状态的新评论,需要你审阅 |
+| **已读** | 正常的已读评论 |
+| **垃圾** | 被标记为垃圾的评论 |
+
+### 常用操作
+
+| 操作 | 说明 |
+|------|------|
+| **标记已读 / 未读** | 切换评论的阅读状态 |
+| **标记垃圾** | 将评论标记为垃圾内容,前台不再展示 |
+| **置顶** | 将评论固定在该页面的最顶部(同页面仅一条置顶) |
+| **删除** | 软删除评论,内容替换为「该评论已删除」 |
+| **批量操作** | 勾选多条评论后批量修改状态或批量删除 |
+
+
+评论被标记为垃圾时,如果该评论附带图片,系统会自动删除这些图片文件(可在「评论图片上传」设置中关闭此行为)。
+
+
+## 评论配置
+
+进入后台「设定 → 评论设置」,可以配置以下选项:
+
+### 基本设置
+
+| 配置项 | 说明 |
+|--------|------|
+| **全站禁止评论** | 关闭全站评论功能,敏感时期专用 |
+| **允许未登录评论** | 开启后访客可以以游客身份评论;关闭后仅已登录读者和站长可以评论 |
+| **只展示已读评论** | 开启后,前台只展示已标记为已读的评论,未读和垃圾评论均不展示 |
+| **禁止非中文评论** | 过滤非中文字符的评论内容 |
+| **评论公开归属地** | 在评论旁显示评论者的 IP 归属地 |
+| **自定义屏蔽关键词** | 添加需要过滤的关键词列表 |
+| **自定义屏蔽 IP** | 添加需要屏蔽的 IP 地址列表 |
+
+### 反垃圾评论
+
+打开「反垃圾评论」开关后,系统会自动检测并过滤垃圾评论。
+
+### AI 评论审核
+
+如果你已在「AI 设定」中配置了 LLM 服务商,可以开启 AI 评论审核:
+
+| 配置项 | 说明 |
+|--------|------|
+| **开启 AI 审核** | 启用后,评论提交时会自动进行 AI 内容安全检查 |
+| **AI 审核方式** | 「是非」模式(AI 直接判断是否为垃圾)或「评分」模式(AI 给出 1-10 风险评分) |
+| **AI 审核阈值** | 评分模式下,超过此阈值的评论被标记为垃圾(默认 5,范围 1-10) |
+| **测试 AI 审核** | 输入测试文本,验证 AI 审核功能是否正常 |
+
+AI 评论审核可以识别垃圾广告、人身攻击、仇恨言论、政治敏感、色情暴力、阴阳怪气等多种违规内容。
+
+## 评论图片上传
+
+读者在评论中上传图片的功能,需要在「设定 → 评论图片上传」中单独配置:
+
+| 配置项 | 说明 |
+|--------|------|
+| **启用读者评论图片上传** | 总开关,关闭后前端隐藏上传入口 |
+| **单图最大大小(MB)** | 默认 5 MB |
+| **单评论图片张数上限** | 默认 4 张 |
+| **单读者每小时上传上限** | 默认 10 次 |
+| **单读者活跃图总容量上限(MB)** | 默认 50 MB |
+| **读者账号最小年龄(小时)** | 准入门槛,0 表示不限 |
+| **读者最小已发评论数** | 准入门槛,0 表示不限 |
+| **评论标记 spam 时同步删图** | 默认开启,关闭则仅删评论保留图片 |
+| **MIME 白名单** | 默认 image/jpeg、image/png、image/webp、image/gif |
+
+
+评论图片有自动清理机制:上传后未被评论引用的图片会在设定时间后自动清除(默认 120 分钟),评论编辑后被移除的图片也会在设定时间后清除(默认 30 分钟)。
+
+
+## 评论排序
+
+前台评论支持三种排序方式:
+
+| 排序 | 说明 |
+|------|------|
+| **置顶优先** | 置顶评论在最前,其余按时间倒序(默认) |
+| **最新** | 按时间倒序 |
+| **最早** | 按时间正序 |
+
+## 悄悄话
+
+评论支持「悄悄话」模式,标记为悄悄话的评论仅站长可见,前台不展示给其他访客。
diff --git a/content/docs/use/content.mdx b/content/docs/use/content.mdx
new file mode 100644
index 00000000..5d2f0aa6
--- /dev/null
+++ b/content/docs/use/content.mdx
@@ -0,0 +1,166 @@
+---
+title: 内容管理
+description: 管理文章、日记、页面——发布、分类、标签、置顶与草稿
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 支持三种主要的内容类型:**文章**(Post)、**日记**(Note)和**页面**(Page)。每种类型有不同的用途和字段。
+
+## 内容类型对比
+
+| 类型 | 用途 | URL 格式 | 特殊字段 |
+|------|------|----------|----------|
+| **文章** | 长篇博客文章 | `/{分类 slug}/{文章 slug}` | 分类、标签、置顶、相关文章、版权声明 |
+| **日记** | 短篇手记、随想 | `/notes/{nid}` 或 `/notes/{年}/{月}/{日}/{slug}` | 心情、天气、密码保护、专题、位置 |
+| **页面** | 独立页面(关于、友链等) | `/{页面 slug}` | 副标题、排序 |
+
+所有内容类型共有的字段:
+
+| 字段 | 说明 |
+|------|------|
+| **标题** | 内容标题 |
+| **正文** | 支持 Markdown 和 Lexical 富文本两种格式 |
+| **摘要** | 文章概要,留空可由 AI 自动生成 |
+| **发布状态** | 已发布 / 草稿 |
+| **创建时间 / 修改时间** | 自动记录 |
+| **评论开关** | 是否允许评论 |
+| **自定义元数据** | JSON 格式的扩展字段 |
+
+## 文章管理
+
+登录后台,进入「文章」页面。
+
+### 创建文章
+
+1. 点击右上角「新建」
+2. 在编辑器中撰写内容
+3. 在右侧面板中设置:
+
+| 设置项 | 说明 |
+|--------|------|
+| **分类** | 必选,将文章归入一个分类 |
+| **Slug** | URL 路径片段,建议英文小写加连字符(如 `my-first-post`) |
+| **标签** | 自由标签,输入后回车添加 |
+| **摘要** | 文章摘要,留空可由 AI 生成 |
+| **版权声明** | 是否在文末显示版权信息 |
+| **置顶** | 置顶该文章并设置置顶顺序 |
+| **发布状态** | 设为草稿或直接发布 |
+
+### 文章列表
+
+文章列表支持以下操作:
+
+- **按分类筛选**:选择分类快速过滤
+- **按年份筛选**:查看特定年份的文章
+- **搜索**:按标题搜索
+- **批量管理**:发布、撤回、删除
+
+
+文章的 URL 格式为 `/{分类 slug}/{文章 slug}`,例如 `/coding/my-first-post`。分类 slug 和文章 slug 共同决定了文章的唯一地址。
+
+
+### 置顶
+
+文章可以置顶,置顶的文章会排在列表最前面。置顶支持设置顺序(数字越大越靠前),多篇文章同时置顶时按顺序排列。
+
+### 相关文章
+
+在文章编辑面板中可以设置「相关文章」,为读者推荐关联内容。
+
+## 日记管理
+
+登录后台,进入「日记」页面。
+
+### 日记特有字段
+
+| 字段 | 说明 |
+|------|------|
+| **心情** | 记录写日记时的心情(如「开心」「思考」) |
+| **天气** | 记录天气情况 |
+| **专题** | 将日记归入一个专题 |
+| **密码保护** | 为单篇日记设置访问密码 |
+| **位置** | 记录写作地点(仅后台可见) |
+| **书签** | 标记为收藏日记 |
+
+### 日记 URL
+
+日记支持两种 URL 格式:
+
+- **NID 格式**:`/notes/{nid}`(自动递增的数字 ID)
+- **日期 + Slug 格式**:`/notes/2024/01/15/my-thoughts`(需要手动设置 slug)
+
+
+日记的 slug 不是必须的。如果你想使用 SEO 友好的 URL(日期 + slug 格式),需要在编辑时手动填写 slug。未设置 slug 的日记只能通过 NID 访问。AI Slug 回填功能可以为缺少 slug 的日记批量生成。
+
+
+### 专题
+
+日记可以归入「专题」。专题是一组相关日记的集合,类似于一个迷你系列。
+
+在后台「专题」页面中可以管理专题:
+
+- 创建专题(名称、Slug、介绍、图标)
+- 编辑和删除专题
+- 在日记编辑时选择归属专题
+
+### 密码保护
+
+为日记设置密码后,访客需要输入密码才能查看内容。后台管理视图中可以直接查看,不受密码限制。
+
+## 页面管理
+
+登录后台,进入「页面」页面。
+
+页面是独立的内容单元,通常用于「关于」「友链」「项目」等不归属于分类的固定页面。
+
+### 页面字段
+
+| 字段 | 说明 |
+|------|------|
+| **标题** | 页面标题 |
+| **副标题** | 页面副标题 |
+| **Slug** | URL 路径(如 `about` → `/about`) |
+| **排序** | 数字越大排序越靠前 |
+| **正文** | 页面内容 |
+
+## 分类管理
+
+在后台「分类」页面中管理文章分类。
+
+每个分类包含:
+
+| 字段 | 说明 |
+|------|------|
+| **名称** | 分类名称 |
+| **Slug** | URL 路径片段 |
+| **类型** | 分类(Category)或标签(Tag) |
+
+
+删除分类不会删除该分类下的文章,但文章将失去分类归属。建议在删除前先迁移文章到其他分类。
+
+
+## 内容格式
+
+Mix Space 支持两种内容编辑格式:
+
+| 格式 | 说明 |
+|------|------|
+| **Markdown** | 标准 Markdown 语法,适合习惯纯文本写作的用户 |
+| **Lexical 富文本** | 可视化富文本编辑器,支持拖拽排版、嵌入等高级功能 |
+
+你可以在后台设置中配置默认使用哪种格式,也可以在编辑时切换。
+
+## 草稿功能
+
+编辑器会自动保存草稿,防止意外丢失内容。草稿功能包括:
+
+- **自动保存**:编辑过程中定时保存
+- **草稿恢复**:打开文章编辑时,如果有未提交的草稿会提示恢复
+- **草稿列表**:在编辑器中查看所有草稿
+
+## 定时发布
+
+文章和日记都支持定时发布:在编辑面板中设置 `publicAt` 字段为未来的某个时间,内容将在指定时间自动发布。
+
+在此之前,内容保持草稿状态,前台不可见。
diff --git a/content/docs/use/cron-tasks.mdx b/content/docs/use/cron-tasks.mdx
new file mode 100644
index 00000000..f058cd65
--- /dev/null
+++ b/content/docs/use/cron-tasks.mdx
@@ -0,0 +1,64 @@
+---
+title: 定时任务
+description: 查看、手动触发和管理 Mix Space 的系统定时任务
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 内置了一组定时任务,用于自动清理过期数据、推送搜索引擎、维护系统健康。你可以在后台查看这些任务的执行状态,也可以手动触发。
+
+## 管理入口
+
+登录后台,进入「维护 → 定时任务」页面。
+
+## 内置任务列表
+
+| 任务 | 说明 | 默认执行频率 |
+|------|------|-------------|
+| **清理访问记录** | 清理过期的访问分析记录 | 每月 1 日凌晨 |
+| **清理 IP 访问记录** | 重置 IP 访问计数 | 每日凌晨 |
+| **清理喜欢数** | 重置文章的点赞和阅读计数缓存 | 每日凌晨 |
+| **清理临时文件** | 删除临时目录中的过期文件 | 每日凌晨 3 点 |
+| **推送百度搜索** | 将新内容推送到百度搜索引擎 | 每日凌晨 1 点 |
+| **推送 Bing 搜索** | 将新内容推送到 Bing 搜索引擎 | 每日凌晨 1 点 |
+| **删除过期 JWT** | 清理数据库中过期的 JWT 令牌 | 每日凌晨 1 点 |
+| **重建搜索索引** | 重建 Algolia 等搜索服务的索引 | 每日凌晨 4 点 |
+| **清理评论图片上传** | 清理未被引用和过期的评论图片 | 每 15 分钟 |
+
+
+搜索引擎推送任务(百度、Bing)需要先在「设定」中配置对应的 Token / API 密钥并开启推送,否则任务不会实际推送数据。
+
+
+## 任务状态
+
+| 状态 | 说明 |
+|------|------|
+| 等待中 | 任务已创建,等待执行 |
+| 执行中 | 任务正在运行 |
+| 已完成 | 任务执行成功 |
+| 部分失败 | 多步骤任务中有部分步骤失败 |
+| 失败 | 任务执行失败 |
+| 已取消 | 任务被手动取消 |
+
+## 手动触发
+
+在定时任务页面中,点击任务旁的「执行」按钮可以手动触发该任务。适用于:
+
+- 首次配置搜索引擎推送后,立即推送已有内容
+- 清理了大量垃圾评论后,手动清理评论图片
+- 搜索索引异常时,手动重建
+
+## 任务日志
+
+每个任务执行后会保留日志记录,包含:
+
+- 任务类型和执行时间
+- 执行结果(成功/失败)
+- 详细的执行输出
+- 失败时的错误信息
+
+对于失败的任务,可以点击「重试」按钮重新执行。
+
+## 清理历史任务
+
+在任务列表中,可以批量清理已完成的历史任务记录,保持列表整洁。
diff --git a/content/docs/use/faq.mdx b/content/docs/use/faq.mdx
new file mode 100644
index 00000000..32d621a2
--- /dev/null
+++ b/content/docs/use/faq.mdx
@@ -0,0 +1,113 @@
+---
+title: 常见问题
+description: 日常使用 Mix Space 时的常见疑问与解答
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+## 部署相关
+
+### 忘记后台密码怎么办?
+
+如果你配置了 OAuth 登录(GitHub / Google),可以先通过第三方账号登录后台,再在「设定 → 个人信息」中修改密码。
+
+如果没有配置 OAuth,可以通过数据库直接修改密码字段来重置。
+
+### 如何修改网站标题和描述?
+
+登录后台,进入「设定 → SEO 优化」,修改网站标题和网站描述,保存后立即生效。
+
+### 后台地址是什么?
+
+默认后台地址为 `https://你的域名/proxy/qaqdmin`。如果开启了后台反代(「设定 → 后台附加设置」),也可以通过 API 地址直接访问。
+
+### 启动报错 `JWT_SECRET is required`
+
+JWT 密钥是必填项。在环境变量或 `docker-compose.yml` 中添加 `JWT_SECRET=你的随机字符串`(16-32 位)。
+
+### 启动报错 `SNOWFLAKE_WORKER_ID is required`
+
+单实例部署填 `SNOWFLAKE_WORKER_ID=1` 即可。
+
+## 内容相关
+
+### 文章的 URL 规则是什么?
+
+文章 URL 格式为 `/{分类 slug}/{文章 slug}`。分类 slug 和文章 slug 共同决定文章地址。例如分类 `coding` 下 slug 为 `hello-world` 的文章,URL 为 `/coding/hello-world`。
+
+### 如何为日记设置密码保护?
+
+在日记编辑面板中设置密码字段。设置后,访客需要输入密码才能查看日记内容。管理员在后台可以直接查看,不受限制。
+
+### 如何批量导入文章?
+
+在后台文章列表页面点击「导入」按钮,选择本地的 Markdown 文件。系统会自动解析 Frontmatter 中的标题、标签、分类等元数据。详见 [写作工作流](/docs/use/writing)。
+
+### 支持哪些编辑器格式?
+
+Mix Space 支持 **Markdown** 和 **Lexical 富文本**两种编辑格式。可以在编辑器中切换,也可以在设置中配置默认格式。
+
+## 图片与存储
+
+### 图片存在哪里?
+
+默认存储在服务器本地。你也可以配置 S3 兼容的对象存储(如 Cloudflare R2、AWS S3),详见 [图床与存储](/docs/configure/image-storage)。
+
+### 上传的图片 URL 格式是什么?
+
+- 本地存储:`/api/v2/static/{type}/{filename}`
+- S3 存储:`{自定义域名}/{前缀}/{filename}`
+
+自定义命名规则可以在「设定 → 文件上传设定」中配置。
+
+## 邮件与通知
+
+### 评论通知邮件不发送?
+
+请检查:
+1. 后台「设定 → 邮件通知设置」中是否开启了邮件提醒
+2. SMTP 配置是否正确(主机、端口、用户名、密码)
+3. 如果使用 Gmail,需要开启「应用专用密码」
+4. 服务器防火墙是否放行了 SMTP 端口(465/587)
+
+推荐使用 [Resend](https://resend.com) 等现代邮件 API 服务,配置更简单。
+
+### 如何推送到 Telegram / 微信?
+
+通过 Webhook 功能实现。在后台「其他 → Webhook」中创建一个 Webhook,Payload URL 填写你的通知服务地址,勾选关注的事件即可。详见 [Webhook 与事件通知](/docs/use/webhook)。
+
+## 数据库与迁移
+
+### 数据库可以迁移到另一台服务器吗?
+
+可以。推荐步骤:
+1. 在原服务器执行备份(后台备份或 `pg_dump`)
+2. 将备份文件传输到新服务器
+3. 在新服务器恢复数据并重启服务
+
+跨服务器迁移时,保持环境变量和配置一致,尤其是 `JWT_SECRET` 和加密密钥。
+
+### 如何从 MongoDB 迁移到 PostgreSQL?
+
+请参考 [v11 → v12 升级指南](/docs/migrate/v11-to-v12)。
+
+## 性能与优化
+
+### 站点访问速度慢?
+
+常见优化手段:
+1. **使用 CDN**:为静态资源和图片配置 CDN 加速
+2. **开启 S3 图床**:将图片托管到对象存储 + CDN
+3. **Redis 缓存**:确保 Redis 正常运行,Mix Space 大量依赖 Redis 缓存
+4. **反向代理优化**:开启 Nginx 的 gzip 压缩和静态文件缓存
+
+### Docker 容器占用内存过高?
+
+Mix Space 正常运行约需要 256-512MB 内存。如果内存占用异常,检查:
+- 是否有大量 AI 任务在后台运行
+- Redis 连接是否正常
+- 日志文件是否过大
+
+
+遇到文档中没有覆盖的问题?可以在 [GitHub Issues](https://github.com/mx-space/core/issues) 中搜索或提交新问题。
+
diff --git a/content/docs/use/files.mdx b/content/docs/use/files.mdx
new file mode 100644
index 00000000..b4d47706
--- /dev/null
+++ b/content/docs/use/files.mdx
@@ -0,0 +1,86 @@
+---
+title: 文件管理
+description: 管理上传的图片、图标、头像和文件,配置自定义命名规则与存储路径
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 后台提供了文件管理功能,支持图片、图标、头像和普通文件的上传、浏览与管理。
+
+## 文件管理界面
+
+登录后台,进入「文件」页面。页面分为以下标签:
+
+| 标签 | 说明 |
+|------|------|
+| **图标** | 站点使用的图标文件 |
+| **头像** | 用户头像文件 |
+| **图片** | 文章和内容中使用的一般图片 |
+| **文件** | 其他普通文件 |
+
+### 文件操作
+
+| 操作 | 说明 |
+|------|------|
+| **上传** | 拖拽或点击上传文件,支持批量上传 |
+| **复制链接** | 复制文件的 URL 地址 |
+| **在新标签页打开** | 预览文件 |
+| **删除** | 删除不需要的文件 |
+
+
+在编辑器中粘贴或拖拽图片时,文件会自动上传到「图片」分类中。
+
+
+## 评论图片管理
+
+在文件管理页面的「评论图片」标签中,可以查看和管理读者在评论中上传的图片:
+
+- 按评论归属查看图片
+- 删除不当图片
+- 查看孤立图片(未被引用的图片)
+
+孤立图片会在设定时间后被系统自动清理。
+
+## 文件上传配置
+
+进入后台「设定 → 文件上传设定」,可以自定义文件命名和存储规则:
+
+| 配置项 | 说明 |
+|--------|------|
+| **启用自定义文件命名** | 开启后使用下方定义的命名模板 |
+| **文件名模板** | 定义上传文件的命名规则 |
+| **文件路径模板** | 定义文件的存储路径规则 |
+
+### 占位符
+
+文件名和路径模板支持以下占位符:
+
+| 占位符 | 说明 |
+|--------|------|
+| `{Y}` | 年份(4 位) |
+| `{y}` | 年份(2 位) |
+| `{m}` | 月份 |
+| `{d}` | 日期 |
+| `{h}` | 小时 |
+| `{i}` | 分钟 |
+| `{s}` | 秒 |
+| `{ms}` | 毫秒 |
+| `{timestamp}` | Unix 时间戳 |
+| `{md5}` | 随机 MD5(32 位) |
+| `{md5-16}` | 随机 MD5(16 位) |
+| `{uuid}` | UUID |
+| `{str-N}` | N 位随机字符串 |
+| `{filename}` | 原文件名(含扩展名) |
+| `{name}` | 原文件名(不含扩展名) |
+| `{ext}` | 扩展名 |
+
+路径模板额外支持 `{type}`(文件类型)和 `{localFolder:N}`(原文件所在文件夹层级)。
+
+### 示例
+
+- 文件名模板:`{Y}/{m}/{md5}.{ext}` → 上传后路径为 `2024/01/abc123def456.jpg`
+- 路径模板:`images/{type}/{Y}{m}{d}/{md5-16}.{ext}` → 按类型和日期分目录存储
+
+
+修改文件命名模板后,仅对新上传的文件生效。已上传的文件不会自动重命名。
+
diff --git a/content/docs/use/friends.mdx b/content/docs/use/friends.mdx
new file mode 100644
index 00000000..3d4a101b
--- /dev/null
+++ b/content/docs/use/friends.mdx
@@ -0,0 +1,99 @@
+---
+title: 友链管理
+description: 管理友情链接、审核申请、配置友链申请规则与头像转内链
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+友情链接(友链)是博客之间互相推荐的方式。Mix Space 支持完整的友链管理流程:添加、审核、健康检查、自动头像转内链。
+
+## 管理友链
+
+登录后台,进入「友链」页面。你可以:
+
+| 操作 | 说明 |
+|------|------|
+| **新增友链** | 点击右上角「+」,填写友链信息后保存 |
+| **编辑友链** | 点击友链条目进入编辑 |
+| **删除友链** | 删除不再需要的友链 |
+| **审核友链申请** | 在「审核中」标签页查看并审批申请 |
+
+### 友链状态
+
+| 状态 | 说明 |
+|------|------|
+| 已通过 | 正常展示在友链列表中 |
+| 审核中 | 等待站长审批的友链申请 |
+| 已过期 | 友链已过期 |
+| 已屏蔽 | 被手动屏蔽的友链 |
+| 已拒绝 | 审核未通过的友链 |
+
+### 友链类型
+
+| 类型 | 说明 |
+|------|------|
+| **友链(Friend)** | 普通友情链接 |
+| **收藏(Collection)** | 收藏的站点链接 |
+
+## 友链申请
+
+如果开启了友链申请功能,访客可以通过前端页面提交友链申请。
+
+### 开启友链申请
+
+进入后台「设定 → 友链设定」,打开「允许申请友链」开关。
+
+### 申请流程
+
+
+
+### 访客提交申请
+
+访客在前端友链页面填写站点名称、URL、头像、描述和邮箱(可选),提交申请。
+
+
+
+### 站长收到通知
+
+系统会通过邮件(如已配置)通知站长有新的友链申请。
+
+
+
+### 站长审批
+
+在后台「友链」页面的「审核中」标签查看申请:
+- 点击「通过」审批友链
+- 点击「拒绝」可填写拒绝理由,系统会通过邮件发送给申请者
+
+
+
+
+审核通过后,系统会自动通过邮件通知申请者(前提是申请者填写了邮箱且邮件服务已配置)。
+
+
+## 友链配置项
+
+进入后台「设定 → 友链设定」:
+
+| 配置项 | 说明 |
+|--------|------|
+| **允许申请友链** | 开启后前端展示友链申请入口 |
+| **允许子路径友链** | 允许申请子路径形式的友链(如 `example.com/blog`) |
+| **友链头像转内链** | 审核通过后自动下载友链头像到本地,避免外部头像加载失败 |
+
+### 头像转内链
+
+打开「友链头像转内链」后,当友链审核通过时,系统会自动下载该友链的头像文件并存储到本地。这样即使原始头像链接失效,你的友链页面仍然可以正常显示头像。
+
+
+头像转内链仅支持常见图片格式(JPEG、PNG、WebP、GIF 等),其他格式的头像不会被转换。
+
+
+## 友链健康检查
+
+在后台友链页面,点击「健康检查」按钮,系统会批量检测所有已通过友链的可达性。不可达的友链会被标记,方便你及时清理失效链接。
+
+## 头像批量迁移
+
+如果你在后期才开启头像转内链功能,已有友链的头像仍然是外部链接。在友链页面点击「迁移头像」按钮,可以批量将所有已通过友链的外部头像下载到本地。
diff --git a/content/docs/use/index.mdx b/content/docs/use/index.mdx
new file mode 100644
index 00000000..4cb637ed
--- /dev/null
+++ b/content/docs/use/index.mdx
@@ -0,0 +1,146 @@
+---
+title: 使用指南
+description: 部署完成后,这篇指南帮助你日常使用 Mix Space
+---
+
+部署完成后,这篇指南帮助你日常使用 Mix Space。
+
+import { Card, Cards } from 'fumadocs-ui/components/card'
+import { Pencil, Sparkles, Cloud, Database, ArrowUp, HelpCircle, MessageSquare, Users, FileImage, Webhook, Mail, BookOpen, Rocket, Megaphone, BarChart3, Clock } from 'lucide-react'
+
+## 内容管理
+
+
+ }
+ href={'/docs/use/content'}
+ title="内容管理"
+ >
+ 文章、日记、页面的发布与管理,分类、专题与草稿
+
+ }
+ href={'/docs/use/writing'}
+ title="写作工作流"
+ >
+ 后台编辑器、Obsidian 插件、Markdown 导入导出
+
+ }
+ href={'/docs/use/comments'}
+ title="评论管理"
+ >
+ 评论审核、反垃圾、AI 审核、评论图片上传
+
+ }
+ href={'/docs/use/friends'}
+ title="友链管理"
+ >
+ 友链添加与审核、申请规则、头像转内链
+
+ }
+ href={'/docs/use/says'}
+ title="说说"
+ >
+ 发布短内容、碎片化想法与一句话动态
+
+ }
+ href={'/docs/use/projects'}
+ title="项目展示"
+ >
+ 管理和展示个人项目与作品集
+
+ }
+ href={'/docs/use/files'}
+ title="文件管理"
+ >
+ 图片、图标、文件的上传管理与自定义命名
+
+
+
+## AI 功能
+
+
+ }
+ href={'/docs/use/ai-features'}
+ title="AI 功能"
+ >
+ 摘要、精读、多语言翻译、写作助手、评论审核、AI Agent
+
+
+
+## 扩展与集成
+
+
+ }
+ href={'/docs/use/serverless'}
+ title="云函数与 Snippet"
+ >
+ 扩展 Mix Space 能力的云函数、自定义路由与数据接口
+
+ }
+ href={'/docs/use/webhook'}
+ title="Webhook 与事件通知"
+ >
+ 将内容事件推送到外部服务(Telegram、Slack 等)
+
+ }
+ href={'/docs/use/mail-subscribe'}
+ title="邮件与订阅"
+ >
+ 邮件服务配置、读者订阅推送、Bark 通知
+
+
+
+## 系统管理
+
+
+ }
+ href={'/docs/use/analytics'}
+ title="站点统计"
+ >
+ 访问量、流量来源、设备分布和热门路径
+
+ }
+ href={'/docs/use/cron-tasks'}
+ title="定时任务"
+ >
+ 系统定时清理、搜索引擎推送、索引重建
+
+ }
+ href={'/docs/use/backup-restore'}
+ title="备份与恢复"
+ >
+ 手动备份、自动备份到 S3、数据回滚
+
+ }
+ href={'/docs/use/update'}
+ title="版本更新"
+ >
+ Docker 与源码部署的更新方式、大版本升级指引
+
+
+
+## 常见问题
+
+
+ }
+ href={'/docs/use/faq'}
+ title="常见问题"
+ >
+ 部署、内容、存储、邮件、数据库等常见疑问
+
+
diff --git a/content/docs/use/mail-subscribe.mdx b/content/docs/use/mail-subscribe.mdx
new file mode 100644
index 00000000..34dd5d4b
--- /dev/null
+++ b/content/docs/use/mail-subscribe.mdx
@@ -0,0 +1,127 @@
+---
+title: 邮件与订阅
+description: 配置邮件服务、开启邮件通知与读者订阅推送
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 支持邮件通知和读者订阅功能。配置邮件服务后,系统可以在友链申请、评论通知等场景发送邮件,读者也可以订阅你的内容更新。
+
+## 邮件服务配置
+
+### 前置条件
+
+你需要一个邮件发送服务。Mix Space 支持两种邮件服务:
+
+| 服务 | 说明 |
+|------|------|
+| **SMTP** | 传统 SMTP 邮件发送,适用于大多数邮件服务商(Gmail、QQ 邮箱、阿里企业邮等) |
+| **Resend** | 现代邮件 API 服务,配置简单,适合开发者 |
+
+### 配置步骤
+
+
+
+### 进入邮件设置
+
+登录后台,前往「设定 → 邮件通知设置」。
+
+
+
+### 开启邮件提醒
+
+打开「开启邮箱提醒」开关。
+
+
+
+### 选择邮件服务
+
+在「邮件服务」下拉框中选择 SMTP 或 Resend。
+
+
+
+### 填写配置
+
+**SMTP 方式:**
+
+| 字段 | 说明 |
+|------|------|
+| SMTP 用户名 | 邮箱账号 |
+| SMTP 密码 | 邮箱密码或应用专用密码 |
+| SMTP 主机 | SMTP 服务器地址(如 `smtp.gmail.com`) |
+| SMTP 端口 | 端口号(如 `465`) |
+| 使用 SSL/TLS | 是否启用加密连接 |
+| 发件邮箱地址 | 发件人邮箱,不填则使用 SMTP 用户名 |
+
+**Resend 方式:**
+
+| 字段 | 说明 |
+|------|------|
+| Resend API Key | 在 [resend.com](https://resend.com) 获取的 API 密钥 |
+| 发件邮箱地址 | Resend 中验证的发件域名邮箱(必填) |
+
+
+
+
+### 高级设置(可选)
+
+| 配置项 | 说明 |
+|--------|------|
+| **发送速率限制** | 每秒最大发送次数,默认 10 |
+| **发送失败重试次数** | 最大重试次数,默认 3 |
+
+
+
+
+
+使用 SMTP 时,部分邮件服务商(如 Gmail)需要开启「应用专用密码」或「不太安全的应用访问」才能正常发送。建议使用 Resend 等专业邮件 API 服务。
+
+
+## 读者订阅
+
+开启订阅功能后,读者可以通过邮箱订阅你的内容更新。当发布新文章或日记时,系统会自动向订阅者发送邮件通知。
+
+### 开启订阅
+
+进入后台「设定 → 特征开关设定」,打开「开启邮件推送订阅」开关。
+
+
+订阅功能依赖邮件服务。请先完成邮件服务配置,否则订阅邮件无法发送。
+
+
+### 订阅类型
+
+读者可以选择订阅以下内容类型:
+
+| 类型 | 说明 |
+|------|------|
+| **博文** | 新文章发布时通知 |
+| **手记** | 新日记发布时通知 |
+| **速记** | 新速记发布时通知 |
+| **说说** | 新说说发布时通知 |
+
+### 管理订阅者
+
+登录后台,进入「其他 → 订阅」页面,可以查看所有订阅者:
+
+- 查看订阅者的邮箱、订阅类型和订阅时间
+- 按类型筛选订阅者
+- 手动取消订阅者的订阅
+- 批量取消订阅
+
+### 取消订阅
+
+读者可以在收到的邮件中点击取消订阅链接,你也可以在后台管理页面手动为读者取消订阅。
+
+## 其他通知方式
+
+除了邮件,Mix Space 还支持 **Bark 推送通知**(iOS)。在「设定 → Bark 通知设定」中配置:
+
+| 配置项 | 说明 |
+|--------|------|
+| **开启 Bark 通知** | 启用 Bark 推送 |
+| **设备 Key** | Bark App 中的设备推送 Key |
+| **服务器 URL** | 自定义 Bark 服务器地址,不填则使用默认 `https://day.app` |
+| **开启评论通知** | 收到新评论时推送 |
+| **开启请求被限流时通知** | 可以在一定程度上预警被攻击 |
diff --git a/content/docs/use/meta.json b/content/docs/use/meta.json
new file mode 100644
index 00000000..ddbea9ed
--- /dev/null
+++ b/content/docs/use/meta.json
@@ -0,0 +1,25 @@
+{
+ "title": "使用",
+ "description": "日常使用 Mix Space",
+ "icon": "BookOpenCheck",
+ "root": true,
+ "pages": [
+ "index",
+ "content",
+ "writing",
+ "comments",
+ "friends",
+ "says",
+ "projects",
+ "files",
+ "ai-features",
+ "serverless",
+ "webhook",
+ "mail-subscribe",
+ "analytics",
+ "cron-tasks",
+ "backup-restore",
+ "update",
+ "faq"
+ ]
+}
diff --git a/content/docs/use/projects.mdx b/content/docs/use/projects.mdx
new file mode 100644
index 00000000..df74aecc
--- /dev/null
+++ b/content/docs/use/projects.mdx
@@ -0,0 +1,45 @@
+---
+title: 项目展示
+description: 管理和展示你的个人项目与作品集
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+Mix Space 内置了项目展示功能,你可以在后台管理自己的项目信息,前端主题会将这些项目以卡片等形式展示出来。
+
+## 管理项目
+
+登录后台,进入「项目管理」页面。
+
+### 添加项目
+
+点击右上角「+」,填写项目信息:
+
+| 字段 | 说明 |
+|------|------|
+| **名称** | 项目名称(必填,唯一) |
+| **描述** | 项目简介(必填) |
+| **详情** | 项目的详细介绍(支持 Markdown) |
+| **预览地址** | 项目在线预览 URL |
+| **文档地址** | 项目文档 URL |
+| **项目地址** | 项目源码仓库 URL |
+| **头像** | 项目图标或 Logo URL |
+| **截图** | 项目截图 URL 列表 |
+
+### 编辑和删除
+
+在项目列表中可以编辑已有项目或删除不再需要项目。
+
+
+所有 URL 字段都需要填写完整的 HTTP/HTTPS 地址。
+
+
+## 前端展示
+
+项目数据通过 API 提供给前端主题。不同主题的展示方式可能不同,常见的展示形式包括:
+
+- 项目卡片网格
+- 带截图的项目详情页
+- 按时间排列的项目列表
+
+具体展示效果取决于你使用的前端主题。
diff --git a/content/docs/use/says.mdx b/content/docs/use/says.mdx
new file mode 100644
index 00000000..7270983f
--- /dev/null
+++ b/content/docs/use/says.mdx
@@ -0,0 +1,43 @@
+---
+title: 说说管理
+description: 发布和管理短内容「说说」,记录碎片化的想法
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+
+「说说」是 Mix Space 中一种轻量级的内容类型,适合发布碎片化的想法、一句话感悟、状态更新等短内容。类似微博或 Twitter 的一条推文。
+
+## 管理说说
+
+登录后台,进入「说说」页面。
+
+### 发布说说
+
+1. 点击右上角「+」新建
+2. 填写以下字段:
+
+| 字段 | 说明 |
+|------|------|
+| **内容** | 说说正文(必填) |
+| **来源** | 发布来源(如「网页」「iPhone」) |
+| **作者** | 引用他人的话时填写原作者 |
+
+3. 点击保存即可发布
+
+### 编辑和删除
+
+在说说列表中,点击条目可以编辑内容,点击删除按钮可以移除说说。
+
+
+说说内容会实时推送到前端主题。如果你的主题支持说说模块,说说会以时间线的形式展示。
+
+
+## 随机说说 API
+
+系统提供了一条随机说说的 API 接口,前端主题可以使用这个接口在页面中随机展示一条说说,增加页面的趣味性。
+
+## 与其他功能的联动
+
+- **订阅推送**:如果开启了读者订阅,新说说发布时可以通知订阅者
+- **Webhook**:说说创建、更新、删除都会触发对应的 Webhook 事件
+- **实时推送**:说说发布后通过 WebSocket 实时推送到在线用户
diff --git a/content/docs/use/serverless.mdx b/content/docs/use/serverless.mdx
new file mode 100644
index 00000000..da1c9831
--- /dev/null
+++ b/content/docs/use/serverless.mdx
@@ -0,0 +1,142 @@
+---
+title: 云函数与 Snippet
+description: 使用云函数和自定义 Snippet 扩展 Mix Space 的能力——数据接口、自定义路由、JS/CSS 注入
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+import { ToGithub } from '@/app/components/ToGithub'
+
+Snippet 是 Mix Space 的扩展机制。每个 Snippet 是一段可配置的代码片段,可以为你的站点添加自定义数据接口、动态路由、前端脚本注入等能力。
+
+## 功能总览
+
+| 类型 | 说明 | 典型用途 |
+|------|------|----------|
+| **JSON / JSON5** | 结构化数据片段 | 配置数据、映射表 |
+| **Text** | 纯文本片段 | 公告、自定义 HTML |
+| **YAML** | YAML 数据片段 | 结构化配置 |
+| **Function** | 可执行函数 | 云函数 API、自定义路由 |
+
+
+Function 类型的 Snippet 就是你常听到的「云函数」。它是 Snippet 系统的一个子集,拥有最强大的扩展能力。
+
+
+## 管理云函数 / Snippet
+
+登录后台,进入「其他 → 云函数」页面。
+
+### 导入社区云函数
+
+
+
+### 点击「下载拓展包」
+
+在页面右上方点击「下载拓展包」按钮,弹出社区云函数列表。
+
+
+
+### 选择并导入
+
+在弹窗中找到对应主题的云函数代码,点击「导入」。
+
+
+
+### 确认启用
+
+导入后在管理页面确认 Snippet 已启用。Function 类型的 Snippet 需要手动开启「启用」开关。
+
+
+
+社区收录的云函数 Snippets 可以在 GitHub 查看:
+
+
+
+### 手动创建 Snippet
+
+1. 点击右上角「+」新建
+2. 填写以下信息:
+
+| 字段 | 说明 |
+|------|------|
+| **名称** | Snippet 名称(英文、数字、下划线,不超过 30 字符) |
+| **类型** | JSON / JSON5 / Text / YAML / Function |
+| **分组** | 用于组织 Snippet(Reference 字段) |
+| **内容** | Snippet 的实际代码 |
+| **备注** | 可选,备注说明 |
+| **私有** | 勾选后仅管理员可访问 |
+
+Function 类型额外支持:
+
+| 字段 | 说明 |
+|------|------|
+| **自定义路径** | 绑定一个 URL 路径,如 `my-api` → `/s/my-api` |
+| **HTTP 方法** | GET / POST / PUT / DELETE / PATCH / ALL |
+| **启用** | 是否启用此函数 |
+| **密钥** | 加密的配置项(如 API Key),存储时自动加密 |
+
+### 分组管理
+
+Snippet 按分组(Reference)组织。管理页面左侧显示分组列表,点击分组展开查看其中的 Snippet。你可以:
+- 展开折叠分组
+- 按 Reference 筛选
+- 查看每个分组的 Snippet 数量
+
+## Function 类型(云函数)
+
+Function 类型是最强大的 Snippet,它是一段可以在服务器端执行的 JavaScript 函数。
+
+### 自定义路由
+
+设置「自定义路径」后,你可以通过 `/s/{自定义路径}` 访问此函数的执行结果。例如:
+
+- 自定义路径 `bili-followings` → 访问 `/s/bili-followings` 获取哔哩哔哩关注列表
+- 自定义路径 `bangumi` → 访问 `/s/bangumi` 获取追番数据
+
+函数支持指定 HTTP 方法(GET、POST 等),也可以选择 ALL 匹配所有方法。
+
+
+Function 类型 Snippet 有请求限流(每 5 秒 100 次),高频调用场景请注意缓存。
+
+
+### 函数日志
+
+Function 类型 Snippet 的执行日志可以在管理页面查看。点击「日志」按钮可以查看函数的运行输出,方便调试。
+
+### 安装依赖
+
+Function 类型支持安装 npm 依赖包。在管理页面中:
+- 点击「安装依赖」按钮添加需要的 npm 包
+- 点击「更新依赖」更新已安装的包
+
+### 密钥管理
+
+函数中可能需要用到 API Key 等敏感信息。使用「密钥」字段存储,系统会自动加密。在函数代码中可以通过注入的上下文访问。
+
+## 数据类型 Snippet 的访问方式
+
+非 Function 类型的 Snippet 可以通过以下方式访问:
+
+| 访问方式 | URL 格式 |
+|----------|----------|
+| 按名称和分组 | `/api/v2/snippets/{reference}/{name}` |
+| 按自定义路径 | `/s/{customPath}`(需要设置自定义路径) |
+
+- **公开(Public)** Snippet 所有人可访问
+- **私有(Private)** Snippet 仅管理员登录后可访问
+
+## 前端主题集成
+
+许多前端主题依赖 Snippet 提供数据。常见用法:
+
+- Shiro 主题使用云函数提供哔哩哔哩追番、最近听歌等模块
+- 自定义 CSS/JS 注入到前端页面
+- 提供导航栏配置、社交链接等结构化数据
+
+具体需要导入哪些 Snippet,请参考你使用的前端主题文档。
+
+## 开发者文档
+
+如需编写自定义 Function 类型 Snippet,请参考完整的开发者文档:
+
+
diff --git a/content/docs/use/update.mdx b/content/docs/use/update.mdx
new file mode 100644
index 00000000..63823481
--- /dev/null
+++ b/content/docs/use/update.mdx
@@ -0,0 +1,71 @@
+---
+title: 版本更新
+description: 更新你的 Mix Space 后端与前端
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Card, Cards } from 'fumadocs-ui/components/card'
+import { FileText, AlertTriangle } from 'lucide-react'
+
+Mix Space 分为前端和后端两个部分,因此更新的时候二者也需要分开更新。
+
+## 小版本更新(常规)
+
+根据部署方式的不同,更新方式也有所不同。
+
+### Docker 部署
+
+进入 core 所在文件夹,执行:
+
+```bash
+docker compose pull && docker compose up -d
+```
+
+### 源码部署
+
+进入克隆 core 的文件夹,执行 `git pull origin master` 拉取新版本源码,随后正常进行构建:
+
+```bash
+pnpm i
+pnpm build
+pnpm bundle
+```
+
+随后进入 `./apps/core`,执行以下命令启动服务:
+
+```bash
+pm2 start ecosystem.config.js
+```
+
+## 大版本更新
+
+
+v12 是一次重大升级,数据库从 MongoDB 迁移到 PostgreSQL。不能简单 `docker compose pull` 升级,请务必阅读专用升级指南。
+
+
+
+ }
+ />
+
+
+## 前端更新
+
+请根据自己所部署的主题跳转到对应的更新部分完成更新。
+
+
+ }
+ target="_blank"
+ />
+ }
+ target="_blank"
+ />
+
diff --git a/content/docs/use/webhook.mdx b/content/docs/use/webhook.mdx
new file mode 100644
index 00000000..ce564e5c
--- /dev/null
+++ b/content/docs/use/webhook.mdx
@@ -0,0 +1,106 @@
+---
+title: Webhook 与事件通知
+description: 配置 Webhook 将 Mix Space 的内容事件推送到外部服务,实现自动化集成
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Webhook 可以将 Mix Space 中发生的事件(如发布文章、收到评论等)实时推送到你指定的外部服务。常见的用途包括:通知到 Telegram/微信、触发 CI/CD 构建、同步到第三方平台等。
+
+## 创建 Webhook
+
+
+
+### 进入 Webhook 管理页面
+
+登录后台,进入「其他 → Webhook」。
+
+
+
+### 点击新建
+
+填写以下信息:
+
+| 字段 | 说明 |
+|------|------|
+| **Payload URL** | 接收推送的 URL 地址 |
+| **Secret** | 签名密钥,用于验证推送来源 |
+| **事件** | 勾选你关注的事件类型 |
+| **启用** | 是否启用此 Webhook |
+| **作用域** | 选择接收推送的范围(访客/管理员/系统) |
+
+
+
+
+### 保存并测试
+
+保存后,当勾选的事件发生时,系统会向 Payload URL 发送 HTTP POST 请求。
+
+
+
+## 支持的事件
+
+| 事件 | 说明 |
+|------|------|
+| `POST_CREATE` | 文章创建 |
+| `POST_UPDATE` | 文章更新 |
+| `POST_DELETE` | 文章删除 |
+| `NOTE_CREATE` | 日记创建 |
+| `NOTE_UPDATE` | 日记更新 |
+| `NOTE_DELETE` | 日记删除 |
+| `PAGE_CREATE` | 页面创建 |
+| `PAGE_UPDATE` | 页面更新 |
+| `PAGE_DELETE` | 页面删除 |
+| `COMMENT_CREATE` | 评论创建 |
+| `COMMENT_DELETE` | 评论删除 |
+| `COMMENT_UPDATE` | 评论更新 |
+| `SAY_CREATE` | 说说创建 |
+| `SAY_UPDATE` | 说说更新 |
+| `SAY_DELETE` | 说说删除 |
+| `CATEGORY_CREATE` | 分类创建 |
+| `CATEGORY_UPDATE` | 分类更新 |
+| `CATEGORY_DELETE` | 分类删除 |
+| `TOPIC_CREATE` | 专题创建 |
+| `TOPIC_UPDATE` | 专题更新 |
+| `TOPIC_DELETE` | 专题删除 |
+| `LINK_APPLY` | 友链申请 |
+| `RECENTLY_CREATE` | 速记创建 |
+| `RECENTLY_UPDATE` | 速记更新 |
+| `RECENTLY_DELETE` | 速记删除 |
+| `TRANSLATION_CREATE` | AI 翻译创建 |
+| `TRANSLATION_UPDATE` | AI 翻译更新 |
+| `INSIGHTS_CREATE` | AI 精读创建 |
+| `INSIGHTS_UPDATE` | AI 精读更新 |
+
+## 作用域说明
+
+Webhook 可以选择不同的推送作用域:
+
+| 作用域 | 说明 |
+|--------|------|
+| **访客** | 仅推送面向访客的事件 |
+| **管理员** | 仅推送面向管理员的事件 |
+| **系统** | 仅推送系统级别的事件 |
+| **全选** | 推送所有事件 |
+
+
+合理选择作用域可以减少不必要的推送请求。例如,如果你想将评论通知推送到 Telegram,选择「访客」作用域即可。
+
+
+## 管理推送记录
+
+在 Webhook 列表中点击某个 Webhook,可以查看该 Webhook 的推送记录:
+
+- **推送状态**:成功或失败
+- **HTTP 状态码**:目标服务返回的状态码
+- **请求头和请求体**:完整的推送内容
+- **响应内容**:目标服务的返回数据
+
+### 重试推送
+
+对于推送失败的记录,可以点击「重新推送」按钮手动重试。
+
+### 清除记录
+
+点击「清除记录」可以删除该 Webhook 的所有历史推送记录。
diff --git a/content/docs/use/writing.mdx b/content/docs/use/writing.mdx
new file mode 100644
index 00000000..7427b4e7
--- /dev/null
+++ b/content/docs/use/writing.mdx
@@ -0,0 +1,102 @@
+---
+title: 写作工作流
+description: 在 Mix Space 中高效写作的多种方式
+---
+
+import { Callout } from 'fumadocs-ui/components/callout'
+import { Step, Steps } from 'fumadocs-ui/components/steps'
+
+Mix Space 提供了多种写作方式,无论你习惯在浏览器中编辑,还是偏爱本地 Markdown 编辑器,都能找到适合你的工作流。
+
+## 后台编辑器
+
+登录后台后,进入「文章」或「日记」页面,点击新建即可开始写作。
+
+### 编辑器功能简介
+
+- **Markdown 支持**:直接输入 Markdown 语法,实时预览渲染效果
+- **Lexical 富文本**:提供可视化的富文本编辑体验,支持拖拽排版
+- **定时发布**:设定未来的发布时间,到点自动上线
+- **密码保护**:为单篇文章设置访问密码,适合私密内容
+
+
+后台地址通常为 `你的域名/proxy/qaqdmin`,部署时可在配置中修改。
+
+
+## Obsidian 插件
+
+[Obsidian Mix Space Plugin](https://github.com/mx-space/obsidian-mixspace-plugin) 是一个 Obsidian 插件,可以将你的 Obsidian 笔记库直接同步到 Mix Space。
+
+### 功能特性
+
+- 发布/更新内容到 Mix Space(支持 Note 和 Post)
+- 自动识别内容类型
+- 反向链接转换(`[[Obsidian 链接]]` → Mix Space URL)
+- Frontmatter 自动补全
+- 多环境配置(Profile)
+- AI 生成标题和 slug
+
+### 安装步骤
+
+
+
+### 下载插件
+
+前往 [GitHub Releases](https://github.com/mx-space/obsidian-mixspace-plugin/releases) 下载最新版本的 `obsidian-mixspace-plugin.zip`。
+
+
+
+### 安装到 Obsidian
+
+在 Obsidian 中打开「设置 → 第三方插件」,关闭安全模式后点击「浏览」旁的「加载已解压的插件」,选择解压后的插件文件夹。
+
+
+
+### 配置 API
+
+在插件设置中填入:
+- **API Endpoint**:你的 Mix Space 地址,如 `https://example.com/api/v2`
+- **Token**:在 Mix Space 后台「设定 → 安全 → API Token」中生成
+
+
+
+### 发布内容
+
+在 Obsidian 中打开一篇笔记,按 `Ctrl/Cmd + P` 打开命令面板,搜索「Mix Space」即可看到发布/更新命令。
+
+
+
+## Markdown 导入导出
+
+Mix Space 后台支持 Markdown 文件的批量导入与导出,方便你在不同平台之间迁移内容。
+
+### 导入 Markdown
+
+
+
+登录后台,进入「文章」页面。
+
+
+点击右上角「导入」按钮,选择本地 Markdown 文件。
+
+
+系统会自动解析 Frontmatter(标题、标签、分类等),确认后完成导入。
+
+
+
+### 导出 Markdown
+
+在后台文章列表中,选择需要导出的文章,点击「导出」即可下载包含完整 Frontmatter 的 Markdown 文件。
+
+
+导入时如果文章已存在相同 slug,系统会提示是否覆盖,请谨慎操作。
+
+
+## 写作建议
+
+为了让你的内容更容易被检索和阅读,建议养成以下习惯:
+
+- **使用标签**:为每篇文章添加 2–5 个标签,便于分类和关联推荐
+- **设置分类**:合理划分文章分类,让读者快速定位感兴趣的主题
+- **撰写摘要**:在 Frontmatter 或摘要栏中填写内容概要,有利于 SEO 和列表展示
+- **规范 slug**:使用英文小写和连字符作为文章链接,避免中文 URL
diff --git a/global.d.ts b/global.d.ts
new file mode 100644
index 00000000..31f07ea5
--- /dev/null
+++ b/global.d.ts
@@ -0,0 +1,4 @@
+declare module '*.css' {
+ const content: string;
+ export default content;
+}
diff --git a/next.config.mjs b/next.config.mjs
index 8019e97d..aea7a02e 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -10,6 +10,36 @@ const config = {
domains: ['github.com', 'avatars.githubusercontent.com', 'pan.vinua.cn'],
unoptimized: true
},
+ async redirects() {
+ return [
+ // Old section redirects — keep for backward compat (bookmarks, external links)
+ // Dev mode: handled by these redirects. Production: handled by static HTML in public/docs/.
+ { source: '/docs/core', destination: '/docs/getting-started', permanent: true },
+ { source: '/docs/core/index', destination: '/docs/getting-started', permanent: true },
+ { source: '/docs/core/features', destination: '/docs/getting-started', permanent: true },
+ { source: '/docs/core/docker', destination: '/docs/deploy/docker', permanent: true },
+ { source: '/docs/core/bash', destination: '/docs/deploy/one-script', permanent: true },
+ { source: '/docs/core/advanced', destination: '/docs/deploy/source', permanent: true },
+ { source: '/docs/core/extra', destination: '/docs/deploy/external-services', permanent: true },
+ { source: '/docs/core/community', destination: '/docs/deploy/community', permanent: true },
+ { source: '/docs/usage', destination: '/docs/use', permanent: true },
+ { source: '/docs/usage/index', destination: '/docs/use', permanent: true },
+ { source: '/docs/usage/serverless', destination: '/docs/use/serverless', permanent: true },
+ { source: '/docs/usage/obsidian', destination: '/docs/use/writing', permanent: true },
+ { source: '/docs/usage/backup', destination: '/docs/use/backup-restore', permanent: true },
+ { source: '/docs/usage/update', destination: '/docs/use/update', permanent: true },
+ { source: '/docs/usage/search', destination: '/docs/configure/algolia', permanent: true },
+ { source: '/docs/usage/security', destination: '/docs/configure/encryption', permanent: true },
+ { source: '/docs/usage/oauth', destination: '/docs/configure/oauth', permanent: true },
+ { source: '/docs/usage/xlog', destination: '/docs/use/writing', permanent: true },
+ { source: '/docs/development', destination: '/docs/develop', permanent: true },
+ { source: '/docs/development/index', destination: '/docs/develop', permanent: true },
+ { source: '/docs/development/admin', destination: '/docs/develop/admin', permanent: true },
+ { source: '/docs/development/frontend', destination: '/docs/develop/frontend', permanent: true },
+ { source: '/docs/document', destination: '/docs/develop/contribute', permanent: true },
+ { source: '/docs/document/index', destination: '/docs/develop/contribute', permanent: true },
+ ]
+ },
async rewrites() {
return [
{
diff --git a/package.json b/package.json
index d871824a..c2d4d593 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
"prettier": "^3.7.4",
"tailwindcss": "^4.1.18",
"tsx": "^4.21.0",
- "typescript": "^5.9.3"
+ "typescript": "^6.0.3"
},
"config": {
"commitizen": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 41739138..7559d8da 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -22,13 +22,13 @@ importers:
version: 2.1.1
commitizen:
specifier: ^4.3.1
- version: 4.3.1(@types/node@22.13.11)(typescript@5.9.3)
+ version: 4.3.1(@types/node@22.13.11)(typescript@6.0.3)
copy-to-clipboard:
specifier: ^3.3.3
version: 3.3.3
cz-conventional-changelog:
specifier: ^3.3.0
- version: 3.3.0(@types/node@22.13.11)(typescript@5.9.3)
+ version: 3.3.0(@types/node@22.13.11)(typescript@6.0.3)
fast-glob:
specifier: ^3.3.3
version: 3.3.3
@@ -37,16 +37,16 @@ importers:
version: 12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
fumadocs-core:
specifier: 15.1.2
- version: 15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ version: 15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
fumadocs-mdx:
specifier: 11.5.7
- version: 11.5.7(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))
+ version: 11.5.7(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))
fumadocs-typescript:
specifier: ^5.0.0
- version: 5.0.0(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18))(typescript@5.9.3)
+ version: 5.0.0(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18))(typescript@6.0.3)
fumadocs-ui:
specifier: 15.1.2
- version: 15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)
+ version: 15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)
lucide-react:
specifier: ^0.562.0
version: 0.562.0(react@19.2.3)
@@ -106,8 +106,8 @@ importers:
specifier: ^4.21.0
version: 4.21.0
typescript:
- specifier: ^5.9.3
- version: 5.9.3
+ specifier: ^6.0.3
+ version: 6.0.3
packages:
@@ -512,67 +512,79 @@ packages:
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-arm@1.0.5':
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.0.4':
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linux-x64@1.0.4':
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@img/sharp-linux-arm64@0.33.5':
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-arm@0.33.5':
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-s390x@0.33.5':
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@img/sharp-linux-x64@0.33.5':
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.33.5':
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@img/sharp-linuxmusl-x64@0.33.5':
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@img/sharp-wasm32@0.33.5':
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
@@ -638,24 +650,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@next/swc-linux-arm64-musl@15.2.3':
resolution: {integrity: sha512-2gAPA7P652D3HzR4cLyAuVYwYqjG0mt/3pHSWTCyKZq/N/dJcUAEoNQMyUmwTZWCJRKofB+JPuDVP2aD8w2J6Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@next/swc-linux-x64-gnu@15.2.3':
resolution: {integrity: sha512-ODSKvrdMgAJOVU4qElflYy1KSZRM3M45JVbeZu42TINCMG3anp7YCBn80RkISV6bhzKwcUqLBAmOiWkaGtBA9w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@next/swc-linux-x64-musl@15.2.3':
resolution: {integrity: sha512-ZR9kLwCWrlYxwEoytqPi1jhPd1TlsSJWAc+H/CJHmHkf2nD92MQpSRIURR1iNgA/kuFSdxB8xIPt4p/T78kwsg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@next/swc-win32-arm64-msvc@15.2.3':
resolution: {integrity: sha512-+G2FrDcfm2YDbhDiObDU/qPriWeiz/9cRR0yMWJeTLGGX6/x8oryO3tt7HhodA1vZ8r2ddJPCjtLcpaVl7TE2Q==}
@@ -669,10 +685,6 @@ packages:
cpu: [x64]
os: [win32]
- '@noble/hashes@1.8.0':
- resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
- engines: {node: ^14.21.3 || >=16}
-
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -685,16 +697,10 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
- '@orama/cuid2@2.2.3':
- resolution: {integrity: sha512-Lcak3chblMejdlSHgYU2lS2cdOhDpU6vkfIJH4m+YKvqQyLqs1bB8+w6NT1MG5bO12NUK2GFc34Mn2xshMIQ1g==}
-
'@orama/orama@3.1.18':
resolution: {integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==}
engines: {node: '>= 20.0.0'}
- '@oramacloud/client@2.1.4':
- resolution: {integrity: sha512-uNPFs4wq/iOPbggCwTkVNbIr64Vfd7ZS/h+cricXVnzXWocjDTfJ3wLL4lr0qiSu41g8z+eCAGBqJ30RO2O4AA==}
-
'@radix-ui/number@1.1.1':
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
@@ -1143,24 +1149,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
@@ -1304,12 +1314,14 @@ packages:
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
autocorrect-node-linux-x64-musl@2.14.0:
resolution: {integrity: sha512-3LifiLG61VIXBrOITpD/REcg/ZEUuLz/P2XUWMCfGqhzoUb8oFgM3o0A6extvIH2NefiHMndB9kNbfQjXCl3zA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
autocorrect-node-win32-x64-msvc@2.14.0:
resolution: {integrity: sha512-OM6TeGUW0+4R9KtUYTYNEwlInd+b2kumw/B1HCbCzb1F7HpfaNxnZiMk1li0bdPPBDzD5YuzwM30VJZMCWIi5A==}
@@ -2012,24 +2024,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-win32-arm64-msvc@1.30.2:
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
@@ -2736,8 +2752,8 @@ packages:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
- typescript@5.9.3:
- resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ typescript@6.0.3:
+ resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
engines: {node: '>=14.17'}
hasBin: true
@@ -2874,15 +2890,15 @@ snapshots:
'@commitlint/execute-rule@20.0.0':
optional: true
- '@commitlint/load@20.0.0(@types/node@22.13.11)(typescript@5.9.3)':
+ '@commitlint/load@20.0.0(@types/node@22.13.11)(typescript@6.0.3)':
dependencies:
'@commitlint/config-validator': 20.0.0
'@commitlint/execute-rule': 20.0.0
'@commitlint/resolve-extends': 20.0.0
'@commitlint/types': 20.0.0
chalk: 5.6.2
- cosmiconfig: 9.0.0(typescript@5.9.3)
- cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.11)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3)
+ cosmiconfig: 9.0.0(typescript@6.0.3)
+ cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.11)(cosmiconfig@9.0.0(typescript@6.0.3))(typescript@6.0.3)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -3255,9 +3271,6 @@ snapshots:
'@next/swc-win32-x64-msvc@15.2.3':
optional: true
- '@noble/hashes@1.8.0':
- optional: true
-
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -3270,20 +3283,8 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.19.1
- '@orama/cuid2@2.2.3':
- dependencies:
- '@noble/hashes': 1.8.0
- optional: true
-
'@orama/orama@3.1.18': {}
- '@oramacloud/client@2.1.4':
- dependencies:
- '@orama/cuid2': 2.2.3
- '@orama/orama': 3.1.18
- lodash: 4.17.21
- optional: true
-
'@radix-ui/number@1.1.1': {}
'@radix-ui/primitive@1.1.3': {}
@@ -4043,10 +4044,10 @@ snapshots:
commander@14.0.2: {}
- commitizen@4.3.1(@types/node@22.13.11)(typescript@5.9.3):
+ commitizen@4.3.1(@types/node@22.13.11)(typescript@6.0.3):
dependencies:
cachedir: 2.3.0
- cz-conventional-changelog: 3.3.0(@types/node@22.13.11)(typescript@5.9.3)
+ cz-conventional-changelog: 3.3.0(@types/node@22.13.11)(typescript@6.0.3)
dedent: 0.7.0
detect-indent: 6.1.0
find-node-modules: 2.1.3
@@ -4073,22 +4074,22 @@ snapshots:
dependencies:
toggle-selection: 1.0.6
- cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.11)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3):
+ cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.11)(cosmiconfig@9.0.0(typescript@6.0.3))(typescript@6.0.3):
dependencies:
'@types/node': 22.13.11
- cosmiconfig: 9.0.0(typescript@5.9.3)
+ cosmiconfig: 9.0.0(typescript@6.0.3)
jiti: 2.6.0
- typescript: 5.9.3
+ typescript: 6.0.3
optional: true
- cosmiconfig@9.0.0(typescript@5.9.3):
+ cosmiconfig@9.0.0(typescript@6.0.3):
dependencies:
env-paths: 2.2.1
import-fresh: 3.3.1
js-yaml: 4.1.0
parse-json: 5.2.0
optionalDependencies:
- typescript: 5.9.3
+ typescript: 6.0.3
optional: true
cross-spawn@7.0.6:
@@ -4101,16 +4102,16 @@ snapshots:
csstype@3.2.3: {}
- cz-conventional-changelog@3.3.0(@types/node@22.13.11)(typescript@5.9.3):
+ cz-conventional-changelog@3.3.0(@types/node@22.13.11)(typescript@6.0.3):
dependencies:
chalk: 2.4.2
- commitizen: 4.3.1(@types/node@22.13.11)(typescript@5.9.3)
+ commitizen: 4.3.1(@types/node@22.13.11)(typescript@6.0.3)
conventional-commit-types: 3.0.0
lodash.map: 4.6.0
longest: 2.0.1
word-wrap: 1.2.5
optionalDependencies:
- '@commitlint/load': 20.0.0(@types/node@22.13.11)(typescript@5.9.3)
+ '@commitlint/load': 20.0.0(@types/node@22.13.11)(typescript@6.0.3)
transitivePeerDependencies:
- '@types/node'
- typescript
@@ -4364,7 +4365,7 @@ snapshots:
fsevents@2.3.3:
optional: true
- fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
'@formatjs/intl-localematcher': 0.6.1
'@orama/orama': 3.1.18
@@ -4382,7 +4383,6 @@ snapshots:
shiki: 3.20.0
unist-util-visit: 5.0.0
optionalDependencies:
- '@oramacloud/client': 2.1.4
next: 15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
@@ -4390,7 +4390,7 @@ snapshots:
- '@types/react'
- supports-color
- fumadocs-mdx@11.5.7(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)):
+ fumadocs-mdx@11.5.7(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)):
dependencies:
'@mdx-js/mdx': 3.1.1
'@standard-schema/spec': 1.0.0
@@ -4399,7 +4399,7 @@ snapshots:
esbuild: 0.25.10
estree-util-value-to-estree: 3.4.0
fast-glob: 3.3.3
- fumadocs-core: 15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ fumadocs-core: 15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
gray-matter: 4.0.3
next: 15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
unist-util-visit: 5.0.0
@@ -4407,25 +4407,25 @@ snapshots:
transitivePeerDependencies:
- supports-color
- fumadocs-typescript@5.0.0(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18))(typescript@5.9.3):
+ fumadocs-typescript@5.0.0(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18))(typescript@6.0.3):
dependencies:
estree-util-value-to-estree: 3.5.0
- fumadocs-core: 15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ fumadocs-core: 15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
hast-util-to-estree: 3.1.3
hast-util-to-jsx-runtime: 2.3.6
remark: 15.0.1
remark-rehype: 11.1.2
tinyglobby: 0.2.15
ts-morph: 27.0.2
- typescript: 5.9.3
+ typescript: 6.0.3
unist-util-visit: 5.0.0
optionalDependencies:
'@types/react': 19.2.7
- fumadocs-ui: 15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)
+ fumadocs-ui: 15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)
transitivePeerDependencies:
- supports-color
- fumadocs-ui@15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18):
+ fumadocs-ui@15.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-core@15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18):
dependencies:
'@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -4437,7 +4437,7 @@ snapshots:
'@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
'@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
class-variance-authority: 0.7.1
- fumadocs-core: 15.1.2(@oramacloud/client@2.1.4)(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ fumadocs-core: 15.1.2(@types/react@19.2.7)(next@15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
lodash.merge: 4.6.2
lucide-react: 0.483.0(react@19.2.3)
next: 15.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -5753,7 +5753,7 @@ snapshots:
type-fest@0.21.3: {}
- typescript@5.9.3: {}
+ typescript@6.0.3: {}
undici-types@6.20.0: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 00000000..dbb26c82
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+allowBuilds:
+ esbuild: true
+ sharp: true
diff --git a/public/agent-skills/mix-space-development.md b/public/agent-skills/mix-space-development.md
new file mode 100644
index 00000000..5c9e9a06
--- /dev/null
+++ b/public/agent-skills/mix-space-development.md
@@ -0,0 +1,198 @@
+# Mix Space — Agent Skill: Mix Space Development
+
+## Description
+
+You are an expert developer for the Mix Space ecosystem. You help contributors write code for the backend (mx-core), admin dashboard (admin-vue3), and frontend themes.
+
+## When to Use
+
+Use this skill when the user asks about:
+- Developing new features for Mix Space backend
+- Creating or modifying admin dashboard pages
+- Building frontend themes for Mix Space
+- Writing tests for Mix Space
+- Understanding the codebase architecture
+- Contributing to Mix Space open source
+
+## Project Structure
+
+### Backend (mx-core)
+
+```
+mx-core/
+├── apps/core/
+│ ├── src/modules/ # 44+ business modules
+│ ├── src/processors/ # Infra (database, redis, gateway, task-queue)
+│ ├── src/common/ # Guards, Interceptors, Decorators, Filters
+│ ├── src/constants/ # Business events, cache keys, error codes
+│ ├── src/transformers/ # Response transforms (snake_case, pagination)
+│ └── test/ # Vitest tests
+├── packages/
+│ ├── api-client/ # @mx-space/api-client SDK
+│ └── webhook/ # @mx-space/webhook SDK
+└── docker-compose.yml
+```
+
+### Admin (admin-vue3)
+
+```
+admin-vue3/
+├── apps/admin/src/
+│ ├── api/ # API layer (ofetch wrapper)
+│ ├── views/ # Page views
+│ ├── components/ # Shared components
+│ ├── hooks/queries/ # TanStack Query hooks
+│ ├── stores/ # Pinia stores
+│ └── router/ # Route config
+└── packages/rich-react/ # React editor bridge
+```
+
+## Key Patterns
+
+### Backend Module Structure
+
+Every module follows NestJS conventions:
+
+```
+modules/example/
+├── example.module.ts # Module registration
+├── example.controller.ts # API endpoints
+├── example.service.ts # Business logic
+├── example.model.ts # Database model (Drizzle ORM)
+└── example.schema.ts # Zod validation schemas
+```
+
+### Key Decorators
+
+```typescript
+@ApiController() // Adds /api/v{version} prefix in production
+@Auth() // Requires admin authentication
+@HasAdminAccess() // Checks if request has admin access (optional auth)
+@Paginator // Wraps paginated response
+@HTTPDecorators.Bypass // Skip response transform
+@HTTPDecorators.Idempotence() // Deduplicate requests
+@IpLocation() // Extract IP geo info
+@Lang() // Get Accept-Language header
+@TranslateFields({...}) // Auto-translate specified fields
+```
+
+### Response Transform (ResponseInterceptor)
+
+- Array → `{ data: [...] }`
+- Object → returned as-is
+- `@Paginator` → `{ data: [...], pagination: {...} }`
+- All keys auto-converted to **snake_case**
+- `@Bypass` → skip transform
+
+### Config System
+
+Configuration is defined in `configs.schema.ts` using Zod with a DSL:
+
+```typescript
+export const MySchema = section('配置名称', {
+ enable: field.toggle(z.boolean().optional(), '开关名称'),
+ value: field.plain(z.string().optional(), '字段名称'),
+ items: field.array(z.array(z.string()).optional(), '列表名称'),
+ secret: field.password(z.string().optional(), '密钥'),
+ select: field.select(z.enum(['a', 'b']).optional(), '选择', [
+ { label: '选项A', value: 'a' },
+ { label: '选项B', value: 'b' },
+ ]),
+})
+```
+
+Register in `configSchemaMapping`.
+
+### Admin Frontend Patterns
+
+**API layer** (`api/xxx.ts`):
+```typescript
+export const xxxApi = {
+ getList: (params) => request.get('/xxx', { params }),
+ create: (data) => request.post('/xxx', data),
+}
+```
+
+**TanStack Query hooks** (`hooks/queries/use-xxx.ts`):
+```typescript
+export const useXxxList = (params) =>
+ useQuery({
+ queryKey: queryKeys.xxx.list(params),
+ queryFn: () => xxxApi.getList(params),
+ })
+```
+
+**Page view** (`views/xxx/index.tsx`): Vue 3 + TSX with Naive UI components.
+
+### CSS Conventions
+
+- **Colors**: MUST use `neutral` (never `gray`): `text-neutral-500`, `bg-neutral-800`
+- **Font sizes**: Standard Tailwind classes only, never arbitrary values
+- **Breakpoints**: `phone:` (≤768px), `tablet:` (≤1024px), `desktop:` (≥1024px)
+- **Path alias**: `~` → `./src`
+
+## Development Commands
+
+### Backend
+```bash
+pnpm dev # Dev server (port 2333)
+pnpm build # Compile TypeScript
+pnpm bundle # Production bundle (tsdown)
+pnpm test # Run tests (Vitest)
+pnpm test -- test/src/modules/xxx.spec.ts # Single test file
+pnpm lint # ESLint
+pnpm typecheck # TypeScript check
+```
+
+### Admin
+```bash
+pnpm dev # Dev server
+pnpm build # Production build
+pnpm lint # Oxlint
+pnpm typecheck # tsc --noEmit (NOT build)
+```
+
+## Adding a New Feature Checklist
+
+### Backend:
+1. Create module directory `modules/xxx/`
+2. Define Drizzle schema in model file
+3. Create controller with `@ApiController()`
+4. Implement service with business logic
+5. Add Zod validation schemas
+6. Register module in `app.module.ts`
+7. Add config fields if needed in `configs.schema.ts`
+8. Write tests in `test/src/modules/`
+
+### Admin:
+1. Add API functions in `api/xxx.ts`
+2. Add TanStack Query hooks in `hooks/queries/`
+3. Create page view in `views/xxx/`
+4. Register route in `router/route.tsx`
+5. Add config form fields if needed
+
+## Testing
+
+### Backend (Vitest + in-memory DB)
+```typescript
+const proxy = createE2EApp({
+ imports: [...],
+ controllers: [MyController],
+ providers: [...],
+ models: [MyModel],
+ pourData: async (modelMap) => { /* seed data */ }
+})
+```
+
+### Admin
+```bash
+npx tsc --noEmit # Type check only, do NOT use build
+```
+
+## Important Notes
+
+- Package manager: **pnpm** only (via Corepack)
+- API versioning: `/api/v2` prefix in production, none in dev
+- Path aliases: Backend `~` → `apps/core/src/`, Admin `~` → `apps/admin/src/`
+- The admin is Vue 3 but uses React for the rich editor (bridge pattern via `packages/rich-react/`)
+- All `@haklex/*` packages use pinned npm versions, NOT workspace links
diff --git a/public/agent-skills/mix-space-expert.md b/public/agent-skills/mix-space-expert.md
new file mode 100644
index 00000000..5d611689
--- /dev/null
+++ b/public/agent-skills/mix-space-expert.md
@@ -0,0 +1,88 @@
+# Mix Space — Agent Skill: Mix Space CMS Expert
+
+## Description
+
+You are an expert on Mix Space, an AI-powered headless CMS for personal blogs and content sites. You help users deploy, configure, use, and troubleshoot Mix Space and its ecosystem.
+
+## When to Use
+
+Use this skill when the user asks about:
+- Deploying or setting up Mix Space (Docker, source, reverse proxy)
+- Configuring Mix Space features (AI, SEO, OAuth, mail, comments, storage)
+- Using Mix Space admin dashboard (content management, AI features, webhooks)
+- Troubleshooting Mix Space errors
+- Developing for Mix Space (backend modules, admin views, frontend themes)
+- Migrating to Mix Space (from WordPress, from v11/MongoDB to v12/PostgreSQL)
+
+## Key Facts
+
+### Architecture
+- **Backend (Core)**: NestJS 11 + Fastify + PostgreSQL 16 + Redis 7
+- **Admin**: Vue 3 + Naive UI + TanStack Query (embedded in Core at `/proxy/qaqdmin`)
+- **Frontend Themes**: Next.js (Shiro, Yohaku), standalone deployments
+- **API prefix**: `/api/v2` in production, no prefix in dev (port 2333)
+
+### Content Types
+| Type | URL Format | Special Fields |
+|------|-----------|---------------|
+| Post | `/{category-slug}/{post-slug}` | Category, tags, pin, related posts, copyright |
+| Note | `/notes/{nid}` | Mood, weather, password, topic, location |
+| Page | `/{slug}` | Subtitle, order |
+| Say | Short-form content | Author, source |
+| Project | Portfolio items | Preview URL, screenshots, GitHub link |
+
+### AI Features (requires LLM provider config)
+- Summary: Auto-generate multi-language summaries
+- Insights: Deep reading companion (TL;DR, structure, Mermaid diagrams)
+- Translation: Markdown + Lexical dual strategy with glossary
+- Writer: Auto title/slug generation, bulk slug backfill
+- Comment Review: AI spam detection (binary/score modes)
+- Agent: In-editor AI chat
+- Task Queue: Unified batch/bulk task management
+
+### Response Format
+All API responses use snake_case. Arrays wrapped as `{ data: [...] }`, paginated as `{ data: [...], pagination: {...} }`.
+
+### Key Environment Variables
+| Variable | Required | Description |
+|----------|----------|-------------|
+| `JWT_SECRET` | Yes | 16-32 char string for JWT signing |
+| `SNOWFLAKE_WORKER_ID` | Yes | Unique worker ID (1 for single instance) |
+| `ALLOWED_ORIGINS` | Recommended | Comma-separated allowed domains |
+| `PG_HOST` / `PG_URL` | Yes* | PostgreSQL connection |
+| `REDIS_HOST` | Yes* | Redis connection |
+
+*Handled automatically in Docker Compose setup.
+
+### Deployment
+Recommended: Docker Compose (includes PostgreSQL + Redis + app).
+
+```bash
+git clone https://github.com/mx-space/core.git --depth=1
+cd core
+# Edit JWT_SECRET and ALLOWED_ORIGINS in docker-compose.yml
+docker compose up -d
+# Admin at http://localhost:2333/proxy/qaqdmin
+```
+
+### Common Issues & Fixes
+- `JWT_SECRET is required` → Set the environment variable
+- `SNOWFLAKE_WORKER_ID is required` → Set to `1`
+- `Connection refused to postgres:5432` → Check PostgreSQL is running and credentials
+- 502 Bad Gateway → Check reverse proxy config, backend port is 2333
+- OAuth callback fails → Verify callback URL matches exactly, check ALLOWED_ORIGINS
+- Mail not sending → Check SMTP/Resend config, try Resend for simpler setup
+
+### Documentation Links
+- Full docs: https://mx-space.js.org/docs
+- API Client SDK: https://github.com/mx-space/api-client
+- Community snippets: https://github.com/mx-space/snippets
+- GitHub: https://github.com/mx-space/core
+
+## Response Style
+
+- Answer in the same language the user uses (Chinese or English)
+- For deployment questions, prefer Docker method unless user specifies otherwise
+- For configuration questions, reference the admin UI path (e.g., "设定 → AI 设定")
+- For code questions, reference the actual file paths in the monorepo
+- When troubleshooting, start with the most common cause first
diff --git a/public/docs/core.html b/public/docs/core.html
new file mode 100644
index 00000000..b969094b
--- /dev/null
+++ b/public/docs/core.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/getting-started
+
+
diff --git a/public/docs/core/advanced.html b/public/docs/core/advanced.html
new file mode 100644
index 00000000..92ca8880
--- /dev/null
+++ b/public/docs/core/advanced.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/deploy/source
+
+
diff --git a/public/docs/core/bash.html b/public/docs/core/bash.html
new file mode 100644
index 00000000..551fa704
--- /dev/null
+++ b/public/docs/core/bash.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/deploy/one-script
+
+
diff --git a/public/docs/core/community.html b/public/docs/core/community.html
new file mode 100644
index 00000000..c2be8bd6
--- /dev/null
+++ b/public/docs/core/community.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/deploy/community
+
+
diff --git a/public/docs/core/docker.html b/public/docs/core/docker.html
new file mode 100644
index 00000000..84221dc9
--- /dev/null
+++ b/public/docs/core/docker.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/deploy/docker
+
+
diff --git a/public/docs/core/extra.html b/public/docs/core/extra.html
new file mode 100644
index 00000000..0d24b9cc
--- /dev/null
+++ b/public/docs/core/extra.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/deploy/external-services
+
+
diff --git a/public/docs/core/features.html b/public/docs/core/features.html
new file mode 100644
index 00000000..b969094b
--- /dev/null
+++ b/public/docs/core/features.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/getting-started
+
+
diff --git a/public/docs/core/index.html b/public/docs/core/index.html
new file mode 100644
index 00000000..b969094b
--- /dev/null
+++ b/public/docs/core/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/getting-started
+
+
diff --git a/public/docs/development.html b/public/docs/development.html
new file mode 100644
index 00000000..c00c8b53
--- /dev/null
+++ b/public/docs/development.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/develop
+
+
diff --git a/public/docs/development/admin.html b/public/docs/development/admin.html
new file mode 100644
index 00000000..3f4b1ac8
--- /dev/null
+++ b/public/docs/development/admin.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/develop/admin
+
+
diff --git a/public/docs/development/frontend.html b/public/docs/development/frontend.html
new file mode 100644
index 00000000..6374ee10
--- /dev/null
+++ b/public/docs/development/frontend.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/develop/frontend
+
+
diff --git a/public/docs/development/index.html b/public/docs/development/index.html
new file mode 100644
index 00000000..c00c8b53
--- /dev/null
+++ b/public/docs/development/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/develop
+
+
diff --git a/public/docs/document.html b/public/docs/document.html
new file mode 100644
index 00000000..8a51bb0d
--- /dev/null
+++ b/public/docs/document.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/develop/contribute
+
+
diff --git a/public/docs/document/index.html b/public/docs/document/index.html
new file mode 100644
index 00000000..8a51bb0d
--- /dev/null
+++ b/public/docs/document/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/develop/contribute
+
+
diff --git a/public/docs/usage.html b/public/docs/usage.html
new file mode 100644
index 00000000..a9082fe0
--- /dev/null
+++ b/public/docs/usage.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use
+
+
diff --git a/public/docs/usage/backup.html b/public/docs/usage/backup.html
new file mode 100644
index 00000000..3afb40d2
--- /dev/null
+++ b/public/docs/usage/backup.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use/backup-restore
+
+
diff --git a/public/docs/usage/index.html b/public/docs/usage/index.html
new file mode 100644
index 00000000..a9082fe0
--- /dev/null
+++ b/public/docs/usage/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use
+
+
diff --git a/public/docs/usage/oauth.html b/public/docs/usage/oauth.html
new file mode 100644
index 00000000..e4bcdfd8
--- /dev/null
+++ b/public/docs/usage/oauth.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/configure/oauth
+
+
diff --git a/public/docs/usage/obsidian.html b/public/docs/usage/obsidian.html
new file mode 100644
index 00000000..41e61062
--- /dev/null
+++ b/public/docs/usage/obsidian.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use/writing
+
+
diff --git a/public/docs/usage/search.html b/public/docs/usage/search.html
new file mode 100644
index 00000000..c87cb99e
--- /dev/null
+++ b/public/docs/usage/search.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/configure/algolia
+
+
diff --git a/public/docs/usage/security.html b/public/docs/usage/security.html
new file mode 100644
index 00000000..76e9f221
--- /dev/null
+++ b/public/docs/usage/security.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/configure/encryption
+
+
diff --git a/public/docs/usage/serverless.html b/public/docs/usage/serverless.html
new file mode 100644
index 00000000..db8e3aad
--- /dev/null
+++ b/public/docs/usage/serverless.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use/serverless
+
+
diff --git a/public/docs/usage/update.html b/public/docs/usage/update.html
new file mode 100644
index 00000000..b262ef48
--- /dev/null
+++ b/public/docs/usage/update.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use/update
+
+
diff --git a/public/docs/usage/xlog.html b/public/docs/usage/xlog.html
new file mode 100644
index 00000000..41e61062
--- /dev/null
+++ b/public/docs/usage/xlog.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Redirecting...
+
+
+ Redirecting to /docs/use/writing
+
+
diff --git a/public/llm-full.txt b/public/llm-full.txt
new file mode 100644
index 00000000..484db7bd
--- /dev/null
+++ b/public/llm-full.txt
@@ -0,0 +1,3763 @@
+# Mix Space — Complete Documentation (llm-full.txt)
+
+> This file contains the complete Mix Space documentation for LLM consumption.
+> Online version: https://mx-space.js.org/docs
+> Source code: https://github.com/mx-space/core
+
+## About Mix Space
+
+Mix Space is an AI-powered headless CMS for personal blogs and content sites.
+- Backend: NestJS 11 + Fastify + PostgreSQL 16 + Redis 7
+- Admin: Vue 3 + Naive UI
+- Frontend Themes: Next.js (Shiro, Yohaku) or community themes
+
+## Documentation Structure
+
+1. Getting Started — What is Mix Space, requirements, quick start
+2. Deploy — Docker, one-script, source, reverse proxy, SSL, external services
+3. Configure — Environment variables, SEO, OAuth, Algolia, encryption, account, image storage
+4. Themes — Yohaku, Shiro, Kami, Yun, community
+5. Use — Writing, content, comments, friends, says, projects, files, analytics, AI, webhook, mail, serverless, cron, backup, update, FAQ
+6. Migrate — v11→v12, WordPress
+7. Develop — Backend, frontend, admin, contribute
+8. Reference — Common issues
+
+---
+
+# Mix Space — Complete Documentation
+# Full documentation for Mix Space CMS. Source: https://mx-space.js.org/docs
+
+================================================================================
+## Mix Space 是什么
+Path: /docs/getting-started/index
+================================================================================
+
+Mix Space 是一个简洁、现代、高性能的个人博客系统,采用前后端分离架构。
+## 系统组成
+Mix Space 由两大部分组成:
+
+- **后端 (Core)**:提供数据存储、业务逻辑、RESTful API 以及后台管理界面。你可以通过后台管理文章、页面、笔记、评论等所有内容。
+- **前端 (Theme)**:面向访客的展示站点,通过调用后端 API 获取数据并渲染页面。
+这种分离设计让你可以自由搭配前端主题,而后端数据始终保持一致。
+## 官方主题
+目前官方维护的前端主题有:
+- **Shiro** —— 最受欢迎的现代化主题,设计精致,功能丰富
+- **Yohaku** —— 简约留白风格,注重阅读体验
+- **Kami** —— 经典风格,稳定可靠
+- **Yun** —— 早期主题,轻量简洁
+ 这不是 WordPress 式的「一键安装」。你需要分别部署后端和前端,但这也带来了更大的灵活性。
+## 继续阅读
+
+ 了解你需要准备的服务器、域名和基础知识
+
+ 在本地快速启动 Mix Space,无需配置域名
+
+ 完整的生产环境部署文档
+
+================================================================================
+## 准备工作
+Path: /docs/getting-started/what-you-need
+================================================================================
+
+## 你需要什么
+在正式开始之前,请确认你已准备好以下事项:
+- [ ] 一台服务器(Linux / macOS,内存 >= 1GB,推荐 2GB)
+- [ ] 一个域名(推荐,但本地体验可以不要)
+- [ ] 基础的命令行知识(会复制粘贴命令即可)
+- [ ] 预计费用:服务器 ~ 几十元/月,域名 ~ 几十元/年
+## 基础知识自查
+如果你知道以下概念是什么,那么你已经具备了部署 Mix Space 的基础:
+- **Docker** —— 容器化运行环境,帮你自动处理依赖
+- **Docker Compose** —— 多容器编排工具,一键启动所有服务
+- **反向代理** —— 如 Nginx、Caddy,用于将域名指向服务并配置 HTTPS
+如果以上术语对你来说比较陌生,不用担心,选择 **Docker 部署** 是最简单的方式,只需要复制粘贴命令即可完成。
+## 系统架构
+Mix Space 由以下几个部分组成:
+| 组件 | 说明 | 必需 |
+|------|------|------|
+| **Core(后端)** | NestJS API 服务,提供所有后端功能 | ✅ |
+| **PostgreSQL** | 关系型数据库,存储所有业务数据 | ✅ |
+| **Redis** | 缓存,用于会话、队列、实时数据 | ✅ |
+| **前端主题** | 用户访问的网站界面(Shiro、Yohaku 等) | ✅ |
+| **Admin** | 后台管理系统(内嵌在 Core 中) | ✅ |
+PostgreSQL 和 Redis 可以使用 Docker 内置的服务,也可以连接外部已有的实例。
+## 两种部署路径
+| 方式 | 难度 | 适合谁 | 预计时间 |
+| :--- | :--- | :--- | :--- |
+| Docker | 简单 | 大多数用户 | 15 分钟 |
+| 源码编译 | 较难 | 开发者 / 想折腾的用户 | 1 小时 |
+Docker 方式会帮你自动处理 PostgreSQL、Redis 和运行环境;源码编译则需要你手动安装 Node.js、数据库等依赖,并进行编译构建。
+ 如果你不确定选哪个,选 Docker。
+准备好了?继续阅读 [5 分钟快速体验](./quick-start),在本地先跑起来看看。
+
+================================================================================
+## 5 分钟快速体验
+Path: /docs/getting-started/quick-start
+================================================================================
+
+本指南的目标是在 **5 分钟** 内让你在本地运行起一个完整的 Mix Space,**无需配置域名,无需填写环境变量**(全部使用默认值)。
+
+ 确保你的机器已安装 Docker 和 Docker Compose。如果没有,可以执行以下命令一键安装:
+ ```bash
+ curl -fsSL https://get.docker.com | bash
+ ```
+ 安装完成后,运行 `docker --version` 和 `docker compose version` 确认安装成功。
+
+ 执行以下命令克隆后端仓库并启动服务:
+ ```bash
+ git clone https://github.com/mx-space/core.git --depth=1
+ cd core
+ docker compose up -d
+ ```
+ 首次启动会拉取镜像并初始化 PostgreSQL 和 Redis,可能需要几分钟时间。
+
+ 等待约 30 秒,让数据库和服务完成初始化。可以用以下命令检查状态:
+ ```bash
+ docker compose ps
+ ```
+ 所有服务状态为 `healthy` 后,打开浏览器访问:
+ ```
+ http://localhost:2333/proxy/qaqdmin
+ ```
+
+ 第一次访问后台时,系统会引导你完成初始化设置:
+ - 设置管理员账号和密码
+ - 填写站点基本信息
+ 初始化完成后,即可使用刚才设置的账号登录后台管理系统。
+
+ 确认以下事项均正常:
+ - [ ] 后端 API 响应正常(访问 `http://localhost:2333/api/v2` 能返回 JSON)
+ - [ ] 后台管理页面能正常加载和登录
+ - [ ] 可以在后台发布一篇文章并保存成功
+
+ 这只是本地体验。要对外公开访问,你需要继续阅读[部署指南](/docs/deploy),配置域名和反向代理。
+## 服务架构
+本地启动后,以下服务在后台运行:
+| 服务 | 端口 | 说明 |
+|------|------|------|
+| **Mix Space 后端** | 2333 | NestJS API 服务 + 后台管理界面 |
+| **PostgreSQL** | 5432 | 数据库(仅容器内可访问) |
+| **Redis** | 6379 | 缓存(仅容器内可访问) |
+## 下一步
+本地体验完成后,你可以:
+1. [部署到服务器](/docs/deploy) — 配置域名和 HTTPS
+2. [部署前端主题](/docs/themes) — 为你的站点选择一个漂亮的前端
+3. [配置 AI 功能](/docs/use/ai-features) — 开启 AI 摘要、翻译等功能
+
+================================================================================
+## 选择部署方式
+Path: /docs/deploy/index
+================================================================================
+
+Mix Space 提供三种部署方式,从简单到复杂依次为 Docker、一键脚本、源码编译。
+## 部署方式对比
+| 方式 | 难度 | 维护成本 | 适合谁 |
+|------|------|----------|--------|
+| Docker | ⭐ | 低 | 大多数用户,推荐 |
+| 一键脚本 | ⭐ | 中 | 想自动化部署的用户 |
+| 源码编译 | ⭐⭐⭐ | 高 | 开发者,需要二次开发 |
+## 如何选择
+- **如果你第一次部署** → 选择 [Docker 部署](./docker),稳定、可维护、社区支持最好。
+- **如果你想在服务器上一键搞定** → 选择 [一键脚本部署](./one-script),自动安装依赖并配置。
+- **如果你想改后端代码,或需要深度定制** → 选择 [源码部署](./source),完全可控但维护成本更高。
+## 快速开始
+ }>
+ 推荐大多数用户使用,简单稳定
+
+ }>
+ 自动化安装,适合懒人
+
+ }>
+ 面向开发者,完全可控
+
+部署完成后,请继续配置 [反向代理](./reverse-proxy) 和 [SSL 证书](./ssl)。
+
+================================================================================
+## Docker 部署
+Path: /docs/deploy/docker
+================================================================================
+
+### 安装 Docker
+如果你的服务器在国内,建议使用阿里云的安装脚本:
+```bash
+curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
+```
+在国外,可以直接使用官方脚本:
+```bash
+curl -fsSL https://get.docker.com | bash -s docker
+```
+验证安装:
+```bash
+docker -v
+docker compose version
+```
+### 拉取配置文件
+```bash
+cd && mkdir -p mx-space/core && cd $_
+# 拉取 docker-compose.yml 文件
+wget https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
+```
+### 配置环境变量
+在下方的表格中填入配置,点击复制后粘贴到 `docker-compose.yml` 的 `environment` 字段中。
+ format="yaml"
+ variableNames={[
+ {
+ key: 'JWT_SECRET',
+ name: '[JWT 密钥] 长度 16-32 个字符',
+ },
+ {
+ key: 'ALLOWED_ORIGINS',
+ name: '[被允许的域名] 多个域名用英文逗号分隔',
+ },
+ {
+ key: 'ENCRYPT_ENABLE',
+ name: '[是否开启加密] true 或 false',
+ },
+ {
+ key: 'ENCRYPT_KEY',
+ name: '[加密密钥] 开启加密时必填',
+ },
+ ]}
+/>
+- **`JWT 密钥`**:长度 16-32 个字符,用于加密用户 JWT,务必保存好不要泄露。
+- **`被允许的域名`**:通常是前端的域名,多个用英文逗号分隔。
+- **`是否开启加密`**:如需开启,将 `false` 改为 `true`。
+- **`加密密钥`**:开启加密后必填,长度必须为 64 位且只有小写字母和数字。可用 `openssl rand -hex 32` 生成。**此操作不可逆,请谨慎。**
+### 启动服务
+如果服务器在国内,拉取镜像速度过慢,可在 `docker-compose.yml` 的 image 前添加镜像域名,例如 `docker.1panel.top/innei/mx-server:latest`。
+```bash
+docker compose up -d
+```
+### 验证
+启动后,请按以下清单确认服务正常:
+- [ ] `docker compose ps` 显示所有服务状态为 healthy
+- [ ] `curl http://localhost:2333/api/v2/ping` 返回 `pong`
+- [ ] 浏览器能打开后台初始化页面 `http://你的域名/proxy/qaqdmin`
+## 下一步
+ }>
+ 将域名指向你的服务,并配置 HTTPS
+
+ }>
+ 部署前端主题完成整套系统
+
+================================================================================
+## 一键脚本部署
+Path: /docs/deploy/one-script
+================================================================================
+
+此脚本由社区维护,官方文档仅作引用。如遇问题请前往对应的 GitHub 仓库提出 Issue。
+本脚本由社区用户“[Mikuの鬆](https://github.com/PaloMiku)”维护。
+## 介绍
+这是一种在服务器自动安装 Docker 和进行 Mix Space 后端部署的 Bash 脚本,它可以帮助你交互式快速部署 Mix Space 后端。
+注意脚本会自动根据是否为中国大陆网络环境按需修改服务器 Docker 安装源和镜像源。
+脚本支持交互式安装方式和预配置文件的自动安装方式。
+## 使用
+在服务器终端运行以下指令,即可自动进入交互式安装。
+### 海外服务器
+```bash
+curl -sSL https://raw.githubusercontent.com/PaloMiku/MxShell/refs/heads/main/install/core.sh -o core.sh && bash core.sh
+```
+### 国内服务器
+使用 Moeyy 的 GitHub 加速源。
+```bash
+curl -sSL https://github.moeyy.xyz/https://raw.githubusercontent.com/PaloMiku/MxShell/refs/heads/main/install/core.sh -o core.sh && bash core.sh
+```
+## 预配置文件
+参考下方示例修改并粘贴到 `mxshell.env` 文件,并将其与脚本置于同一目录后运行脚本,脚本会根据配置文件内容自动完成前后端部署。
+### 配置文件示例
+```yaml
+# 需要填写长度不小于 16 个字符,不大于 32 个字符的字符串,用于加密用户的 JWT,务必保存好自己的密钥,不要泄露给他人。
+JWT_SECRET=
+# 需要填写被允许访问前端的域名,如果允许多个域名访问,用英文逗号,分隔。
+ALLOWED_ORIGINS=
+# Mix Space 容器文件存储目录
+TARGET_DIR="/opt/mxspace"
+```
+- **`JWT 密钥`**:需要填写长度不小于 16 个字符,不大于 32 个字符的字符串,用于加密用户的 JWT,务必保存好自己的密钥,不要泄露给他人。
+- **`被允许的域名`**:需要填写被允许访问容器的域名,通常是前端的域名,如果允许多个域名访问,用英文逗号,分隔。
+- **`Mix Space 容器文件存储目录`**:指定文件存储路径,通常是 `/opt/mxspace`。
+
+================================================================================
+## 源码部署
+Path: /docs/deploy/source
+================================================================================
+
+如果你**不是开发者**,或者**不想折腾**,请不要选择源码部署。由于自身技术原因导致的问题,我们将**不会提供任何技术支持**。
+## 要求
+- [Node.js](https://nodejs.org/zh-cn/) 22+
+- [PostgreSQL](https://www.postgresql.org/download/) 16+
+- [Redis](https://redis.io/download)
+- [Git](https://git-scm.com/downloads)、[PNPM](https://pnpm.io/installation)、[PM2](https://pm2.keymetrics.io/docs/usage/quick-start/)
+### 克隆并安装
+```bash
+git clone https://github.com/mx-space/core.git --depth=1
+cd core
+pnpm i
+```
+### 构建 & Bundle
+```bash
+pnpm build
+pnpm bundle
+```
+### 配置 ecosystem.config.js
+在 `./apps/core` 目录下创建 `ecosystem.config.js`:
+```js
+const { cpus } = require('os')
+const { execSync } = require('child_process')
+const nodePath = execSync(`npm root --quiet -g`, { encoding: 'utf-8' }).split(
+ '\n',
+)[0]
+const cpuLen = cpus().length
+module.exports = {
+ apps: [
+ {
+ name: 'mx-server',
+ script: './out/index.js',
+ autorestart: true,
+ exec_mode: 'cluster',
+ watch: false,
+ instances: cpuLen,
+ max_memory_restart: '520M',
+ args: '',
+ env: {
+ NODE_ENV: 'production',
+ NODE_PATH: nodePath,
+ // 必填:允许跨域的域名,多个用逗号分隔
+ ALLOWED_ORIGINS: 'your-domain.com',
+ // 必填:JWT 密钥,16-32 个字符
+ JWT_SECRET: 'your-jwt-secret',
+ // 可选:加密密钥,开启加密时填写
+ MX_ENCRYPT_KEY: '',
+ },
+ },
+ ],
+}
+```
+### 启动
+```bash
+pm2 start ecosystem.config.js
+```
+查看运行状态:
+```bash
+pm2 logs mx-server
+```
+## 环境变量
+更多环境变量配置请参考 [环境变量说明](/docs/configure/environment)。
+## 下一步
+部署完成后,请配置 [反向代理](./reverse-proxy) 和 [SSL 证书](./ssl)。
+
+================================================================================
+## 反向代理
+Path: /docs/deploy/reverse-proxy
+================================================================================
+
+## 为什么需要反向代理
+Mix Space 默认运行在本地端口(后端 `2333`,前端 `2323`),反向代理可以将域名请求转发到对应端口,并提供 HTTPS、WebSocket 支持。
+## 图形化面板
+现代服务器面板(如 1Panel、宝塔面板)自带的反向代理已足以满足 Mix Space 的需求(包括 WebSocket),非高级用户建议使用图形化界面操作。
+### 宝塔面板
+进入 `网站`,在 `反向代理` 栏目下点击 `添加反代`。
+- `域名` 填入你将要使用的域名
+- `目标` 填写 `URL 地址` + `http://127.0.0.1:2333`
+### 1Panel
+进入 `网站 > 网站`,创建一个新网站,选择 `反向代理`。
+- `主域名` 填入你将要使用的域名,并勾选 `监听 IPV6`
+- 代理类型选择 `http`,地址填入 `127.0.0.1:2333`
+## Vane
+Vane 是一个较新的反向代理项目,请做好出现异常问题的准备。目前已测试过 mx-server + Shiro,如遇问题请携带日志反馈。
+[Vane](https://github.com/canmi21/vane) 是一个使用 Rust 编写的现代反向代理,内存占用约 1.5-3MB,Docker 镜像约 5MB。
+### 获取证书
+Vane 目前不包含 SSL 证书管理,可通过以下方式获取:
+- 使用 1Panel / 宝塔面板自带的 acme.sh 生成证书,导入到 Vane
+- 使用 [lazy-acme](https://github.com/canmi21/lazy-acme)(Vane 配套工具,支持 Cloudflare DNS 验证)
+### 部署配置
+推荐使用 [docker-compose.yml](https://github.com/canmi21/vane?tab=readme-ov-file#installation-and-usage) 部署。
+编写主配置文件 `~/vane/config.toml`:
+```toml
+[domains]
+"example.com" = "example.com.toml"
+"api.example.com" = "api.example.com.toml"
+```
+前端域名配置 `example.com.toml`:
+```toml
+https = true
+http3 = true
+hsts = true
+http_options = "reject"
+[tls]
+cert = "~/vane/cert/example.com.pem"
+key = "~/vane/cert/example.com.key"
+[methods]
+allow = "GET, POST, OPTIONS, HEAD"
+[rate_limit.default]
+period = "1s"
+requests = 20
+[[routes]]
+path = "/"
+websocket = true
+targets = ["http://127.0.0.1:2323"]
+```
+后端域名配置 `api.example.com.toml`:
+```toml
+https = true
+http_options = "reject"
+hsts = true
+http3 = false
+[tls]
+cert = "~/vane/cert/api.example.com.pem"
+key = "~/vane/cert/api.example.com.key"
+[methods]
+allow = "GET, POST, OPTIONS, HEAD"
+[rate_limit.default]
+period = "1s"
+requests = 20
+[[routes]]
+path = "/*"
+websocket = true
+targets = ["http://localhost:2333"]
+```
+注意根据实际部署情况修改端口和域名。
+## Cloudflare Tunnel
+除非你在非完整服务器环境(如 Sealos 或 Huggingface Space)部署,否则不推荐在容器内使用 Cloudflare Tunnel,而应在宿主机配置以避免管理不便。
+启动该功能需要两个环境变量:
+- `ENABLE_CLOUDFLARED` = `true`
+- `CF_ZERO_TRUST_TOKEN` = Tunnel 给的令牌(删掉 `cloudflared.exe service install`,只保留令牌部分)
+### 详细步骤
+1. 申请 Cloudflare Zero Trust
+2. 添加一条隧道,连接方式选择 Cloudflared,名称任意
+3. 添加一个 Public Hostname,回源选择 HTTP,端口选择 `2333`
+启动成功后,日志中应看到:
+```
+============================================
+Starting Cloudflared Tunnel
+============================================
+```
+## Nginx 手写配置
+手写配置文件需要较高的技术功底,请量力而行。
+### 双域名配置
+假定前端域名为 `www.example.com`,后端为 `server.example.com`。
+后端配置:
+```nginx
+server {
+ location /socket.io {
+ proxy_pass http://127.0.0.1:2333/socket.io;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_buffering off;
+ proxy_http_version 1.1;
+ add_header Cache-Control no-cache;
+ }
+ location / {
+ proxy_pass http://127.0.0.1:2333;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ add_header X-Cache $upstream_cache_status;
+ }
+}
+```
+前端配置:
+```nginx
+server {
+ location ~* \.(gif|png|jpg|css|js|woff|woff2)$ {
+ proxy_pass http://127.0.0.1:2323;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ expires 30d;
+ }
+ location / {
+ proxy_pass http://127.0.0.1:2323;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ add_header X-Cache $upstream_cache_status;
+ add_header Cache-Control no-cache;
+ proxy_intercept_errors on;
+ }
+}
+```
+使用双域名配置时:
+- API 地址为 `https://server.example.com/api/v2`
+- 前端地址为 `https://www.example.com`
+- Gateway 为 `https://server.example.com`
+- 后台为 `https://server.example.com/proxy/qaqdmin`
+### 单域名配置
+```nginx
+server {
+ listen 80;
+ listen 443 ssl http2;
+ server_name www.example.com;
+ index index.html;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Host $server_name;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ location /socket.io {
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:2333/socket.io;
+ }
+ location /api/v2 {
+ proxy_pass http://127.0.0.1:2333/api/v2;
+ }
+ location /render {
+ proxy_pass http://127.0.0.1:2333/render;
+ }
+ location / {
+ proxy_pass http://127.0.0.1:2323;
+ }
+ location /qaqdmin {
+ proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
+ }
+ location /proxy {
+ proxy_pass http://127.0.0.1:2333/proxy;
+ }
+ ssl_certificate /path/to/fullchain.pem;
+ ssl_certificate_key /path/to/privkey.pem;
+ ssl_protocols TLSv1.3 TLSv1.2;
+ error_page 497 https://$host$request_uri;
+}
+```
+使用单域名配置时:
+- API 地址为 `https://www.example.com/api/v2`
+- 前端地址为 `https://www.example.com`
+- Gateway 为 `https://www.example.com`
+- 后台为 `https://www.example.com/proxy/qaqdmin`
+
+================================================================================
+## HTTPS / SSL 证书
+Path: /docs/deploy/ssl
+================================================================================
+
+Mix Space 的后台管理、OAuth 登录等功能要求使用 HTTPS。现代浏览器也会标记 HTTP 站点为不安全,影响访问体验。本页介绍几种常见的 SSL 证书获取和配置方式。
+## 获取证书
+### 自动证书(Let's Encrypt + Certbot)
+Let's Encrypt 提供免费、自动化的 SSL 证书,有效期 90 天,支持自动续期。
+**使用服务器面板(推荐):**
+大部分服务器面板(1Panel、宝塔)都内置了自动证书申请功能,推荐在面板中一键申请并开启自动续期。
+**使用 Certbot 命令行:**
+```bash
+# 安装 Certbot
+apt install certbot python3-certbot-nginx # Debian/Ubuntu
+yum install certbot python3-certbot-nginx # CentOS
+# 申请证书(Nginx 插件自动配置)
+certbot --nginx -d example.com -d www.example.com
+# 测试自动续期
+certbot renew --dry-run
+```
+Certbot 会自动修改 Nginx 配置并设置定时任务续期。
+### Cloudflare Origin Certificates
+如果你使用 Cloudflare CDN,可以申请 Cloudflare Origin Certificates:
+- 有效期最长 15 年
+- 仅用于 Cloudflare 回源到服务器的加密
+- 访客看到的是 Cloudflare 的 Edge 证书
+操作步骤:
+1. 登录 Cloudflare 后台,进入 `SSL/TLS → 源服务器`
+2. 点击「创建证书」,选择 RSA,有效期 15 年
+3. 下载 PEM(证书)和 Key(私钥)文件
+4. 在 Nginx 中配置这两个文件
+使用 Cloudflare Origin Certificates 时,Cloudflare 的 SSL/TLS 加密模式应设为「完全(严格)」,以确保端到端加密。
+### 手动上传证书
+如果你已从其他 CA(如 DigiCert、Sectigo)购买或申请了证书,将证书文件和私钥上传到服务器,然后在 Nginx 中指定路径即可。
+## Nginx SSL 配置
+### 基础配置
+```nginx
+server {
+ listen 443 ssl http2;
+ server_name example.com;
+ ssl_certificate /etc/ssl/certs/fullchain.pem;
+ ssl_certificate_key /etc/ssl/private/privkey.pem;
+}
+```
+### 推荐的安全配置
+```nginx
+server {
+ listen 443 ssl http2;
+ server_name example.com;
+ # 证书路径
+ ssl_certificate /etc/ssl/certs/fullchain.pem;
+ ssl_certificate_key /etc/ssl/private/privkey.pem;
+ # 仅使用 TLS 1.2 和 1.3
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
+ ssl_prefer_server_ciphers on;
+ # 会话缓存
+ ssl_session_cache shared:SSL:10m;
+ ssl_session_timeout 10m;
+ # HSTS(可选,启用后浏览器强制 HTTPS)
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ # HTTP 自动跳转
+ error_page 497 https://$host$request_uri;
+}
+# HTTP 跳转 HTTPS
+server {
+ listen 80;
+ server_name example.com;
+ return 301 https://$host$request_uri;
+}
+```
+### 安全响应头(可选)
+```nginx
+add_header X-Frame-Options "SAMEORIGIN" always;
+add_header X-Content-Type-Options "nosniff" always;
+add_header X-XSS-Protection "1; mode=block" always;
+add_header Referrer-Policy "strict-origin-when-cross-origin" always;
+```
+## 常见问题
+### 证书续期后未生效
+Certbot 续期证书后需要重载 Nginx:
+```bash
+nginx -s reload
+```
+Certbot 的 `deploy-hook` 可以自动执行此操作。
+### 浏览器提示证书不匹配
+- 确认证书覆盖了所有访问域名(包括 `www` 子域名)
+- 检查证书是否过期
+- 如果使用 Cloudflare,确认 SSL 模式不是「灵活」(灵活模式会导致重定向循环)
+### 混合内容警告
+确保前端页面中所有资源(图片、脚本、样式表)都使用 HTTPS 地址。检查 HTML 中是否有硬编码的 `http://` 链接。
+
+================================================================================
+## 使用外部数据库
+Path: /docs/deploy/external-services
+================================================================================
+
+如果你需要使用来自远端或非容器内的 Redis / PostgreSQL 服务,可以通过环境变量或启动参数传入配置。
+## 外部 Redis
+支持传入的参数:
+| 参数 | 说明 |
+|------|------|
+| `redis_host` | Redis 服务地址,域名或 IP |
+| `redis_port` | Redis 服务端口 |
+| `redis_password` | Redis 服务密码 |
+| `disable_cache` | 是否禁用缓存,默认不启用 |
+### Docker 部署
+在 `docker-compose.yml` 的 `services.app.environment` 中添加:
+```yaml
+services:
+ app:
+ container_name: mx-server
+ image: innei/mx-server:latest
+ environment:
+ - TZ=Asia/Shanghai
+ - NODE_ENV=production
+ - REDIS_HOST=远端地址
+ - REDIS_PASSWORD=redis?passwd
+ - ALLOWED_ORIGINS=localhost
+ - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
+ volumes:
+ - ./data/mx-space:/root/.mx-space
+```
+修改完成后执行 `docker compose up -d` 重启服务。
+### 源码部署
+修改 `ecosystem.config.js`,在 `script` 项中添加参数:
+```diff
+ script: 'out/index.js',
++ script: 'out/index.js --redis_host=远端地址 --redis_password=redis?passwd',
+```
+然后重启服务:
+```bash
+pnpm prod:pm2
+```
+## 外部 PostgreSQL
+支持传入的参数:(Docker 中为对应大写环境变量)
+| 参数 | 说明 |
+|------|------|
+| `pg_host` | PostgreSQL 服务地址 |
+| `pg_port` | PostgreSQL 服务端口 |
+| `pg_user` | PostgreSQL 用户名 |
+| `pg_password` | PostgreSQL 密码 |
+| `pg_database` | PostgreSQL 数据库名 |
+| `pg_connection_string` | 连接地址(`postgresql://` 或 `postgres://` 开头),优先级高于以上五项 |
+| `pg_ssl` | 是否启用 SSL 连接,`true` 为启用 |
+| `pg_max_pool_size` | 连接池大小,默认 `20` |
+如果使用密码登录,必须同时传入 `user` 和 `password`,建议对数据库划分好用户权限。
+### Docker 部署
+在 `docker-compose.yml` 的 `services.app.environment` 中添加:
+```yaml
+services:
+ app:
+ container_name: mx-server
+ image: innei/mx-server:latest
+ environment:
+ - TZ=Asia/Shanghai
+ - NODE_ENV=production
+ - PG_HOST=远端地址
+ - PG_USER=postgres-test
+ - PG_PASSWORD=db?passwd
+ - PG_DATABASE=mx_core
+ - REDIS_HOST=redis
+ - ALLOWED_ORIGINS=localhost
+ - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
+ volumes:
+ - ./data/mx-space:/root/.mx-space
+```
+修改完成后执行 `docker compose up -d` 重启服务。
+### 源码部署
+修改 `ecosystem.config.js`,在 `script` 项中添加参数:
+```diff
+ script: 'out/index.js',
++ script: 'out/index.js --pg_host=远端地址 --pg_user=postgres-test --pg_password=db?passwd --pg_database=mx_core',
+```
+然后重启服务:
+```bash
+pnpm prod:pm2
+```
+
+================================================================================
+## 社区部署方案
+Path: /docs/deploy/community
+================================================================================
+
+ 你可以参考他们的部署方式,但我们不保证它们的可用性。如果你也有教程想要与大家分享的话,欢迎您向文档提交
+ [Pull Request](https://github.com/mx-space/docs/pulls) 以分享您的部署方式。
+} target="_blank">BiliBili 前后端部署视频教程 | By 喵二 | 平台:Selfhost
+
+ {" "}
+ Kami 前端部署博文教程 | By 喵二 | 平台:Serverless
+
+ {" "}
+ 前后端部署博文教程 | By Arthals | 平台:Selfhost
+
+ 前后端部署博文教程 | By 草方块 | 平台:Serverless
+
+ 前后端部署博文教程 | By Rinne | 平台:Android
+
+ 后端迁移系统数据博文教程 | By Fosky
+
+ 前后端部署博文教程 | By 南栀 | 平台:Selfhost{" "}
+
+ {" "}
+ 前后端部署博文教程 | By 光合作用の少女 | 平台:Selfhost
+
+ {" "}
+ 前后端部署博文教程 | By 星野纯夏 | 平台:Selfhost
+
+ {" "}
+ 前后端部署博文教程 | By 白熊sama | 平台:Serverless
+
+ {" "}
+ 前后端部署博文教程 | By C_Hanze | 平台:Serverless
+
+ {" "}
+ 前后端部署博文教程 | By Yuuki | 平台:Selfhost
+
+ {" "}
+ Mix Space 后端部署博文教程 | By 极夜System | 平台:Selfhost
+
+================================================================================
+## 功能配置概览
+Path: /docs/configure/index
+================================================================================
+
+## 我想实现的功能
+| 我想实现... | 查看文档 |
+| --- | --- |
+| 设置第三方登录(GitHub/Google)| [OAuth 2.0](./oauth) |
+| 配置 SEO 和搜索引擎推送 | [SEO 与站点优化](./seo) |
+| 管理 API Token 和 Passkey | [账号与安全](./account-security) |
+| 配置 S3 图床和 CDN | [图床与存储](./image-storage) |
+| 添加站内搜索 | [Algolia Search](./algolia) |
+| 加密敏感配置 | [Key 加密](./encryption) |
+| 了解所有环境变量 | [环境变量参考](./environment) |
+## 快速导航
+
+ 查看所有支持的环境变量及其说明
+
+ SEO 元数据、Sitemap、RSS、百度/Bing 推送
+
+ 所有者信息、API Token、Passkey、OAuth 绑定
+
+ S3 对象存储配置、CDN 加速、自定义存储路径
+
+ 配置 GitHub、Google 等第三方登录
+
+ 为站点添加 Algolia 站内搜索
+
+ 加密数据库中的敏感配置项
+
+================================================================================
+## 环境变量参考
+Path: /docs/configure/environment
+================================================================================
+
+ 如果你不确定某个变量的作用,保持默认值即可。
+以下环境变量适用于 Mix Space Core 后端服务。Docker 用户在 `docker-compose.yml` 的 `environment` 中设置;源码用户在 `.env` 或 `ecosystem.config.js` 中设置。
+## 核心必填
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `JWT_SECRET` | JWT 签名密钥 | - | `my-secret-key` |
+| `ALLOWED_ORIGINS` | 允许的跨域域名 | - | `example.com,www.example.com` |
+| `SNOWFLAKE_WORKER_ID` | 工作节点 ID(单实例填 1)| - | `1` |
+## PostgreSQL 数据库
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `PG_URL` | 完整连接字符串(推荐)| - | `postgresql://mx:mx@localhost:5432/mx_core` |
+| `PG_HOST` | 数据库地址 | `127.0.0.1` | `localhost` |
+| `PG_PORT` | 端口 | `5432` | `5432` |
+| `PG_USER` | 用户名 | `mx` | `mx` |
+| `PG_PASSWORD` | 密码 | `mx` | `secret` |
+| `PG_DATABASE` | 数据库名 | `mx_core` | `mx_core` |
+| `PG_MAX_POOL_SIZE` | 连接池大小 | `20` | `20` |
+| `PG_SSL` | 启用 SSL | `false` | `true` |
+## Redis
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `REDIS_HOST` | 地址 | `localhost` | `redis` |
+| `REDIS_PORT` | 端口 | `6379` | `6379` |
+| `REDIS_PASSWORD` | 密码 | - | `secret` |
+## 安全
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `ENCRYPT_ENABLE` | 启用加密 | `false` | `true` |
+| `ENCRYPT_KEY` | 加密密钥(64 位 hex)| 自动获取 machine-id | `abc...` |
+## 其他
+| 变量名 | 说明 | 默认值 | 示例 |
+| --- | --- | --- | --- |
+| `PORT` | 服务端口 | `2333` | `3000` |
+| `TZ` | 时区 | `Asia/Shanghai` | `UTC` |
+| `DISABLE_CACHE` | 禁用 Redis 缓存 | `false` | `false` |
+| `THROTTLE_TTL` | 限流窗口(秒)| `10` | `10` |
+| `THROTTLE_LIMIT` | 限流次数 | `100` | `100` |
+
+================================================================================
+## SEO 与站点优化
+Path: /docs/configure/seo
+================================================================================
+
+Mix Space 内置了 SEO 基础功能,包括自定义站点元数据、自动生成 Sitemap 和 RSS Feed,以及百度/Bing 搜索引擎推送。
+## SEO 基础设置
+进入后台「设定 → SEO 优化」,配置以下信息:
+| 配置项 | 说明 |
+|--------|------|
+| **网站标题** | 站点名称,显示在浏览器标签和搜索结果中 |
+| **网站描述** | 一段简短的站点描述,用于搜索引擎结果摘要 |
+| **浅色图标 URL** | 浅色模式下的站点图标 |
+| **深色图标 URL** | 深色模式下的站点图标 |
+| **关键字** | 站点关键词列表,用于搜索引擎识别站点主题 |
+这些信息会自动应用到前端页面的 `` 标签中。
+## 网站地址
+进入后台「设定 → 网站设置」,正确填写站点地址:
+| 配置项 | 说明 |
+|--------|------|
+| **前端地址** | 你的前端主题地址(如 `https://example.com`) |
+| **管理后台地址** | 后台管理地址(如 `https://example.com/proxy/qaqdmin`) |
+| **API 地址** | 后端 API 地址 |
+| **Gateway 地址** | WebSocket 网关地址 |
+「前端地址」非常重要,Sitemap 和 RSS 中的链接都基于此地址生成。请确保填写正确的完整 URL(包含 `https://`)。
+## Sitemap
+Mix Space 自动生成 Sitemap 文件,无需额外配置。
+访问 `https://你的API地址/sitemap` 即可获取标准的 XML Sitemap,其中包含所有已发布内容的 URL 和更新时间。
+Sitemap 缓存 1 小时,内容更新后会自动刷新。
+## RSS Feed
+Mix Space 自动生成 RSS Feed,无需额外配置。
+访问以下地址即可获取 RSS 订阅源:
+- `https://你的API地址/feed`
+- `https://你的API地址/atom.xml`
+RSS Feed 包含最新的文章内容,支持全文输出(Markdown 文章)和链接跳转(富文本文章)。
+## 搜索引擎推送
+### 百度推送
+进入后台「设定 → 百度推送设定」:
+| 配置项 | 说明 |
+|--------|------|
+| **开启推送** | 启用百度搜索引擎推送 |
+| **Token** | 百度站长平台提供的推送 Token |
+在 [百度搜索资源平台](https://ziyuan.baidu.com/) 注册并验证你的站点后,可以在「链接提交」中获取 Token。
+### Bing 推送
+进入后台「设定 → Bing 推送设定」:
+| 配置项 | 说明 |
+|--------|------|
+| **开启推送** | 启用 Bing 搜索引擎推送 |
+| **Bing API 密钥** | Bing Webmaster Tools 的 API 密钥 |
+在 [Bing Webmaster Tools](https://www.bing.com/webmasters) 中注册并验证站点后,可以在 API 设置中获取密钥。
+搜索引擎推送会在内容创建和更新时自动触发,无需手动操作。
+
+================================================================================
+## OAuth 2.0 登录
+Path: /docs/configure/oauth
+================================================================================
+
+Mix Space 支持通过第三方 OAuth 账号登录后台,免去记忆密码的麻烦。目前支持 GitHub 和 Google 两种 OAuth 服务商。
+OAuth 登录基于 better-auth 实现,不走 Clerk 等第三方认证服务,所有数据存储在你自己的数据库中。
+## 前置条件
+在配置 OAuth 之前,请确保:
+- 后端服务已正常运行
+- 前端和后端都已配置好 HTTPS(OAuth 回调要求 HTTPS)
+- 你有 GitHub 或 Google 的开发者账号
+## 配置 GitHub 登录
+### 创建 GitHub OAuth 应用
+1. 前往 [GitHub Developer Settings](https://github.com/settings/developers)
+2. 点击「New OAuth App」
+3. 填写以下信息:
+| 字段 | 填写内容 |
+|------|----------|
+| Application name | 你的站点名称 |
+| Homepage URL | 前端地址(如 `https://example.com`) |
+| Authorization callback URL | 后台提示的回调地址 |
+4. 创建完成后,记下 **Client ID**
+5. 点击「Generate a new client secret」,记下 **Client Secret**
+### 在后台配置
+登录后台,进入「设定 → 登录方式」,在 GitHub 部分填入 Client ID 和 Client Secret,保存。
+### 测试并绑定
+在前端登录页面点击 GitHub 登录按钮,完成授权后会提示是否将此账号设为站长。确认后即可通过 GitHub 登录后台。
+## 配置 Google 登录
+### 创建 Google OAuth 客户端
+1. 前往 [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
+2. 创建一个项目或选择已有项目
+3. 配置「OAuth 权限请求页面」:
+ - 已获授权的网域填写你的根域名
+ - API 范围选择非敏感范围的三项(email、profile、openid)
+4. 创建「OAuth 客户端 ID」,选择「Web 应用」:
+| 字段 | 填写内容 |
+|------|----------|
+| 已获授权的 JavaScript 来源 | 前端地址 |
+| 已获授权的重定向 URI | 后台提示的回调地址 |
+5. 记下 **Client ID** 和 **Client Secret**
+### 在后台配置
+登录后台,进入「设定 → 登录方式」,在 Google 部分填入 Client ID 和 Client Secret,保存。
+### 测试并绑定
+在前端登录页面点击 Google 登录按钮,完成授权后绑定站长身份。
+## 获取回调地址
+在后台「设定 → 登录方式」页面的 OAuth 部分,每个服务商旁边会显示对应的回调地址(Callback URL)。创建 OAuth 应用时需要将此地址填入。
+回调地址与你的前端地址和后端地址相关。如果更换了域名,需要同步更新 OAuth 应用的回调地址配置。
+## 绑定站长身份
+首次通过 OAuth 登录时,系统会提示你是否将此 OAuth 账号设为站长(Owner)。确认后,该 OAuth 账号就拥有了完整的管理权限。
+如果你后续需要更换绑定的 OAuth 账号,可以在后台「设定 → 账号与安全」中操作。
+## 同时使用多种登录方式
+你可以同时启用 GitHub 和 Google 登录。登录页面会显示所有已启用的登录方式,用户可以选择任意一种登录。
+如果同时配置了密码登录和 OAuth 登录,建议在「设定 → 认证安全设置」中考虑是否禁用密码登录以提高安全性。详见 [账号与安全](/docs/configure/account-security)。
+## 常见问题
+### 回调后提示错误
+- 确认回调地址完全一致(包括末尾的斜杠)
+- 确认 `ALLOWED_ORIGINS` 环境变量中包含前端域名
+- 确认 OAuth 应用的 Client ID 和 Secret 正确
+### GitHub 提示「Application suspended」
+- 检查 GitHub OAuth 应用的状态,可能因为长时间未使用被暂停
+- 确认 Client Secret 未过期(GitHub Secret 有过期时间设置)
+### Google 提示「未验证应用」
+- 在 Google Cloud Console 中将应用发布为「正式版」
+- 或者添加测试用户账号
+
+================================================================================
+## 账号与安全
+Path: /docs/configure/account-security
+================================================================================
+
+Mix Space 的账号系统围绕「所有者」概念设计。每个 Mix Space 实例只有一个所有者(Owner),所有者拥有完整的管理权限。
+## 所有者信息
+登录后台,进入「设定 → 个人信息」页面。你可以设置以下信息:
+| 字段 | 说明 |
+|------|------|
+| **昵称** | 显示名称 |
+| **头像** | 头像图片 URL |
+| **邮箱** | 联系邮箱 |
+| **个人介绍** | 一段简短的个人介绍 |
+| **社交链接** | GitHub、Twitter、Bilibili 等社交账号链接 |
+这些信息会被前端主题读取并展示在首页的博主信息区域。
+## API Token
+API Token 是访问 Mix Space API 的凭证。第三方工具(如 Obsidian 插件、API 客户端)需要 Token 才能调用需要认证的 API。
+### 管理 Token
+进入「设定 → 账号与安全 → API Token」:
+| 操作 | 说明 |
+|------|------|
+| **创建 Token** | 设置名称和过期时间,生成新的 Token |
+| **查看 Token** | 创建时显示完整的 Token 值,请妥善保存 |
+| **删除 Token** | 吊销指定 Token,所有使用该 Token 的请求将被拒绝 |
+Token 仅在创建时显示一次完整值。如果忘记 Token,需要删除后重新创建。请勿将 Token 提交到公开的代码仓库。
+### Token 的用途
+- **Obsidian 插件**:配置 API Token 以同步内容
+- **API 客户端**:`@mx-space/api-client` SDK 使用 Token 认证
+- **自动化脚本**:CI/CD 或自定义脚本调用 API
+## Passkey(通行密钥)
+Mix Space 支持使用 Passkey(WebAuthn)进行无密码登录,更加安全便捷。
+### 添加 Passkey
+### 进入账号设置
+前往「设定 → 账号与安全 → Passkey」。
+### 注册新密钥
+点击「添加 Passkey」,浏览器会弹出安全密钥注册窗口。根据设备不同,可能需要:
+- 使用指纹识别(Touch ID / Windows Hello)
+- 使用面部识别
+- 插入硬件安全密钥(如 YubiKey)
+### 命名密钥
+为 Passkey 设置一个便于识别的名称(如「MacBook Touch ID」),方便管理。
+Passkey 与设备和浏览器绑定。如果你更换设备,需要在旧设备上仍然可以登录时添加新的 Passkey。
+## OAuth 第三方登录
+Mix Space 支持通过 GitHub、Google 等第三方账号登录后台。
+### 配置 OAuth
+前往「设定 → OAuth」页面。详细配置步骤请参考 [OAuth 2.0 登录](/docs/configure/oauth)。
+### 将 OAuth 账号设为所有者
+首次通过 OAuth 登录后,需要在「设定 → 账号与安全」中点击「设为所有者」,将该 OAuth 账号与站点所有者身份绑定。
+## 安全设置
+### 禁用密码登录
+如果你已经配置了 Passkey 或 OAuth 登录,可以在「认证安全设置」中禁用密码登录,提高安全性。
+禁用密码登录前,请确保你至少有一种可用的替代登录方式(Passkey 或 OAuth)。否则你将无法登录后台。
+## 登录会话
+在账号与安全页面,你可以查看当前所有活跃的登录会话:
+- 设备和浏览器信息
+- 登录 IP 地址
+- 登录时间
+- 当前会话标记
+你可以手动结束其他设备的会话。
+
+================================================================================
+## 图床与存储
+Path: /docs/configure/image-storage
+================================================================================
+
+Mix Space 支持将图片和文件存储到 S3 兼容的对象存储服务(如 Cloudflare R2、AWS S3、阿里 OSS、腾讯 COS 等),替代默认的本地存储。
+## 配置 S3 图床
+### 进入图床设置
+登录后台,前往「设定 → 图床设置」。
+### 开启 S3 图床
+打开「开启 S3 图床」开关。
+### 填写 S3 配置
+| 字段 | 说明 |
+|------|------|
+| **S3 服务端点** | S3 兼容服务的 Endpoint(如 `https://.r2.cloudflarestorage.com`) |
+| **Access Key ID** | 访问密钥 ID |
+| **Secret Access Key** | 访问密钥(加密存储) |
+| **Bucket** | 存储桶名称 |
+| **Region** | 地域(Cloudflare R2 填 `auto`) |
+### 配置自定义域名(推荐)
+填写「自定义域名 (CDN)」字段,用于替换默认的 S3 URL。例如你的 CDN 域名是 `cdn.example.com`,则上传后的文件 URL 为 `https://cdn.example.com/{路径}/{文件名}`。
+### 设置文件路径前缀(可选)
+填写「文件路径前缀」来组织上传的文件。支持占位符:
+| 占位符 | 说明 |
+|--------|------|
+| `{Y}` | 年份(4 位) |
+| `{m}` | 月份 |
+| `{d}` | 日期 |
+| `{type}` | 文件类型 |
+| `{md5}` | 随机 MD5 |
+示例:`blog/{Y}/{m}/{d}` → 文件上传到 `blog/2024/01/15/` 路径下。
+开启 S3 图床后,新上传的文件会存储到 S3。之前上传到本地的文件不会自动迁移,但仍然可以正常访问。
+## 常用 S3 服务配置参考
+### Cloudflare R2
+| 字段 | 值 |
+|------|-----|
+| S3 服务端点 | `https://.r2.cloudflarestorage.com` |
+| Region | `auto` |
+| 自定义域名 | R2 绑定的自定义域名或 `r2.dev` 公开访问地址 |
+### AWS S3
+| 字段 | 值 |
+|------|-----|
+| S3 服务端点 | 留空(使用默认)或区域端点 |
+| Region | 如 `us-east-1`、`ap-southeast-1` |
+| 自定义域名 | CloudFront 分发域名 |
+### 阿里 OSS / 腾讯 COS
+按照对应服务的 S3 兼容接口文档填写 Endpoint 和 Region 即可。
+## 评论图片专用前缀
+在「评论图片路径前缀」字段中,可以为读者评论上传的图片设置独立的存储路径前缀。该字段额外支持 `{readerId}` 占位符,按读者 ID 组织目录。
+留空则使用默认路径:`comments/{readerId}/{Y}/{m}/{md5}.{ext}`
+## 备份到 S3
+在「设定 → 备份」中也可以配置 S3 信息,将数据库备份文件同时上传到 S3 存储,实现异地备份。详见 [备份与恢复](/docs/use/backup-restore)。
+
+================================================================================
+## Algolia 站内搜索
+Path: /docs/configure/algolia
+================================================================================
+
+## 介绍
+Algolia 是一个数据库实时搜索服务,能够提供毫秒级的数据库搜索服务,并且其服务能以 API 的形式方便地布局到网页、客户端、APP 等多种场景。
+像 VuePress 官方文档就是使用的 Algolia 搜索,使用 Algolia 搜索最大的好处就是方便,它会自动爬取网站的页面内容并构建索引,你只用申请一个 Algolia 服务,在网站上添加一些代码,就可以实现一个全文搜索功能。
+## 使用
+在这之前,你需要先在 Algolia 官网注册一个账号,或者直接用第三方登录。
+### 新建应用
+登录 Algolia 账号,进入控制台,在左上角点击 Applications 下列表,点击 `New Application`,填写应用名称,选择 `BUILD` 订阅(免费),选择好数据中心,点击 `Create Application`,即可创建一个应用。
+一些额外说明的地方都在图片上标注了,可参考下面的图片。
+
+### 创建索引(Index)
+在新建应用之后,你会直接跳转到如下图所示的界面,只需要在输入框中输入一个索引名称,点击 `Create Index`,即可创建一个索引。
+请记住你所创建的索引名称(Index Name),后面的步骤会用到。
+
+### 获取相关变量
+接下来,在左下角找到齿轮图标,进入设置,在右侧找到 `API Keys`,进入,这里有两个变量需要复制下来备用,分别是 `Application ID` 和 `Admin API Key`,请复制下这两个变量的值,后面的步骤会用到。
+
+### 后台配置
+进入后台,设定->系统->Algolia Search,将"开启 Algolia Search"开关打开,将前面准备的 `IndexName`、`Application ID(AppID)` 和 `Admin API Key(ApiKey)` 填入对应的框中,右上角保存即可。
+
+至此,Algolia 搜索的配置就完成了。稍等一会,就可以尝试在主页用 `Ctrl + K` 调用 Algolia 进行站内搜索了。
+
+================================================================================
+## 数据加密
+Path: /docs/configure/encryption
+================================================================================
+
+在 v3.41.0 后续版本,加入了敏感 Key 加密功能。默认为关。
+为什么需要 Key 加密。
+假设黑客通过某种手段数据库被脱库。如果开启了 Key 加密,即便是拿到了全部数据也不能解密某些关键数据,例如配置项中的各类 API Key。
+但是,也需要谨慎开启此功能,开启后你需要记住加密秘钥。否则,你也将会永远丢失这些数据。
+## 如何开启
+你可以附加 `--encrypt_enable` 来启动服务。如:
+```bash
+node index.js --encrypt_enable
+```
+可以通过附加 `--encrypt_key ` 来指定加密密钥,长度必须为 64 位,且只有小写字母和数字。请牢记此密钥。或者通过环境变量 `MX_ENCRYPT_KEY` 也可以指定密钥。
+ 若开启加密,则需注意密钥长度**必须为 64 位且只有小写字母和数字**,不然会在初始化时报错。注意这是**不可逆**的,务必保存自己的秘钥。
+ API Key.
+密钥可以通过 `openssl rand -hex 32` 命令生成。请务必牢记。
+ `MX_ENCRYPT_KEY` `--encrypt_key` 不是必须的,默认取机器的
+ [machine-id](https://www.npmjs.com/package/node-machine-id)。
+此操作是不可逆的,操作前请备份数据库。
+## 自动化加密配置(进阶指令)(非必要)
+此操作是不可逆的,操作前请备份数据库。
+```bash
+cd core
+tsx src/migration/helper/encrypt-configs.ts
+```
+## 疑难解答
+如果出现 `Invalid key length`,请你确定是否开启了此功能,并且 key 的长度是否为 64 位长度,且只有小写字母和数字。
+
+================================================================================
+## 余白 / Yohaku
+Path: /docs/themes/yohaku/index
+================================================================================
+
+## 概述
+**Yohaku**(余白)取自日文,意为**留白**。它是 [Shiro](/docs/themes/shiro/deploy) 的设计继承者,基于 Shiro 深度重构而来,延续了「纸的纯净与雪的清新」的设计语言,并在此基础上进一步打磨视觉体验与交互细节。
+
+## 开源说明
+ [Innei/Yohaku](https://github.com/Innei/Yohaku) 仓库为**设计语言的公开存档**,记录视觉规范与设计决策,不包含可运行的完整代码。
+ 完整的可部署代码以闭源方式维护于私有仓库,**需要赞助后才可获得访问权限**。
+### 如何获取完整实现
+1. 前往 [github.com/sponsors/Innei](https://github.com/sponsors/Innei) 赞助
+2. 赞助后通过 [Issues](https://github.com/Innei/Yohaku/issues) 或邮件告知你的 GitHub 用户名
+3. 作者会手动添加私有仓库的访问权限
+[](https://github.com/sponsors/Innei)
+## 设计哲学
+整站以**个人书写**为隐喻。页面像一封徐徐展开的信纸,文字与空白共同构成节奏,内容如手帐般自然散落。
+- **颜色是克制的** — 浅色模式接近真实纸张的米白,深色模式沉入暖灰
+- **动画是呼吸式的** — 元素随滚动自然浮现,而非弹出
+- **字体是有质感的** — 标题用衬线字体,注释以斜体呈现
+- **交互是低调的** — 悬停时仅颜色微微加深,如纸面被指尖轻触
+## 设计规范
+| 维度 | 浅色 | 深色 |
+|------|------|------|
+| 强调色 | 浅葱 `#33A6B8` | 桃 `#F596AA` |
+| 背景底色 | `#fefefb`(纸张本白) | `rgb(28,28,30)`(暖灰夜色) |
+| 动效缓动 | `cubic-bezier(0.22, 1, 0.36, 1)` | 同左 |
+| 基础字号 | 14px | 同左 |
+## 与 Shiro 的关系
+Yohaku 是 Shiro 的下一代演进。如果你正在使用 Shiro,可以继续使用——Shiro 仍然是一个完整的开源主题。Yohaku 在 Shiro 的基础上提供了更精致的视觉设计和更多闭源独有功能。
+## 相关链接
+- [Innei/Yohaku](https://github.com/Innei/Yohaku) — 开源设计存档
+- [Innei/Shiro](https://github.com/Innei/Shiro) — 开源前身
+- [在线演示](https://innei.in) — 作者的个人博客,使用 Yohaku 驱动
+
+================================================================================
+## 配置
+Path: /docs/themes/yohaku/config
+================================================================================
+
+# 配置项
+Yohaku 的配置沿用 Shiro 的配置体系,在 Mix Space 后台「配置与云函数」页面中,创建一条 `theme` 引用、名称为 `shiro` 的配置项(数据类型 JSON 或 YAML)。配置参考详见 [Shiro 的部署页面](https://mx-space.js.org/docs/themes/shiro/deploy#设置主题配置)。
+ Yohaku 复用了 `shiro` 这个配置键名,如果你从 Shiro 迁移到 Yohaku,无需更改配置名称。
+## 页脚信息 (`footer`)
+此部分定义页脚的部分信息,主要包括备案、建站年份和页脚导航三部分。
+### 备案信息 (`otherInfo.icp`)
+**如何使用**: 根据示例,修改位于 `text` 的备案号以及备案号所指向的链接 `link`。
+### 建站年份 (`otherInfo.date`)
+**如何使用**: `{{now}}` 指向当前年份,其他略。
+### 页脚导航 (`linkSections`)
+分类包括 `name` 和 `links` 两个字段,对应分类名字及其下链接,其下链接又分为 `name`、`href`、`external` 三个字段,对应链接名字,指向链接和是否外链三个属性。
+**如何使用**: 根据自己需要增删或修改特定链接及分类,需要注意如果指向外链的话需要加一行 `"external": true`。
+## 站点信息 (`config.site`)
+此部分包含了网站的基础信息设置,例如 favicon(网站图标)的配置。
+### Favicon
+- **`favicon`**: 设置网站在浅色模式下使用的图标。
+- **`faviconDark`**: 设置网站在深色模式下使用的图标。
+## Hero 部分 (`config.hero`)
+`hero` 部分定义了网站首页的主要欢迎信息或介绍部分,这是访问者首次进入网站时看到的部分。
+### Title 模板 (`title.template`)
+包括多个元素(如 `span`, `code`, `h1` 等),每个元素都可以自定义文本内容和样式。
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `type` | `string` | 渲染标签,如 `span`、`code`、`br`。`br` 表示显式换行。 |
+| `text` | `string` | 文本内容。 |
+| `class` | `string` | Tailwind CSS 类名。 |
+| `style` | `object` | **推荐**。内联样式对象,可直接写 CSS 属性(如 `fontWeight`、`color`、`animation` 等),不依赖 Tailwind JIT 扫描,且能跟随 CSS 变量自动适配暗色主题。 |
+**如何使用**: 修改 `text` 和 `style` 字段来自定义标题的文本内容和样式。你可以通过添加或删除元素来调整标题的结构。
+### 描述 (`description`)
+提供了对主页 `hero` 部分的简短描述。
+**如何使用**: 直接修改 `description` 的值以更改介绍文本。
+### 一言 (`hitokoto`)
+提供自定义首页一言的功能。
+接受一个对象,包含 `random` 和 `custom` 两个可选字段。
+- 当存在 `random` 字段且值为 `true` 时,将会随机获取一言,优先级高于 `custom` 字段。
+- 当存在 `custom` 字段时,将会使用自定义的一言。
+- 如果两个字段都不存在,将会使用默认的一言。
+```ts
+interface Hitokoto {
+ random?: boolean
+ custom?: string
+}
+```
+## 自定义脚本 (`config.custom`)
+可以配置自定义的 CSS, Script。
+### Scripts (`scripts`)
+接受一个 [Script](https://nextjs.org/docs/app/api-reference/components/script#props) Props 参数数组。
+### Styles (`styles`)
+自定义 CSS。接受一个字符串数组。
+### JavaScript tag (`js`)
+自定义 JS 脚本。接受一个字符串数组。
+### CSS href link (`css`)
+加载外部 CSS,接受一个 CSS 外部样式表链接数组。
+## 模块 (`config.module`)
+此部分配置了网站的一些特定功能模块,比如活动跟踪、捐赠支持、社交媒体链接等。
+### 实时活动 (`activity`) 模块
+- **`enable`**: 控制模块是否启用。
+- **`endpoint`**: 指定活动更新的服务器端点。
+**如何使用**: 若需开启活动跟踪功能,将 `enable` 设为 `true` 并设置 `endpoint` 为处理活动数据的服务器地址。
+### 捐赠 (`donate`) 模块
+- **`enable`**: 控制捐赠模块是否启用。
+- **`link`**: 提供捐赠页面的链接。
+- **`qrcode`**: 提供一或多个捐赠二维码图片的链接。
+**如何使用**: 启用捐赠功能,并提供捐赠链接或捐赠二维码,以便支持者可以直接进行捐赠。
+### 社交媒体 (`bilibili`) 模块
+- **`liveId`**: b 站直播间 ID
+### OpenPanel 模块
+[OpenPanel](https://openpanel.dev) 是一个开源的网站分析工具。
+- **`enable`**: 控制 OpenPanel 功能是否启用。
+- **`id`**: OpenPanel 的 ID。
+- **`url`**: OpenPanel 的访问地址。
+**如何使用**: 如果你使用 OpenPanel 进行网站分析,通过这些配置连接并启用面板。
+### 文章列表设定 (`posts`)
+- **`mode`**: 文章列表的预览模式。可选值:`"loose"`(默认)、`"compact"`
+两个模式,紧凑模式和松散模式。
+### RSS 配置 (`rss`)
+- **`noRSS`**: 设为 `true` 可禁用 RSS 输出。
+- **`custom_elements`**: 自定义 RSS 元素数组。
+### 签名动画 (`signature`) 模块
+- **`svg`**: 签名的 SVG 代码。
+- **`animated`**: 是否启用动画效果,默认为 `true`。
+**如何使用**: SVG 代码可通过 [此网站](https://danmarshall.github.io/google-font-to-svg-path/) 生成。
+ 受限于 JSON 语法规则,SVG 代码需替换所有的 `"` 为 `\"`,否则会报错。
+### OG 图片 (`og`)
+- **`avatar`**: 自定义 Open Graph 图片中的头像 URL。
+### 订阅 (`subscription`)
+- **`tg`**: Telegram 频道链接,用于展示订阅入口。
+## 配置示例
+```json
+{
+ "footer": {
+ "otherInfo": {
+ "date": "2020-{{now}}",
+ "icp": {
+ "text": "萌 ICP 备 20236136 号",
+ "link": "https://icp.gov.moe/?keyword=20236136"
+ }
+ },
+ "linkSections": [
+ {
+ "name": "关于",
+ "links": [
+ { "name": "关于本站", "href": "/about-site" },
+ { "name": "关于我", "href": "/about" },
+ {
+ "name": "关于此项目",
+ "href": "https://github.com/Innei/Yohaku",
+ "external": true
+ }
+ ]
+ },
+ {
+ "name": "更多",
+ "links": [
+ { "name": "时间线", "href": "/timeline" },
+ { "name": "友链", "href": "/friends" }
+ ]
+ },
+ {
+ "name": "联系",
+ "links": [
+ { "name": "写留言", "href": "/message" },
+ { "name": "GitHub", "href": "https://github.com/innei", "external": true }
+ ]
+ }
+ ]
+ },
+ "config": {
+ "color": {
+ "light": ["#33A6B8", "#FF6666", "#26A69A", "#fb7287", "#69a6cc"],
+ "dark": ["#F596AA", "#A0A7D4", "#ff7b7b", "#99D8CF", "#838BC6"]
+ },
+ "site": ,
+ "hero": {
+ "title": {
+ "template": [
+ {
+ "type": "span",
+ "text": "Hi, I'm ",
+ "style": { "fontWeight": 300, "opacity": 0.85 }
+ },
+ {
+ "type": "span",
+ "text": "Innei",
+ "style": {
+ "fontWeight": 500,
+ "color": "var(--color-accent)",
+ "letterSpacing": "-0.02em"
+ }
+ },
+ {
+ "type": "span",
+ "text": " 👋",
+ "style": {
+ "fontWeight": 300,
+ "display": "inline-block",
+ "transform": "rotate(-8deg)"
+ }
+ },
+ { "type": "br" },
+ {
+ "type": "span",
+ "text": "A NodeJS Full Stack ",
+ "style": { "fontWeight": 300, "opacity": 0.8 }
+ },
+ {
+ "type": "code",
+ "text": "",
+ "style": {
+ "display": "inline-block",
+ "fontFamily": "var(--font-mono)",
+ "fontSize": "0.72em",
+ "fontWeight": 500,
+ "padding": "0.25em 0.55em",
+ "borderRadius": "0.35em",
+ "backgroundColor": "color-mix(in srgb, var(--color-accent) 10%, transparent)",
+ "color": "var(--color-accent)",
+ "border": "1px solid color-mix(in srgb, var(--color-accent) 22%, transparent)"
+ }
+ },
+ {
+ "type": "span",
+ "style": {
+ "display": "inline-block",
+ "width": "2px",
+ "height": "0.9em",
+ "backgroundColor": "var(--color-accent)",
+ "marginLeft": "2px",
+ "animation": "blink 1.2s linear infinite"
+ }
+ }
+ ]
+ },
+ "description": "An independent developer coding with love."
+ },
+ "module": {
+ "activity": {
+
+================================================================================
+## 部署
+Path: /docs/themes/shiro/deploy
+================================================================================
+
+ Shiro 的下一代演进版本 **[余白 / Yohaku](/docs/themes/yohaku)** 已经发布。Yohaku 基于 Shiro 深度重构,提供更精致的视觉设计与更多功能。如果你正在寻找最新的体验,请前往 [Yohaku 文档](/docs/themes/yohaku) 了解更多。
+## 前提要求
+- 你已安装 Mix Space 后端并且已启动
+- (选择 Vercel 部署)已注册 [Vercel](https://vercel.com/) 和 [GitHub](https://github.com/) 账号
+ 自 Core v7 起,已抛弃 Clerk,取而代之的是 GitHub 和 Google 的 OAuth 2.0,
+ 配置步骤请参考 [OAuth 2.0](/docs/configure/oauth)
+ ~~请注意,Shiro 主题的部署教程与初版有所不同,如果你已经部署过 Shiro
+ 主题,请重新阅读本文档(尤其是填入配置文件环节,配置有所变化),并阅读
+ [「移除 Edge Config」](#移除-edge-config) 部分。~~
+## 准备步骤
+export function FAQBox({ title, children }) {
+ return (
+
+
+ {title}
+
+ {children}
+
+ )
+}
+### 设置主题配置
+进入 Mix Space 后台,进入「配置与云函数」页面,点击右上角的新增按钮,在编辑页面中,填入以下设置:
+- 名称:`shiro`
+- 引用:`theme`
+- 数据类型:`JSON`
+- 数据:(点击下方的按钮复制)
+ 请注意,这份配置你需要自行修改成符合你的需求的配置。直接使用下面的配置可能会导致你的博客无法按照你的预期运行。
+ 下面的配置可能不全,更多配置项的信息请移步 [配置项](./config) 了解。
+ 此外,配置也可写成 yaml 格式,此时数据类型应选择 `YAML`。
+```json showLineNumbers
+{
+ "footer": {
+ "otherInfo": {
+ "date": "2020-{{now}}",
+ "icp": {
+ "text": "萌 ICP 备 20236136 号",
+ "link": "https://icp.gov.moe/?keyword=20236136"
+ }
+ },
+ "linkSections": [
+ {
+ "name": "关于",
+ "links": [
+ {
+ "name": "关于本站",
+ "href": "/about-site"
+ },
+ {
+ "name": "关于我",
+ "href": "/about"
+ },
+ {
+ "name": "关于此项目",
+ "href": "https://github.com/innei/Shiro",
+ "external": true
+ }
+ ]
+ },
+ {
+ "name": "更多",
+ "links": [
+ {
+ "name": "时间线",
+ "href": "/timeline"
+ },
+ {
+ "name": "友链",
+ "href": "/friends"
+ },
+ {
+ "name": "监控",
+ "href": "https://status.innei.in/status/main",
+ "external": true
+ }
+ ]
+ },
+ {
+ "name": "联系",
+ "links": [
+ {
+ "name": "写留言",
+ "href": "/message"
+ },
+ {
+ "name": "发邮件",
+ "href": "mailto:i@innei.ren",
+ "external": true
+ },
+ {
+ "name": "GitHub",
+ "href": "https://github.com/innei",
+ "external": true
+ }
+ ]
+ }
+ ]
+ },
+ "config": {
+ "color": {
+ "light": [
+ "#33A6B8",
+ "#FF6666",
+ "#26A69A",
+ "#fb7287",
+ "#69a6cc",
+ "#F11A7B",
+ "#78C1F3",
+ "#FF6666",
+ "#7ACDF6"
+ ],
+ "dark": [
+ "#F596AA",
+ "#A0A7D4",
+ "#ff7b7b",
+ "#99D8CF",
+ "#838BC6",
+ "#FFE5AD",
+ "#9BE8D8",
+ "#A1CCD1",
+ "#EAAEBA"
+ ]
+ },
+ "bg": [
+ "/static/images/F0q8mwwaIAEtird.jpeg",
+ "/static/images/IMG_2111.jpeg.webp.jpg"
+ ],
+ "custom": {
+ "css": [],
+ "styles": [],
+ "js": [],
+ "scripts": []
+ },
+ "site": ,
+ "hero": {
+ "title": {
+ "template": [
+ {
+ "type": "h1",
+ "text": "Hi, I'm ",
+ "class": "font-light text-4xl"
+ },
+ {
+ "type": "h1",
+ "text": "Innei",
+ "class": "font-medium mx-2 text-4xl"
+ },
+ {
+ "type": "h1",
+ "text": "👋。",
+ "class": "font-light text-4xl"
+ },
+ {
+ "type": "br"
+ },
+ {
+ "type": "h1",
+ "text": "A NodeJS Full Stack ",
+ "class": "font-light text-4xl"
+ },
+ {
+ "type": "code",
+ "text": "",
+ "class": "font-medium mx-2 text-3xl rounded p-1 bg-gray-200 dark:bg-gray-800/0 hover:dark:bg-gray-800/100 bg-opacity-0 hover:bg-opacity-100 transition-background duration-200"
+ },
+ {
+ "type": "span",
+ "class": "inline-block w-[1px] h-8 -bottom-2 relative bg-gray-800/80 dark:bg-gray-200/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 group-hover:animation-blink"
+ }
+ ]
+ },
+ "description": "An independent developer coding with love."
+ },
+ "module": {
+ "activity": {
+ "enable": true,
+ "endpoint": "/fn/ps/update"
+ },
+ "donate": {
+ "enable": true,
+ "link": "https://afdian.net/@Innei",
+ "qrcode": [
+ "/static/images/20191211132347.png",
+ "/static/images/0424213144.png"
+ ]
+ },
+ "bilibili": {
+ "liveId": 1434499
+ },
+ "rss": {
+ "noRSS": true
+ }
+ }
+ }
+}
+```
+
+================================================================================
+## 配置
+Path: /docs/themes/shiro/config
+================================================================================
+
+# 配置项
+## 页脚信息 (`footer`)
+此部分定义页脚的部分信息,主要包括备案、建站年份和页脚导航三部分。
+### 备案信息 (`otherInfo.icp`)
+**如何使用**: 根据示例,修改位于 `text` 的备案号以及备案号所指向的链接 `link`。
+### 建站年份 (`otherInfo.date`)
+**如何使用**: `{{now}}` 指向当前年份,其他略。
+### 页脚导航 (`linkSections`)
+分类包括 `name` 和 `links` 两个字段,对应分类名字及其下链接,其下链接又分为 `name`、`href`、`external` 三个字段,对应链接名字,指向链接和是否外链三个属性。
+**如何使用**: 根据自己需要增删或修改特定链接及分类,需要注意如果指向外链的话需要加一行 `"external": true`。
+## 站点信息 (`config.site`)
+此部分包含了网站的基础信息设置,例如 favicon(网站图标)的配置。
+### Favicon
+- **`favicon`**: 设置网站在浅色模式下使用的图标。
+- **`faviconDark`**: 设置网站在深色模式下使用的图标。
+## Hero 部分 (`config.hero`)
+`hero` 部分定义了网站首页的主要欢迎信息或介绍部分,这是访问者首次进入网站时看到的部分。
+### Title 模板 (`title.template`)
+包括多个元素(如 `h1`, `code`, `span`),每个元素都可以自定义文本内容和样式(通过 CSS 类)。
+**如何使用**: 修改 `text` 和 `class` 字段来自定义标题的文本内容和样式。你可以通过添加或删除元素来调整标题的结构。
+### 描述 (`description`)
+提供了对主页 `hero` 部分的简短描述。
+**如何使用**: 直接修改 `description` 的值以更改介绍文本。
+## 自定义脚本 (`config.custom`)
+可以配置自定义的 CSS, Script。
+### Scripts (`scripts`)
+接受一个 [Script](https://nextjs.org/docs/app/api-reference/components/script#props) Props 参数数组。
+### Styles (`styles`)
+自定义 CSS。接受一个字符串数组。
+### JavaScript tag (`js`)
+自定义 JS 脚本。接受一个字符串数组。
+### CSS href link (`css`)
+加载外部 CSS,接受一个 CSS 外部样式表链接数组。
+## 模块 (`config.module`)
+此部分配置了网站的一些特定功能模块,比如活动跟踪、捐赠支持、社交媒体链接等。
+### 实时活动 (`activity`) 模块
+- **`enable`**: 控制模块是否启用。
+- **`endpoint`**: 指定活动更新的服务器端点。
+**如何使用**: 若需开启活动跟踪功能,将 `enable` 设为 `true` 并设置 `endpoint` 为处理活动数据的服务器地址。
+### 捐赠 (`donate`) 模块
+- **`enable`**: 控制捐赠模块是否启用。
+- **`link`**: 提供捐赠页面的链接。
+- **`qrcode`**: 提供一或多个捐赠二维码图片的链接。
+**如何使用**: 启用捐赠功能,并提供捐赠链接或捐赠二维码,以便支持者可以直接进行捐赠。
+### 社交媒体 (`bilibili`) 模块
+- **`liveId`**: b 站直播间 ID
+
+================================================================================
+## 额外功能
+Path: /docs/themes/shiro/extra
+================================================================================
+
+# 额外功能
+## 扩展的 Markdown 语法
+参考 https://shiro.innei.in/#/markdown
+**对于 LinkCard 的解析,某些需要你填写 API Key,以下的键值都是填写在 .env 环境变量中**
+- GitHub,默认直接用浏览器访问,可能受到 rate limit,可以填写 `GH_TOKEN` 以保证 API 可达性。
+- TMDB,必须填写 `TMDB_API_KEY` 才可以正确解析 tmdb 的链接。参考 https://post.smzdm.com/p/a5op4w33/ 这里获取 TOKEN
+## 我的动态
+Shiro 主题中,有一个可以在顶部显示博主当前正在做的事情的功能,这个功能是通过云函数和 ProcessReporter 软件实现的。
+ 非常感谢 Innei, timochan, TNXG 的贡献,目前 ProcessReporter 已支持全平台!
+### 配置云函数
+进入后台,点击左侧菜单栏的「其他 -> 配置与云函数」,然后点击新建按钮,在选项卡中填入以下信息:
+- 名称:`update`
+- 引用:`ps`
+- 数据类型:`Function`
+- 请求方式:`POST`
+这个地方还需要设置一个密钥,在 Secret 中填入 `key`,在 Value 中填入你自己的密钥。
+这个密钥将用于验证你的软件是否有权限更新博主的动态,所以请务必设置一个复杂的密钥。
+**密钥在后面的步骤中还需要用到,所以请务必记住。**
+上方没有提到的选项都不需要填写,然后在右侧的代码编辑器中填入下面链接中的代码:
+点击保存按钮,云函数就配置完成了。
+ 请关注此代码的更新,它可能会随时变化,你需要及时更新它们
+### 配置主题配置
+继续在「配置与云函数」页面,找到「theme -> shiro」配置,点击编辑,进入编辑页面,在代码中找到 `module`,加入 activity 配置,如下:(高亮部分)
+```json {14,15,16,17}
+{
+ "module": {
+ "donate": {
+ "enable": false,
+ "link": "https://afdian.net/@Innei",
+ "qrcode": [
+ "https://cdn.jsdelivr.net/gh/Innei/img-bed@master/20191211132347.png",
+ "https://cdn.innei.ren/bed/2023/0424213144.png"
+ ]
+ },
+ "bilibili": {
+ "liveId": 1434499
+ },
+ "activity": {
+ "enable": true,
+ "endpoint": "fn/ps/update"
+ }
+ }
+}
+```
+### 配置软件
+前往对应着你的电脑系统的软件的 GitHub 仓库,下载并打开 ProcessReporter。
+由于不同平台有不同的使用方法,不同的软件我们会在下方具体讲述。
+### ProcessReporter `Mac`
+打开软件后,你会发现你的系统菜单栏中多了一个图标,点击图标,然后点击「设置」,在弹出的窗口中填入你的信息:
+- Endpoint:`{你的API地址}/fn/ps/update` (请将 `{你的API地址}` 替换为你的 API 地址,如:`https://api.example.com/api/v2`)
+- API Key:填入你刚刚在云函数中设置的密钥
+如果你希望软件在开机时自动启动,可以勾选「Launch at login」选项。
+接着关闭窗口,再次点击菜单栏中的图标,点击「Enable」即可。如果一切正常,刷新一下你的博客就可以在博客顶部看到你的动态了。
+### ProcessReporter `Windows`
+Windows 版本的使用问题,请前往 [TNXG/ProcessReporterWinpy](https://github.com/TNXG/ProcessReporterWinpy#readme) 查看。
+#### 使用 GUI 版本
+在 [Releases](https://github.com/TNXG/ProcessReporterWinpy/releases) 页面下载 `ProcessReporterWinpy_Launcher.exe`
+,配置好 `config.yml` 文件,然后运行 `ProcessReporterWinpy_Launcher.exe` 即可。
+`config.yml` 配置具体配置项以及说明请参考 [TNXG/ProcessReporterWinpy](https://github.com/TNXG/ProcessReporterWinpy#readme)。
+#### 使用预编译的二进制文件
+在 [Releases](https://github.com/TNXG/ProcessReporterWinpy/releases) 页面下载 `ProcessReporterWinpy.exe`,配置好 `config.yml` 文件后,在终端运行即可,示例如下
+```powershell
+processforwinpy.exe --path "运行目录的路径"
+```
+`config.yml` 配置具体配置项以及说明请参考 [TNXG/ProcessReporterWinpy](https://github.com/TNXG/ProcessReporterWinpy#readme)。
+#### 使用源代码
+下载代码后,修改 `config.yml` 文件,填入你的信息:
+- api_url:`{你的API地址}/fn/ps/update` (请将 `{你的API地址}` 替换为你的 API 地址,如:`https://api.example.com/api/v2`)
+- api_key:填入你刚刚在云函数中设置的密钥
+- report_time: 上报间隔(单位:秒)
+接着运行程序即可。如果一切正常,刷新一下你的博客你就可以在博客顶部看到你的动态了。
+### ProcessReporter `Linux`
+在仓库的 [Releases](https://github.com/ttimochan/processforlinux/releases) 页面下载对应的二进制包,解压运行即可,具体请参照项目的 README 进行配置运行。
+安装完成后,新建 `.env.process` 文件,填入你的信息:
+```env
+# 你的 key
+API_KEY=your_key
+# 你的云函数地址
+API_URL={你的API地址}/fn/ps/update
+# 上报时间间隔,单位为秒
+REPORT_TIME=30
+# 是否开启媒体状态上报
+MEDIA_ENABLE=true
+# 是否打印日志
+LOG_ENABLE=true
+```
+然后执行程序即可。如果一切正常,刷新一下你的博客你就可以在博客顶部看到你的动态了。
+如果有什么疑问,可以去阅读该项目的 [README](https://github.com/ttimochan/processforlinux#readme)
+
+## 个人状态展示
+
+设置当前的状态。
+### 配置云函数
+进入后台,点击左侧菜单栏的「其他 -> 配置与云函数」,然后点击新建按钮,在选项卡中填入以下信息:
+- 名称:`status`
+- 引用:`shiro`
+- 数据类型:`Function`
+- 请求方式:`ALL`
+这个地方还需要设置一个密钥,在 Secret 中填入 `key`,在 Value 中填入你自己的密钥。
+这个密钥将用于验证你的软件是否有权限更新当前状态,所以请务必设置一个复杂的密钥。
+**密钥在后面的步骤中还需要用到,所以请务必记住。**
+上方没有提到的选项都不需要填写,然后在右侧的代码编辑器中填入下面链接中的代码:
+点击保存按钮,云函数就配置完成了。
+ 请关注此代码的更新,它可能会随时变化,你需要及时更新它们
+### 设置状态
+在主页登录之后,你可以点击此头像的右下方设置状态。
+
+================================================================================
+## 闭源功能
+Path: /docs/themes/shiro/pro
+================================================================================
+
+# 闭源功能
+本文档介绍 Shiro 主题闭源版本的特有功能。
+## 配置项
+### 一言 (`hitokoto`)
+提供自定义首页一言的功能。
+接受一个对象,包含 `random` 和 `custom` 两个可选字段。
+当存在 `random` 字段时,将会随机获取一言。优先级高于 `custom` 字段。
+当存在 `custom` 字段时,将会使用自定义的一言。
+如果两个字段都不存在,将会使用默认的一言。
+```ts
+interface Hitokoto {
+ random?: boolean
+ custom?: string
+}
+```
+### OpenPanel 模块
+[OpenPanel](https://openpanel.dev) 是一个交互式面板工具。
+- **`enable`**: 控制 OpenPanel 功能是否启用。
+- **`id`**: OpenPanel 的 ID。
+- **`url`**: OpenPanel 的访问地址。
+**如何使用**: 如果你使用 OpenPanel 提供交互式面板或其他功能,通过这些配置连接并显示面板。
+### 签名动画 (`signature`) 模块
+- **`svg`**: 签名的 svg 代码。
+**如何使用**: 请参考[签名动画](#签名动画)部分。
+### 文章列表设定 (`posts`)
+- **`mode`**: 文章列表的预览模式。可选的值:`"loose"`(默认值) `"compact"`
+两个模式,紧凑模式和松散模式。
+## 功能特性
+### AI 参与声明
+Shiro 主题支持在文章的 Meta 数据中声明 AI 的参与程度,实现创作过程的透明化。编辑时可在 `meta.aiGen` 字段选择声明类型,前端会自动展示对应的 AI 参与徽章。
+ 多选说明:
+
+ - 手作 和 完全 为单选类型,选择后会清除其他选项
+ - 其他类型支持多选,可以组合声明多种 AI 参与方式
+
+支持的声明类型:
+| 类型 | 说明 |
+| -------- | -------------------------------------------------- |
+| 手作 | 本文内容完全由作者独立创作,未使用任何 AI 辅助 |
+| 辅助写作 | AI 辅助构思/结构/表达,作者审阅并修改后发布 |
+| 润色 | AI 用于语言润色/语法调整,不改变核心观点 |
+| 完全 | 内容主要由 AI 生成,作者进行了选择与编辑后发布 |
+| 故事整理 | 作者口述内容,AI 进行整理与润色后发布 |
+| 标题生成 | 标题由 AI 生成或优化 |
+| 校对 | AI 协助校对文本,检查拼写、语法和逻辑问题 |
+| 灵感提供 | AI 提供创意灵感或写作思路 |
+| 改写 | AI 将内容改写成不同风格或语气 |
+| AI 作图 | 文章中的图片、表格或流程图由 AI 生成或辅助绘制 |
+### 动态背景系统
+Shiro 主题内置基于 WebGL 的高性能粒子物理背景系统,支持多种效果自动切换:
+#### 粒子物理背景
+基于牛顿力学的粒子物理系统,响应页面滚动产生惯性运动效果。
+**技术特点:**
+- 滚动驱动力:与滚动速度成正比
+- 阻力模拟:每帧保留 85% 速度,模拟能量耗散
+- 恢复力系统:停止滚动后逐渐回归原始轨道
+- 智能分布:80% 粒子避开内容区域,避免干扰阅读
+#### 雪花背景
+程序化生成的六重对称雪花,支持完整的物理效果。
+**可配置参数:**
+- 风力系统:风速、风向控制
+- 重力模拟:可调节下落速度
+- 湍流效果:随机扰动的自然飘落
+- 深度模糊:基于距离的景深效果
+- 雪花密度:可调整粒子数量
+#### 萤火虫背景
+互动式萤火虫动画,营造梦幻氛围。
+**交互特性:**
+- 鼠标点击惊吓:萤火虫会逃离点击区域
+- 多种颜色:黄绿色、绿色、淡蓝色
+- 脉动闪烁:自然的亮度变化效果
+- 智能避让:自动避开内容阅读区域
+#### 季节自动切换
+系统会根据当前日期和主题自动选择合适的背景效果:
+| 条件 | 背景效果 |
+| ----------------------------- | ------------------------- |
+| 冬季(12 月 -2 月)+ 深色模式 | 雪花背景 |
+| 其他情况 | 粒子物理背景 / 萤火虫背景 |
+文章详情页默认不显示背景动画,以保持阅读体验。
+### 签名动画
+
+在「配置与云函数」页面,找到「theme -> shiro」配置,进入编辑页面,在代码中找到 `module`,加入 `signature` 配置,如下(高亮部分):
+其中 svg 后填生成的 svg 代码,可通过 [此网站](https://danmarshall.github.io/google-font-to-svg-path/) 进行生成。
+ 受限于 Json 语法规则,此处 svg 代码需替换所有的 `"` 为 `\"`,否则会报错。
+```json {18,19,20}
+{
+ "module": {
+ "donate": {
+ "enable": false,
+ "link": "https://afdian.net/@Innei",
+ "qrcode": [
+ "https://cdn.jsdelivr.net/gh/Innei/img-bed@master/20191211132347.png",
+ "https://cdn.innei.ren/bed/2023/0424213144.png"
+ ]
+ },
+ "bilibili": {
+ "liveId": 1434499
+ },
+ "activity": {
+ "enable": true,
+ "endpoint": "/fn/ps/update"
+ },
+ "signature": {
+ "svg": ""
+ }
+ }
+}
+```
+
+================================================================================
+## Kami 主题
+Path: /docs/themes/kami
+================================================================================
+
+> 下一个代替项目将会是 Shiro,当它完成之时,我便不再投入任何精力到 Kami 中。迎接未来总需要舍弃一些东西,非常感谢大家三年来使用 Kami,不管你是谁,都需要对你说声谢谢。**—— Innei**
+## 现状
+Kami 目前由 `wibus-wee` 维护,处于最小程度更新的兼容状态。更新仅针对与 Core 接口不兼容的问题,以确保 Kami 能继续正常运行。
+由于 Kami 主题已进入存档状态,本文档仅保持最小程度更新。请注意:使用 Kami 需要 Linux 内核版本 ≥ 4.19。
+如发现 Kami 与 Core 的不兼容问题,请在 Kami 仓库提交 issue 并详细描述问题。
+## 安装步骤
+### 检查内核版本
+```bash
+uname -r
+```
+如果你的内核版本小于 4.19,请升级内核。或者使用最新的 Ubuntu / Debian。
+### 克隆项目
+```bash
+git clone https://github.com/mx-space/kami.git --depth=1
+cd kami && git fetch --tags && git checkout $(git rev-list --tags --max-count=1)
+```
+
+### 安装依赖
+```bash
+git lfs fetch --all
+git lfs pull
+pnpm i
+```
+### 配置 ENV
+1. 复制 .env.example 为 .env
+2. 编辑 .env 文件,它看起来应该是这个样子的
+```env
+# API 地址
+NEXT_PUBLIC_API_URL=https://server.test.cn/api/v2
+# GATEWAY 地址
+NEXT_PUBLIC_GATEWAY_URL=https://server.test.cn
+#前端使用的配置项名字
+NEXT_PUBLIC_SNIPPET_NAME=kami
+# 如果使用 CDN, 修改产物前缀;一般留空
+ASSETPREFIX=
+```
+
+### 开始构建
+```bash
+pnpm build
+```
+### 启动前端
+```bash
+pnpm prod:pm2
+```
+## 更新指南
+根据是否对 Kami 进行过修改,可以选择以下两种更新方式:
+### 标准更新
+适用于未修改源代码的用户。
+```bash
+cd ~/mx-space/kami
+git pull origin master
+pnpm i && pnpm build
+pm2 start
+```
+即使未进行源码修改,也可能遇到代码合并冲突。此时建议参考下方的手动更新方法。
+### 手动更新
+适用于修改过源码的用户。
+将 `kami` 文件夹改为任意名字,例如修改为 `kami.d`,然后拉取 kami 前端仓库,更新到稳定版本:
+```bash
+cd ~/mx-space
+git clone https://github.com/mx-space/kami.git --depth=1
+cd kami && git fetch --tags && git checkout $(git rev-list --tags --max-count=1)
+```
+然后将更新前之前配置时修改过的文件,如在 `kami.d` 中的 `.env` 和 `public` 文件夹复制到 `kami`,将你的修改的部分依次修改替换完成。
+安装依赖、构建、启动前端:
+```bash
+pnpm i
+pnpm build
+pm2 start
+```
+
+================================================================================
+## Yun 主题
+Path: /docs/themes/yun
+================================================================================
+
+由于 Yun 主题将不再维护,此文档将不再更新,但是你仍然可以使用它。
+## 安装步骤
+### 克隆项目
+```bash
+git clone https://github.com/mx-space/mx-web-yun.git --depth=1
+```
+
+### 安装依赖
+```bash
+pnpm i
+```
+### 配置服务
+如果你部署 Mix Space 后端与部署 Yun 前端在同一台服务器,并且后端监听的端口为 2333,那么你可以跳过这一步。
+1. 前往 `./server/constant.ts`
+```ts {3,4,5} filename="./server/constant.ts"
+export const isProduction = process.env.NODE_ENV === 'production'
+export const isDev = !isProduction
+export const apiBase = isDev
+ ? 'https://api.innei.ren/v2/'
+ : 'http://localhost:2333/api/v2/'
+```
+修改为你的后端 API 地址。
+### 开始构建
+```bash
+pnpm build
+```
+### 启动前端
+```bash
+pnpm pm2
+```
+
+================================================================================
+## 社区分享
+Path: /docs/themes/community
+================================================================================
+
+你可以参考他们的部署方式,但我们不保证它们的可用性。如果你也有教程想要与大家分享的话,欢迎您向文档提交 [Pull Request](https://github.com/mx-space/docs/pulls) 以分享您的部署方式。
+前端部署方式拓展博文教程 | By Mikuの鬆
+前端部署方式拓展博文教程 | By wuhang2003
+
+================================================================================
+## 使用指南
+Path: /docs/use/index
+================================================================================
+
+部署完成后,这篇指南帮助你日常使用 Mix Space。
+温馨提示:此指南需要一定的基础知识 & 理解能力,请准备好哦~
+ }
+ href={'/docs/use/writing'}
+ title="写作工作流"
+ >
+ 后台编辑器、Obsidian 插件、Markdown 导入导出
+
+ }
+ href={'/docs/use/content'}
+ title="内容管理"
+ >
+ 文章、日记、页面的发布与管理,分类与专题
+
+ }
+ href={'/docs/use/comments'}
+ title="评论管理"
+ >
+ 评论审核、反垃圾、AI 审核、评论图片上传
+
+ }
+ href={'/docs/use/friends'}
+ title="友链管理"
+ >
+ 友链添加与审核、申请规则、头像转内链、健康检查
+
+ }
+ href={'/docs/use/says'}
+ title="说说"
+ >
+ 发布短内容、碎片化想法与一句话动态
+
+ }
+ href={'/docs/use/projects'}
+ title="项目展示"
+ >
+ 管理和展示个人项目与作品集
+
+
+ 图片、图标、头像和文件的上传管理与自定义命名
+
+ }
+ href={'/docs/use/ai-features'}
+ title="AI 功能"
+ >
+ 摘要、精读、多语言翻译、写作助手、评论审核、AI Agent
+
+ }
+ href={'/docs/use/webhook'}
+ title="Webhook 与事件通知"
+ >
+ 配置 Webhook 推送事件到外部服务
+
+ }
+ href={'/docs/use/mail-subscribe'}
+ title="邮件与订阅"
+ >
+ 邮件服务配置、读者订阅推送、Bark 通知
+
+ }
+ href={'/docs/use/serverless'}
+ title="云函数扩展"
+ >
+ 扩展 Mix Space 能力的云函数 Snippets
+
+ }
+ href={'/docs/use/analytics'}
+ title="站点统计"
+ >
+ 访问量、流量来源、设备分布和热门路径
+
+ }
+ href={'/docs/use/cron-tasks'}
+ title="定时任务"
+ >
+ 系统定时清理、搜索引擎推送、索引重建
+
+ }
+ href={'/docs/use/backup-restore'}
+ title="备份与恢复"
+ >
+ 手动备份、自动备份、数据回滚与命令行备份
+
+ }
+ href={'/docs/use/update'}
+ title="版本更新"
+ >
+ Docker 与源码部署的更新方式、大版本升级指引
+
+ }
+ href={'/docs/use/faq'}
+ title="常见问题"
+ >
+ 日常使用中的常见疑问与解答
+
+================================================================================
+## 写作工作流
+Path: /docs/use/writing
+================================================================================
+
+Mix Space 提供了多种写作方式,无论你习惯在浏览器中编辑,还是偏爱本地 Markdown 编辑器,都能找到适合你的工作流。
+## 后台编辑器
+登录后台后,进入「文章」或「日记」页面,点击新建即可开始写作。
+### 编辑器功能简介
+- **Markdown 支持**:直接输入 Markdown 语法,实时预览渲染效果
+- **Lexical 富文本**:提供可视化的富文本编辑体验,支持拖拽排版
+- **定时发布**:设定未来的发布时间,到点自动上线
+- **密码保护**:为单篇文章设置访问密码,适合私密内容
+后台地址通常为 `你的域名/proxy/qaqdmin`,部署时可在配置中修改。
+## Obsidian 插件
+[Obsidian Mix Space Plugin](https://github.com/mx-space/obsidian-mixspace-plugin) 是一个 Obsidian 插件,可以将你的 Obsidian 笔记库直接同步到 Mix Space。
+### 功能特性
+- 发布/更新内容到 Mix Space(支持 Note 和 Post)
+- 自动识别内容类型
+- 反向链接转换(`[[Obsidian 链接]]` → Mix Space URL)
+- Frontmatter 自动补全
+- 多环境配置(Profile)
+- AI 生成标题和 slug
+### 安装步骤
+### 下载插件
+前往 [GitHub Releases](https://github.com/mx-space/obsidian-mixspace-plugin/releases) 下载最新版本的 `obsidian-mixspace-plugin.zip`。
+### 安装到 Obsidian
+在 Obsidian 中打开「设置 → 第三方插件」,关闭安全模式后点击「浏览」旁的「加载已解压的插件」,选择解压后的插件文件夹。
+### 配置 API
+在插件设置中填入:
+- **API Endpoint**:你的 Mix Space 地址,如 `https://example.com/api/v2`
+- **Token**:在 Mix Space 后台「设定 → 安全 → API Token」中生成
+### 发布内容
+在 Obsidian 中打开一篇笔记,按 `Ctrl/Cmd + P` 打开命令面板,搜索「Mix Space」即可看到发布/更新命令。
+## Markdown 导入导出
+Mix Space 后台支持 Markdown 文件的批量导入与导出,方便你在不同平台之间迁移内容。
+### 导入 Markdown
+登录后台,进入「文章」页面。
+点击右上角「导入」按钮,选择本地 Markdown 文件。
+系统会自动解析 Frontmatter(标题、标签、分类等),确认后完成导入。
+### 导出 Markdown
+在后台文章列表中,选择需要导出的文章,点击「导出」即可下载包含完整 Frontmatter 的 Markdown 文件。
+导入时如果文章已存在相同 slug,系统会提示是否覆盖,请谨慎操作。
+## 写作建议
+为了让你的内容更容易被检索和阅读,建议养成以下习惯:
+- **使用标签**:为每篇文章添加 2–5 个标签,便于分类和关联推荐
+- **设置分类**:合理划分文章分类,让读者快速定位感兴趣的主题
+- **撰写摘要**:在 Frontmatter 或摘要栏中填写内容概要,有利于 SEO 和列表展示
+- **规范 slug**:使用英文小写和连字符作为文章链接,避免中文 URL
+
+================================================================================
+## 内容管理
+Path: /docs/use/content
+================================================================================
+
+Mix Space 支持三种主要的内容类型:**文章**(Post)、**日记**(Note)和**页面**(Page)。每种类型有不同的用途和字段。
+## 内容类型对比
+| 类型 | 用途 | URL 格式 | 特殊字段 |
+|------|------|----------|----------|
+| **文章** | 长篇博客文章 | `/{分类 slug}/{文章 slug}` | 分类、标签、置顶、相关文章、版权声明 |
+| **日记** | 短篇手记、随想 | `/notes/{nid}` 或 `/notes/{年}/{月}/{日}/{slug}` | 心情、天气、密码保护、专题、位置 |
+| **页面** | 独立页面(关于、友链等) | `/{页面 slug}` | 副标题、排序 |
+所有内容类型共有的字段:
+| 字段 | 说明 |
+|------|------|
+| **标题** | 内容标题 |
+| **正文** | 支持 Markdown 和 Lexical 富文本两种格式 |
+| **摘要** | 文章概要,留空可由 AI 自动生成 |
+| **发布状态** | 已发布 / 草稿 |
+| **创建时间 / 修改时间** | 自动记录 |
+| **评论开关** | 是否允许评论 |
+| **自定义元数据** | JSON 格式的扩展字段 |
+## 文章管理
+登录后台,进入「文章」页面。
+### 创建文章
+1. 点击右上角「新建」
+2. 在编辑器中撰写内容
+3. 在右侧面板中设置:
+| 设置项 | 说明 |
+|--------|------|
+| **分类** | 必选,将文章归入一个分类 |
+| **Slug** | URL 路径片段,建议英文小写加连字符(如 `my-first-post`) |
+| **标签** | 自由标签,输入后回车添加 |
+| **摘要** | 文章摘要,留空可由 AI 生成 |
+| **版权声明** | 是否在文末显示版权信息 |
+| **置顶** | 置顶该文章并设置置顶顺序 |
+| **发布状态** | 设为草稿或直接发布 |
+### 文章列表
+文章列表支持以下操作:
+- **按分类筛选**:选择分类快速过滤
+- **按年份筛选**:查看特定年份的文章
+- **搜索**:按标题搜索
+- **批量管理**:发布、撤回、删除
+文章的 URL 格式为 `/{分类 slug}/{文章 slug}`,例如 `/coding/my-first-post`。分类 slug 和文章 slug 共同决定了文章的唯一地址。
+### 置顶
+文章可以置顶,置顶的文章会排在列表最前面。置顶支持设置顺序(数字越大越靠前),多篇文章同时置顶时按顺序排列。
+### 相关文章
+在文章编辑面板中可以设置「相关文章」,为读者推荐关联内容。
+## 日记管理
+登录后台,进入「日记」页面。
+### 日记特有字段
+| 字段 | 说明 |
+|------|------|
+| **心情** | 记录写日记时的心情(如「开心」「思考」) |
+| **天气** | 记录天气情况 |
+| **专题** | 将日记归入一个专题 |
+| **密码保护** | 为单篇日记设置访问密码 |
+| **位置** | 记录写作地点(仅后台可见) |
+| **书签** | 标记为收藏日记 |
+### 日记 URL
+日记支持两种 URL 格式:
+- **NID 格式**:`/notes/{nid}`(自动递增的数字 ID)
+- **日期 + Slug 格式**:`/notes/2024/01/15/my-thoughts`(需要手动设置 slug)
+日记的 slug 不是必须的。如果你想使用 SEO 友好的 URL(日期 + slug 格式),需要在编辑时手动填写 slug。未设置 slug 的日记只能通过 NID 访问。AI Slug 回填功能可以为缺少 slug 的日记批量生成。
+### 专题
+日记可以归入「专题」。专题是一组相关日记的集合,类似于一个迷你系列。
+在后台「专题」页面中可以管理专题:
+- 创建专题(名称、Slug、介绍、图标)
+- 编辑和删除专题
+- 在日记编辑时选择归属专题
+### 密码保护
+为日记设置密码后,访客需要输入密码才能查看内容。后台管理视图中可以直接查看,不受密码限制。
+## 页面管理
+登录后台,进入「页面」页面。
+页面是独立的内容单元,通常用于「关于」「友链」「项目」等不归属于分类的固定页面。
+### 页面字段
+| 字段 | 说明 |
+|------|------|
+| **标题** | 页面标题 |
+| **副标题** | 页面副标题 |
+| **Slug** | URL 路径(如 `about` → `/about`) |
+| **排序** | 数字越大排序越靠前 |
+| **正文** | 页面内容 |
+## 分类管理
+在后台「分类」页面中管理文章分类。
+每个分类包含:
+| 字段 | 说明 |
+|------|------|
+| **名称** | 分类名称 |
+| **Slug** | URL 路径片段 |
+| **类型** | 分类(Category)或标签(Tag) |
+删除分类不会删除该分类下的文章,但文章将失去分类归属。建议在删除前先迁移文章到其他分类。
+## 内容格式
+Mix Space 支持两种内容编辑格式:
+| 格式 | 说明 |
+|------|------|
+| **Markdown** | 标准 Markdown 语法,适合习惯纯文本写作的用户 |
+| **Lexical 富文本** | 可视化富文本编辑器,支持拖拽排版、嵌入等高级功能 |
+你可以在后台设置中配置默认使用哪种格式,也可以在编辑时切换。
+## 草稿功能
+编辑器会自动保存草稿,防止意外丢失内容。草稿功能包括:
+- **自动保存**:编辑过程中定时保存
+- **草稿恢复**:打开文章编辑时,如果有未提交的草稿会提示恢复
+- **草稿列表**:在编辑器中查看所有草稿
+## 定时发布
+文章和日记都支持定时发布:在编辑面板中设置 `publicAt` 字段为未来的某个时间,内容将在指定时间自动发布。
+在此之前,内容保持草稿状态,前台不可见。
+
+================================================================================
+## 评论管理
+Path: /docs/use/comments
+================================================================================
+
+Mix Space 提供了完整的评论系统,支持访客留言、登录读者评论、站长回复,以及多层嵌套讨论。你可以在后台对评论进行审核、置顶、标记垃圾等操作,也可以借助 AI 自动审核来减轻管理负担。
+## 评论管理界面
+登录后台,进入「评论」页面。页面分为三个标签:
+| 标签 | 说明 |
+|------|------|
+| **待审** | 未读状态的新评论,需要你审阅 |
+| **已读** | 正常的已读评论 |
+| **垃圾** | 被标记为垃圾的评论 |
+### 常用操作
+| 操作 | 说明 |
+|------|------|
+| **标记已读 / 未读** | 切换评论的阅读状态 |
+| **标记垃圾** | 将评论标记为垃圾内容,前台不再展示 |
+| **置顶** | 将评论固定在该页面的最顶部(同页面仅一条置顶) |
+| **删除** | 软删除评论,内容替换为「该评论已删除」 |
+| **批量操作** | 勾选多条评论后批量修改状态或批量删除 |
+评论被标记为垃圾时,如果该评论附带图片,系统会自动删除这些图片文件(可在「评论图片上传」设置中关闭此行为)。
+## 评论配置
+进入后台「设定 → 评论设置」,可以配置以下选项:
+### 基本设置
+| 配置项 | 说明 |
+|--------|------|
+| **全站禁止评论** | 关闭全站评论功能,敏感时期专用 |
+| **允许未登录评论** | 开启后访客可以以游客身份评论;关闭后仅已登录读者和站长可以评论 |
+| **只展示已读评论** | 开启后,前台只展示已标记为已读的评论,未读和垃圾评论均不展示 |
+| **禁止非中文评论** | 过滤非中文字符的评论内容 |
+| **评论公开归属地** | 在评论旁显示评论者的 IP 归属地 |
+| **自定义屏蔽关键词** | 添加需要过滤的关键词列表 |
+| **自定义屏蔽 IP** | 添加需要屏蔽的 IP 地址列表 |
+### 反垃圾评论
+打开「反垃圾评论」开关后,系统会自动检测并过滤垃圾评论。
+### AI 评论审核
+如果你已在「AI 设定」中配置了 LLM 服务商,可以开启 AI 评论审核:
+| 配置项 | 说明 |
+|--------|------|
+| **开启 AI 审核** | 启用后,评论提交时会自动进行 AI 内容安全检查 |
+| **AI 审核方式** | 「是非」模式(AI 直接判断是否为垃圾)或「评分」模式(AI 给出 1-10 风险评分) |
+| **AI 审核阈值** | 评分模式下,超过此阈值的评论被标记为垃圾(默认 5,范围 1-10) |
+| **测试 AI 审核** | 输入测试文本,验证 AI 审核功能是否正常 |
+AI 评论审核可以识别垃圾广告、人身攻击、仇恨言论、政治敏感、色情暴力、阴阳怪气等多种违规内容。
+## 评论图片上传
+读者在评论中上传图片的功能,需要在「设定 → 评论图片上传」中单独配置:
+| 配置项 | 说明 |
+|--------|------|
+| **启用读者评论图片上传** | 总开关,关闭后前端隐藏上传入口 |
+| **单图最大大小(MB)** | 默认 5 MB |
+| **单评论图片张数上限** | 默认 4 张 |
+| **单读者每小时上传上限** | 默认 10 次 |
+| **单读者活跃图总容量上限(MB)** | 默认 50 MB |
+| **读者账号最小年龄(小时)** | 准入门槛,0 表示不限 |
+| **读者最小已发评论数** | 准入门槛,0 表示不限 |
+| **评论标记 spam 时同步删图** | 默认开启,关闭则仅删评论保留图片 |
+| **MIME 白名单** | 默认 image/jpeg、image/png、image/webp、image/gif |
+评论图片有自动清理机制:上传后未被评论引用的图片会在设定时间后自动清除(默认 120 分钟),评论编辑后被移除的图片也会在设定时间后清除(默认 30 分钟)。
+## 评论排序
+前台评论支持三种排序方式:
+| 排序 | 说明 |
+|------|------|
+| **置顶优先** | 置顶评论在最前,其余按时间倒序(默认) |
+| **最新** | 按时间倒序 |
+| **最早** | 按时间正序 |
+## 悄悄话
+评论支持「悄悄话」模式,标记为悄悄话的评论仅站长可见,前台不展示给其他访客。
+
+================================================================================
+## 友链管理
+Path: /docs/use/friends
+================================================================================
+
+友情链接(友链)是博客之间互相推荐的方式。Mix Space 支持完整的友链管理流程:添加、审核、健康检查、自动头像转内链。
+## 管理友链
+登录后台,进入「友链」页面。你可以:
+| 操作 | 说明 |
+|------|------|
+| **新增友链** | 点击右上角「+」,填写友链信息后保存 |
+| **编辑友链** | 点击友链条目进入编辑 |
+| **删除友链** | 删除不再需要的友链 |
+| **审核友链申请** | 在「审核中」标签页查看并审批申请 |
+### 友链状态
+| 状态 | 说明 |
+|------|------|
+| 已通过 | 正常展示在友链列表中 |
+| 审核中 | 等待站长审批的友链申请 |
+| 已过期 | 友链已过期 |
+| 已屏蔽 | 被手动屏蔽的友链 |
+| 已拒绝 | 审核未通过的友链 |
+### 友链类型
+| 类型 | 说明 |
+|------|------|
+| **友链(Friend)** | 普通友情链接 |
+| **收藏(Collection)** | 收藏的站点链接 |
+## 友链申请
+如果开启了友链申请功能,访客可以通过前端页面提交友链申请。
+### 开启友链申请
+进入后台「设定 → 友链设定」,打开「允许申请友链」开关。
+### 申请流程
+### 访客提交申请
+访客在前端友链页面填写站点名称、URL、头像、描述和邮箱(可选),提交申请。
+### 站长收到通知
+系统会通过邮件(如已配置)通知站长有新的友链申请。
+### 站长审批
+在后台「友链」页面的「审核中」标签查看申请:
+- 点击「通过」审批友链
+- 点击「拒绝」可填写拒绝理由,系统会通过邮件发送给申请者
+审核通过后,系统会自动通过邮件通知申请者(前提是申请者填写了邮箱且邮件服务已配置)。
+## 友链配置项
+进入后台「设定 → 友链设定」:
+| 配置项 | 说明 |
+|--------|------|
+| **允许申请友链** | 开启后前端展示友链申请入口 |
+| **允许子路径友链** | 允许申请子路径形式的友链(如 `example.com/blog`) |
+| **友链头像转内链** | 审核通过后自动下载友链头像到本地,避免外部头像加载失败 |
+### 头像转内链
+打开「友链头像转内链」后,当友链审核通过时,系统会自动下载该友链的头像文件并存储到本地。这样即使原始头像链接失效,你的友链页面仍然可以正常显示头像。
+头像转内链仅支持常见图片格式(JPEG、PNG、WebP、GIF 等),其他格式的头像不会被转换。
+## 友链健康检查
+在后台友链页面,点击「健康检查」按钮,系统会批量检测所有已通过友链的可达性。不可达的友链会被标记,方便你及时清理失效链接。
+## 头像批量迁移
+如果你在后期才开启头像转内链功能,已有友链的头像仍然是外部链接。在友链页面点击「迁移头像」按钮,可以批量将所有已通过友链的外部头像下载到本地。
+
+================================================================================
+## 说说管理
+Path: /docs/use/says
+================================================================================
+
+「说说」是 Mix Space 中一种轻量级的内容类型,适合发布碎片化的想法、一句话感悟、状态更新等短内容。类似微博或 Twitter 的一条推文。
+## 管理说说
+登录后台,进入「说说」页面。
+### 发布说说
+1. 点击右上角「+」新建
+2. 填写以下字段:
+| 字段 | 说明 |
+|------|------|
+| **内容** | 说说正文(必填) |
+| **来源** | 发布来源(如「网页」「iPhone」) |
+| **作者** | 引用他人的话时填写原作者 |
+3. 点击保存即可发布
+### 编辑和删除
+在说说列表中,点击条目可以编辑内容,点击删除按钮可以移除说说。
+说说内容会实时推送到前端主题。如果你的主题支持说说模块,说说会以时间线的形式展示。
+## 随机说说 API
+系统提供了一条随机说说的 API 接口,前端主题可以使用这个接口在页面中随机展示一条说说,增加页面的趣味性。
+## 与其他功能的联动
+- **订阅推送**:如果开启了读者订阅,新说说发布时可以通知订阅者
+- **Webhook**:说说创建、更新、删除都会触发对应的 Webhook 事件
+- **实时推送**:说说发布后通过 WebSocket 实时推送到在线用户
+
+================================================================================
+## 项目展示
+Path: /docs/use/projects
+================================================================================
+
+Mix Space 内置了项目展示功能,你可以在后台管理自己的项目信息,前端主题会将这些项目以卡片等形式展示出来。
+## 管理项目
+登录后台,进入「项目管理」页面。
+### 添加项目
+点击右上角「+」,填写项目信息:
+| 字段 | 说明 |
+|------|------|
+| **名称** | 项目名称(必填,唯一) |
+| **描述** | 项目简介(必填) |
+| **详情** | 项目的详细介绍(支持 Markdown) |
+| **预览地址** | 项目在线预览 URL |
+| **文档地址** | 项目文档 URL |
+| **项目地址** | 项目源码仓库 URL |
+| **头像** | 项目图标或 Logo URL |
+| **截图** | 项目截图 URL 列表 |
+### 编辑和删除
+在项目列表中可以编辑已有项目或删除不再需要项目。
+所有 URL 字段都需要填写完整的 HTTP/HTTPS 地址。
+## 前端展示
+项目数据通过 API 提供给前端主题。不同主题的展示方式可能不同,常见的展示形式包括:
+- 项目卡片网格
+- 带截图的项目详情页
+- 按时间排列的项目列表
+具体展示效果取决于你使用的前端主题。
+
+================================================================================
+## 文件管理
+Path: /docs/use/files
+================================================================================
+
+Mix Space 后台提供了文件管理功能,支持图片、图标、头像和普通文件的上传、浏览与管理。
+## 文件管理界面
+登录后台,进入「文件」页面。页面分为以下标签:
+| 标签 | 说明 |
+|------|------|
+| **图标** | 站点使用的图标文件 |
+| **头像** | 用户头像文件 |
+| **图片** | 文章和内容中使用的一般图片 |
+| **文件** | 其他普通文件 |
+### 文件操作
+| 操作 | 说明 |
+|------|------|
+| **上传** | 拖拽或点击上传文件,支持批量上传 |
+| **复制链接** | 复制文件的 URL 地址 |
+| **在新标签页打开** | 预览文件 |
+| **删除** | 删除不需要的文件 |
+在编辑器中粘贴或拖拽图片时,文件会自动上传到「图片」分类中。
+## 评论图片管理
+在文件管理页面的「评论图片」标签中,可以查看和管理读者在评论中上传的图片:
+- 按评论归属查看图片
+- 删除不当图片
+- 查看孤立图片(未被引用的图片)
+孤立图片会在设定时间后被系统自动清理。
+## 文件上传配置
+进入后台「设定 → 文件上传设定」,可以自定义文件命名和存储规则:
+| 配置项 | 说明 |
+|--------|------|
+| **启用自定义文件命名** | 开启后使用下方定义的命名模板 |
+| **文件名模板** | 定义上传文件的命名规则 |
+| **文件路径模板** | 定义文件的存储路径规则 |
+### 占位符
+文件名和路径模板支持以下占位符:
+| 占位符 | 说明 |
+|--------|------|
+| `{Y}` | 年份(4 位) |
+| `{y}` | 年份(2 位) |
+| `{m}` | 月份 |
+| `{d}` | 日期 |
+| `{h}` | 小时 |
+| `{i}` | 分钟 |
+| `{s}` | 秒 |
+| `{ms}` | 毫秒 |
+| `{timestamp}` | Unix 时间戳 |
+| `{md5}` | 随机 MD5(32 位) |
+| `{md5-16}` | 随机 MD5(16 位) |
+| `{uuid}` | UUID |
+| `{str-N}` | N 位随机字符串 |
+| `{filename}` | 原文件名(含扩展名) |
+| `{name}` | 原文件名(不含扩展名) |
+| `{ext}` | 扩展名 |
+路径模板额外支持 `{type}`(文件类型)和 `{localFolder:N}`(原文件所在文件夹层级)。
+### 示例
+- 文件名模板:`{Y}/{m}/{md5}.{ext}` → 上传后路径为 `2024/01/abc123def456.jpg`
+- 路径模板:`images/{type}/{Y}{m}{d}/{md5-16}.{ext}` → 按类型和日期分目录存储
+修改文件命名模板后,仅对新上传的文件生效。已上传的文件不会自动重命名。
+
+================================================================================
+## 站点统计与分析
+Path: /docs/use/analytics
+================================================================================
+
+Mix Space 内置了站点统计功能,你可以在后台查看访问量、独立访客、流量来源、热门路径等数据,无需集成第三方统计服务。
+## 统计概览
+登录后台,首页(仪表盘)即展示关键数据概览:
+| 指标 | 说明 |
+|------|------|
+| **文章数** | 已发布的文章总数 |
+| **日记数** | 已发布的日记总数 |
+| **评论数** | 评论总数 |
+| **友链数** | 已通过的友链总数 |
+| **在线人数** | 当前 WebSocket 在线连接数 |
+| **总阅读量** | 所有内容的阅读计数 |
+| **总点赞数** | 所有内容的点赞计数 |
+## 详细分析
+进入后台「分析」页面,可以查看更详细的统计数据。
+### 访问趋势
+| 视图 | 说明 |
+|------|------|
+| **今日** | 按小时展示今天的 IP 和 PV 数据 |
+| **本周** | 按周几展示近 7 天的 IP 和 PV |
+| **本月** | 按日期展示近 30 天的 IP 和 PV |
+### 热门路径
+展示访问量最高的页面路径列表,帮助你了解哪些内容最受欢迎。
+### 流量来源
+展示访客的来源渠道分布(搜索引擎、直接访问、外部链接等)。
+### 设备分布
+展示访客使用的设备类型和浏览器分布。
+## 评论活动
+分析页面还展示评论活动趋势图,可以看到评论数量的时间变化。
+## 数据管理
+在分析页面中,你可以:
+- **按时间范围查询**:选择起止日期查看特定时间段的数据
+- **查看今日/本周数据**:快速切换到常用时间范围
+- **清除历史数据**:按时间范围清除分析数据
+分析数据存储在 Redis 中,具有缓存机制。聚合数据缓存约 1 分钟,流量来源和设备分布数据缓存约 5 分钟。
+
+================================================================================
+## AI 功能
+Path: /docs/use/ai-features
+================================================================================
+
+Mix Space 内置了一套完整的 AI 功能体系,覆盖内容创作、管理、分发全流程。你只需配置一个 LLM 服务商即可启用。
+AI 功能需要后台「设定 → AI 设定」中配置至少一个 Provider 并启用对应功能开关。详见下方 [配置 AI Provider](#配置-ai-provider)。
+## 功能总览
+| 功能 | 说明 | 触发方式 |
+|------|------|----------|
+| **AI 摘要** | 自动生成文章摘要,支持多语言 | 手动 / 自动(发布/更新时) |
+| **AI 精读** | 生成深度阅读伴侣(TL;DR、结构图、Mermaid 图、引用锚点) | 手动 / 自动(发布/更新时) |
+| **AI 翻译** | 将文章翻译为多语言版本,保持 Markdown/Lexical 格式完整 | 手动 / 自动(发布/更新时) |
+| **写作助手** | 自动生成标题和 SEO slug,批量回填历史文章 slug | 编辑器内手动 |
+| **评论审核** | AI 自动识别垃圾评论和有害内容 | 自动(评论提交时) |
+| **AI Agent** | 在编辑器中与 AI 对话,辅助写作和修改 | 编辑器内手动 |
+| **任务队列** | 统一管理所有 AI 后台任务的创建、进度和重试 | 后台 AI 页面 |
+## 配置 AI Provider
+### 进入设置页面
+登录后台,前往「设定 → AI 设定」。
+### 添加 Provider
+点击「添加 Provider」,填写以下信息:
+| 字段 | 说明 | 示例 |
+|------|------|------|
+| Provider ID | 唯一标识符 | `openai-main`、`deepseek` |
+| 显示名称 | 便于识别的名称 | `OpenAI`、`DeepSeek` |
+| Provider 类型 | 服务商类型 | OpenAI / OpenAI-Compatible / Anthropic / OpenRouter |
+| API Key | 你的 API 密钥 | `sk-...` |
+| 自定义 Endpoint | OpenAI-Compatible 类型必填 | `https://api.deepseek.com` |
+| 默认模型 | 该 Provider 默认使用的模型 | `gpt-4o`、`deepseek-chat` |
+### 为各功能分配模型(可选)
+在 Provider 列表下方,可以为摘要、写作、翻译、精读等功能分别指定使用哪个 Provider 和模型。留空则使用第一个启用的 Provider 及其默认模型。
+### 测试连接
+配置完成后,点击 Provider 旁的「测试」按钮,验证 API Key 和 Endpoint 是否正确。
+你可以同时配置多个 Provider,并将不同的 AI 功能分配给不同的 Provider。例如用 DeepSeek 做翻译(成本低),用 OpenAI 做精读(效果好)。
+## AI 摘要
+AI 摘要可以为你的文章自动生成简短的内容概要,支持多语言输出。
+### 开启摘要
+在「设定 → AI 设定」中:
+1. 打开「可调用 AI 摘要」开关
+2. 设置「AI 摘要目标语言列表」(使用 [ISO 639-1 语言代码](https://www.w3schools.com/tags/ref_language_codes.asp),如 `zh`、`en`、`ja`)
+3. 可选:打开「文章创建时自动生成摘要」和「文章更新时重新生成摘要」
+4. 可选:设置「摘要自动生成最小文本长度」(低于此字符数的文章跳过自动生成)
+### 手动生成摘要
+进入后台「AI → 摘要」页面,选择文章后点击生成。也可以在文章编辑器中通过侧边栏触发。
+### 摘要管理
+在「AI → 摘要」页面中,你可以:
+- 按文章分组查看所有摘要
+- 编辑已生成的摘要文本
+- 删除不需要的摘要
+- 查看摘要对应的原文信息
+## AI 精读(Insights)
+AI 精读是比摘要更深入的内容分析功能。它会生成一篇「深度阅读伴侣」,包含 TL;DR、结构化大纲、Mermaid 图表、引用锚点回原文、开放性问题等内容,帮助读者更好地理解文章。
+### 开启精读
+在「设定 → AI 设定」中:
+1. 打开「可调用 AI Insights」开关
+2. 可选:打开「文章创建时自动生成 Insights」和「文章更新时重新生成 Insights」
+3. 可选:设置「Insights 目标语言列表」用于精读内容的多语言翻译
+4. 可选:打开「Insights 生成后自动翻译」
+5. 可选:设置「Insights 自动生成最小文本长度」
+### 精读内容包含什么
+精读根据文章类型自动选择 3-7 个组件进行生成,可能包含:
+| 组件 | 说明 |
+|------|------|
+| TL;DR | 1-3 句话概括核心观点 |
+| 结构图 / 时间线 | 文章的逻辑结构或事件时序 |
+| Mermaid 图表 | 架构图、流程图、因果链等可视化 |
+| 关键概念 | 术语表或背景知识卡片 |
+| 引用锚点 | 精读中的关键论点锚定回原文位置 |
+| 反论与盲点 | 指出作者未涉及的视角 |
+| 开放性问题 | 值得读者进一步思考的问题 |
+### 精读翻译
+精读内容也支持多语言翻译。设置「Insights 目标语言列表」后,可以在精读页面手动触发翻译,或开启自动翻译。
+## AI 翻译
+AI 翻译可以将你的文章完整翻译为多语言版本,保持 Markdown 格式、代码块、链接等技术元素不变,同时保持翻译一致性。
+### 开启翻译
+在「设定 → AI 设定」中:
+1. 打开「可调用 AI 翻译」开关
+2. 设置「AI 翻译目标语言列表」(如 `en`、`ja`、`ko`)
+3. 可选:打开「开启 AI 翻译自动生成」(文章发布后自动翻译)
+### 翻译特性
+- **双策略支持**:Markdown 文章和 Lexical 富文本文章分别使用对应的翻译策略,确保格式完整保留
+- **翻译词表**:系统自动维护分类名称、话题名称、心情、天气等短文本的翻译一致性
+- **多语言批量翻译**:可以一次为多篇文章生成多语言翻译
+- **全量翻译**:支持一键为所有已有文章生成翻译
+### 手动翻译操作
+进入后台「AI → 翻译」页面:
+- 选择文章,点击「翻译」
+- 选择目标语言后开始生成
+- 生成完成后可查看、编辑、删除翻译
+### 翻译词表
+进入「AI → 翻译词表」页面,可以查看和管理系统自动维护的翻译词表。词表用于确保分类、话题、心情、天气等短文本在不同文章间翻译一致。
+支持的管理操作:
+- 按类型(分类名、话题名、心情、天气)筛选查看
+- 手动编辑翻译结果
+- 批量重新生成
+## 写作助手
+写作助手在编辑器中为你提供 AI 辅助。
+### 标题和 Slug 生成
+在编辑器中撰写完内容后,可以使用 AI 自动生成:
+- **标题**:根据文章内容生成一个合适的标题
+- **Slug**:生成 SEO 友好的英文 URL 路径
+确保在 AI 设定中配置了写作助手模型(Writer Model),或在编辑器的 AI 面板中选择了可用的 Provider。
+### Slug 批量回填
+如果你有历史文章缺少 slug,可以使用「AI → Slug 回填」功能:
+1. 进入后台「AI → Slug 回填」页面
+2. 查看缺少 slug 的日记条目数量
+3. 点击「开始回填」,系统会为所有缺少 slug 的日记自动生成 SEO slug
+## 评论审核
+AI 评论审核功能会在读者提交评论时自动进行内容安全检查。
+### 配置评论审核
+在后台「设定 → 评论设置」中:
+1. 打开「开启 AI 审核」开关
+2. 选择审核方式:
+ - **是非模式(Binary)**:AI 判断评论是否为垃圾内容
+ - **评分模式(Score)**:AI 给出风险评分(1-10),超过阈值则判定为垃圾
+3. 如果使用评分模式,设置阈值(默认 5,范围 1-10)
+4. 点击「测试 AI 审核」验证功能
+### 检测能力
+AI 评论审核可以识别以下类型的违规内容:
+- 垃圾评论、广告、诈骗
+- 人身攻击、网络霸凌
+- 仇恨言论和歧视
+- 政治敏感、色情、暴力内容
+- 阴阳怪气和隐性攻击
+- 无意义测试内容
+## AI Agent(编辑器内对话)
+AI Agent 允许你在编辑器中直接与 AI 对话,辅助写作和内容修改。
+### 使用方式
+在文章编辑器中,打开右侧的 AI Agent 面板:
+1. 选择一个已配置的 Provider 和模型
+2. 在对话框中输入指令,如「帮我润色这段文字」「把这段改成更口语化的风格」
+3. AI 的回复可以应用到编辑器中
+AI Agent 对话历史会自动保存,你可以在同一篇文章中随时继续之前的对话。
+## 任务队列
+所有 AI 后台任务通过统一的任务队列管理,你可以在「AI → 任务」页面查看和管理。
+### 任务类型
+| 任务类型 | 说明 |
+|----------|------|
+| 摘要生成 | 为单篇文章生成摘要 |
+| 翻译生成 | 为单篇文章生成翻译 |
+| 批量翻译 | 为多篇文章批量生成翻译 |
+| 全量翻译 | 为所有文章生成翻译 |
+| 精读生成 | 为单篇文章生成精读 |
+| 精读翻译 | 翻译已生成的精读内容 |
+| Slug 回填 | 为历史日记批量生成 slug |
+### 任务状态
+| 状态 | 说明 |
+|------|------|
+| Pending | 等待执行 |
+| Running | 正在执行 |
+| Completed | 执行完成 |
+| Partial Failed | 部分子任务失败 |
+| Failed | 执行失败 |
+| Cancelled | 已取消 |
+### 任务管理
+在任务页面中,你可以:
+- 按状态和类型筛选任务
+- 查看任务详情(进度、日志、耗时)
+- 重试失败的任务
+- 取消正在运行的任务
+- 批量清理历史任务
+批量翻译任务会自动分组,你可以在任务列表中展开查看每个子任务的状态。
+
+================================================================================
+## Webhook 与事件通知
+Path: /docs/use/webhook
+================================================================================
+
+Webhook 可以将 Mix Space 中发生的事件(如发布文章、收到评论等)实时推送到你指定的外部服务。常见的用途包括:通知到 Telegram/微信、触发 CI/CD 构建、同步到第三方平台等。
+## 创建 Webhook
+### 进入 Webhook 管理页面
+登录后台,进入「其他 → Webhook」。
+### 点击新建
+填写以下信息:
+| 字段 | 说明 |
+|------|------|
+| **Payload URL** | 接收推送的 URL 地址 |
+| **Secret** | 签名密钥,用于验证推送来源 |
+| **事件** | 勾选你关注的事件类型 |
+| **启用** | 是否启用此 Webhook |
+| **作用域** | 选择接收推送的范围(访客/管理员/系统) |
+### 保存并测试
+保存后,当勾选的事件发生时,系统会向 Payload URL 发送 HTTP POST 请求。
+## 支持的事件
+| 事件 | 说明 |
+|------|------|
+| `POST_CREATE` | 文章创建 |
+| `POST_UPDATE` | 文章更新 |
+| `POST_DELETE` | 文章删除 |
+| `NOTE_CREATE` | 日记创建 |
+| `NOTE_UPDATE` | 日记更新 |
+| `NOTE_DELETE` | 日记删除 |
+| `PAGE_CREATE` | 页面创建 |
+| `PAGE_UPDATE` | 页面更新 |
+| `PAGE_DELETE` | 页面删除 |
+| `COMMENT_CREATE` | 评论创建 |
+| `COMMENT_DELETE` | 评论删除 |
+| `COMMENT_UPDATE` | 评论更新 |
+| `SAY_CREATE` | 说说创建 |
+| `SAY_UPDATE` | 说说更新 |
+| `SAY_DELETE` | 说说删除 |
+| `CATEGORY_CREATE` | 分类创建 |
+| `CATEGORY_UPDATE` | 分类更新 |
+| `CATEGORY_DELETE` | 分类删除 |
+| `TOPIC_CREATE` | 专题创建 |
+| `TOPIC_UPDATE` | 专题更新 |
+| `TOPIC_DELETE` | 专题删除 |
+| `LINK_APPLY` | 友链申请 |
+| `RECENTLY_CREATE` | 速记创建 |
+| `RECENTLY_UPDATE` | 速记更新 |
+| `RECENTLY_DELETE` | 速记删除 |
+| `TRANSLATION_CREATE` | AI 翻译创建 |
+| `TRANSLATION_UPDATE` | AI 翻译更新 |
+| `INSIGHTS_CREATE` | AI 精读创建 |
+| `INSIGHTS_UPDATE` | AI 精读更新 |
+## 作用域说明
+Webhook 可以选择不同的推送作用域:
+| 作用域 | 说明 |
+|--------|------|
+| **访客** | 仅推送面向访客的事件 |
+| **管理员** | 仅推送面向管理员的事件 |
+| **系统** | 仅推送系统级别的事件 |
+| **全选** | 推送所有事件 |
+合理选择作用域可以减少不必要的推送请求。例如,如果你想将评论通知推送到 Telegram,选择「访客」作用域即可。
+## 管理推送记录
+在 Webhook 列表中点击某个 Webhook,可以查看该 Webhook 的推送记录:
+- **推送状态**:成功或失败
+- **HTTP 状态码**:目标服务返回的状态码
+- **请求头和请求体**:完整的推送内容
+- **响应内容**:目标服务的返回数据
+### 重试推送
+对于推送失败的记录,可以点击「重新推送」按钮手动重试。
+### 清除记录
+点击「清除记录」可以删除该 Webhook 的所有历史推送记录。
+
+================================================================================
+## 邮件与订阅
+Path: /docs/use/mail-subscribe
+================================================================================
+
+Mix Space 支持邮件通知和读者订阅功能。配置邮件服务后,系统可以在友链申请、评论通知等场景发送邮件,读者也可以订阅你的内容更新。
+## 邮件服务配置
+### 前置条件
+你需要一个邮件发送服务。Mix Space 支持两种邮件服务:
+| 服务 | 说明 |
+|------|------|
+| **SMTP** | 传统 SMTP 邮件发送,适用于大多数邮件服务商(Gmail、QQ 邮箱、阿里企业邮等) |
+| **Resend** | 现代邮件 API 服务,配置简单,适合开发者 |
+### 配置步骤
+### 进入邮件设置
+登录后台,前往「设定 → 邮件通知设置」。
+### 开启邮件提醒
+打开「开启邮箱提醒」开关。
+### 选择邮件服务
+在「邮件服务」下拉框中选择 SMTP 或 Resend。
+### 填写配置
+**SMTP 方式:**
+| 字段 | 说明 |
+|------|------|
+| SMTP 用户名 | 邮箱账号 |
+| SMTP 密码 | 邮箱密码或应用专用密码 |
+| SMTP 主机 | SMTP 服务器地址(如 `smtp.gmail.com`) |
+| SMTP 端口 | 端口号(如 `465`) |
+| 使用 SSL/TLS | 是否启用加密连接 |
+| 发件邮箱地址 | 发件人邮箱,不填则使用 SMTP 用户名 |
+**Resend 方式:**
+| 字段 | 说明 |
+|------|------|
+| Resend API Key | 在 [resend.com](https://resend.com) 获取的 API 密钥 |
+| 发件邮箱地址 | Resend 中验证的发件域名邮箱(必填) |
+### 高级设置(可选)
+| 配置项 | 说明 |
+|--------|------|
+| **发送速率限制** | 每秒最大发送次数,默认 10 |
+| **发送失败重试次数** | 最大重试次数,默认 3 |
+使用 SMTP 时,部分邮件服务商(如 Gmail)需要开启「应用专用密码」或「不太安全的应用访问」才能正常发送。建议使用 Resend 等专业邮件 API 服务。
+## 读者订阅
+开启订阅功能后,读者可以通过邮箱订阅你的内容更新。当发布新文章或日记时,系统会自动向订阅者发送邮件通知。
+### 开启订阅
+进入后台「设定 → 特征开关设定」,打开「开启邮件推送订阅」开关。
+订阅功能依赖邮件服务。请先完成邮件服务配置,否则订阅邮件无法发送。
+### 订阅类型
+读者可以选择订阅以下内容类型:
+| 类型 | 说明 |
+|------|------|
+| **博文** | 新文章发布时通知 |
+| **手记** | 新日记发布时通知 |
+| **速记** | 新速记发布时通知 |
+| **说说** | 新说说发布时通知 |
+### 管理订阅者
+登录后台,进入「其他 → 订阅」页面,可以查看所有订阅者:
+- 查看订阅者的邮箱、订阅类型和订阅时间
+- 按类型筛选订阅者
+- 手动取消订阅者的订阅
+- 批量取消订阅
+### 取消订阅
+读者可以在收到的邮件中点击取消订阅链接,你也可以在后台管理页面手动为读者取消订阅。
+## 其他通知方式
+除了邮件,Mix Space 还支持 **Bark 推送通知**(iOS)。在「设定 → Bark 通知设定」中配置:
+| 配置项 | 说明 |
+|--------|------|
+| **开启 Bark 通知** | 启用 Bark 推送 |
+| **设备 Key** | Bark App 中的设备推送 Key |
+| **服务器 URL** | 自定义 Bark 服务器地址,不填则使用默认 `https://day.app` |
+| **开启评论通知** | 收到新评论时推送 |
+| **开启请求被限流时通知** | 可以在一定程度上预警被攻击 |
+
+================================================================================
+## 云函数与 Snippet
+Path: /docs/use/serverless
+================================================================================
+
+Snippet 是 Mix Space 的扩展机制。每个 Snippet 是一段可配置的代码片段,可以为你的站点添加自定义数据接口、动态路由、前端脚本注入等能力。
+## 功能总览
+| 类型 | 说明 | 典型用途 |
+|------|------|----------|
+| **JSON / JSON5** | 结构化数据片段 | 配置数据、映射表 |
+| **Text** | 纯文本片段 | 公告、自定义 HTML |
+| **YAML** | YAML 数据片段 | 结构化配置 |
+| **Function** | 可执行函数 | 云函数 API、自定义路由 |
+Function 类型的 Snippet 就是你常听到的「云函数」。它是 Snippet 系统的一个子集,拥有最强大的扩展能力。
+## 管理云函数 / Snippet
+登录后台,进入「其他 → 云函数」页面。
+### 导入社区云函数
+### 点击「下载拓展包」
+在页面右上方点击「下载拓展包」按钮,弹出社区云函数列表。
+### 选择并导入
+在弹窗中找到对应主题的云函数代码,点击「导入」。
+### 确认启用
+导入后在管理页面确认 Snippet 已启用。Function 类型的 Snippet 需要手动开启「启用」开关。
+社区收录的云函数 Snippets 可以在 GitHub 查看:
+### 手动创建 Snippet
+1. 点击右上角「+」新建
+2. 填写以下信息:
+| 字段 | 说明 |
+|------|------|
+| **名称** | Snippet 名称(英文、数字、下划线,不超过 30 字符) |
+| **类型** | JSON / JSON5 / Text / YAML / Function |
+| **分组** | 用于组织 Snippet(Reference 字段) |
+| **内容** | Snippet 的实际代码 |
+| **备注** | 可选,备注说明 |
+| **私有** | 勾选后仅管理员可访问 |
+Function 类型额外支持:
+| 字段 | 说明 |
+|------|------|
+| **自定义路径** | 绑定一个 URL 路径,如 `my-api` → `/s/my-api` |
+| **HTTP 方法** | GET / POST / PUT / DELETE / PATCH / ALL |
+| **启用** | 是否启用此函数 |
+| **密钥** | 加密的配置项(如 API Key),存储时自动加密 |
+### 分组管理
+Snippet 按分组(Reference)组织。管理页面左侧显示分组列表,点击分组展开查看其中的 Snippet。你可以:
+- 展开折叠分组
+- 按 Reference 筛选
+- 查看每个分组的 Snippet 数量
+## Function 类型(云函数)
+Function 类型是最强大的 Snippet,它是一段可以在服务器端执行的 JavaScript 函数。
+### 自定义路由
+设置「自定义路径」后,你可以通过 `/s/{自定义路径}` 访问此函数的执行结果。例如:
+- 自定义路径 `bili-followings` → 访问 `/s/bili-followings` 获取哔哩哔哩关注列表
+- 自定义路径 `bangumi` → 访问 `/s/bangumi` 获取追番数据
+函数支持指定 HTTP 方法(GET、POST 等),也可以选择 ALL 匹配所有方法。
+Function 类型 Snippet 有请求限流(每 5 秒 100 次),高频调用场景请注意缓存。
+### 函数日志
+Function 类型 Snippet 的执行日志可以在管理页面查看。点击「日志」按钮可以查看函数的运行输出,方便调试。
+### 安装依赖
+Function 类型支持安装 npm 依赖包。在管理页面中:
+- 点击「安装依赖」按钮添加需要的 npm 包
+- 点击「更新依赖」更新已安装的包
+### 密钥管理
+函数中可能需要用到 API Key 等敏感信息。使用「密钥」字段存储,系统会自动加密。在函数代码中可以通过注入的上下文访问。
+## 数据类型 Snippet 的访问方式
+非 Function 类型的 Snippet 可以通过以下方式访问:
+| 访问方式 | URL 格式 |
+|----------|----------|
+| 按名称和分组 | `/api/v2/snippets/{reference}/{name}` |
+| 按自定义路径 | `/s/{customPath}`(需要设置自定义路径) |
+- **公开(Public)** Snippet 所有人可访问
+- **私有(Private)** Snippet 仅管理员登录后可访问
+## 前端主题集成
+许多前端主题依赖 Snippet 提供数据。常见用法:
+- Shiro 主题使用云函数提供哔哩哔哩追番、最近听歌等模块
+- 自定义 CSS/JS 注入到前端页面
+- 提供导航栏配置、社交链接等结构化数据
+具体需要导入哪些 Snippet,请参考你使用的前端主题文档。
+## 开发者文档
+如需编写自定义 Function 类型 Snippet,请参考完整的开发者文档:
+
+================================================================================
+## 定时任务
+Path: /docs/use/cron-tasks
+================================================================================
+
+Mix Space 内置了一组定时任务,用于自动清理过期数据、推送搜索引擎、维护系统健康。你可以在后台查看这些任务的执行状态,也可以手动触发。
+## 管理入口
+登录后台,进入「维护 → 定时任务」页面。
+## 内置任务列表
+| 任务 | 说明 | 默认执行频率 |
+|------|------|-------------|
+| **清理访问记录** | 清理过期的访问分析记录 | 每月 1 日凌晨 |
+| **清理 IP 访问记录** | 重置 IP 访问计数 | 每日凌晨 |
+| **清理喜欢数** | 重置文章的点赞和阅读计数缓存 | 每日凌晨 |
+| **清理临时文件** | 删除临时目录中的过期文件 | 每日凌晨 3 点 |
+| **推送百度搜索** | 将新内容推送到百度搜索引擎 | 每日凌晨 1 点 |
+| **推送 Bing 搜索** | 将新内容推送到 Bing 搜索引擎 | 每日凌晨 1 点 |
+| **删除过期 JWT** | 清理数据库中过期的 JWT 令牌 | 每日凌晨 1 点 |
+| **重建搜索索引** | 重建 Algolia 等搜索服务的索引 | 每日凌晨 4 点 |
+| **清理评论图片上传** | 清理未被引用和过期的评论图片 | 每 15 分钟 |
+搜索引擎推送任务(百度、Bing)需要先在「设定」中配置对应的 Token / API 密钥并开启推送,否则任务不会实际推送数据。
+## 任务状态
+| 状态 | 说明 |
+|------|------|
+| 等待中 | 任务已创建,等待执行 |
+| 执行中 | 任务正在运行 |
+| 已完成 | 任务执行成功 |
+| 部分失败 | 多步骤任务中有部分步骤失败 |
+| 失败 | 任务执行失败 |
+| 已取消 | 任务被手动取消 |
+## 手动触发
+在定时任务页面中,点击任务旁的「执行」按钮可以手动触发该任务。适用于:
+- 首次配置搜索引擎推送后,立即推送已有内容
+- 清理了大量垃圾评论后,手动清理评论图片
+- 搜索索引异常时,手动重建
+## 任务日志
+每个任务执行后会保留日志记录,包含:
+- 任务类型和执行时间
+- 执行结果(成功/失败)
+- 详细的执行输出
+- 失败时的错误信息
+对于失败的任务,可以点击「重试」按钮重新执行。
+## 清理历史任务
+在任务列表中,可以批量清理已完成的历史任务记录,保持列表整洁。
+
+================================================================================
+## 备份与恢复
+Path: /docs/use/backup-restore
+================================================================================
+
+## 手动备份
+在后台「其他 → 备份」中点击「立即备份」,系统会将数据打包为 zip 文件,保存到服务器的绝对目录:
+```
+~/mx-space/core/data/mx-space/backup/20xx-xx-xx_xx:xx:xx/backup-20xx-xx-xx_xx:xx:xx.zip
+```
+建议定期手动下载备份包到本地,以防服务器故障导致数据丢失。
+## 自动备份
+目前该功能仅支持备份到支持 S3 协议的云服务,暂不支持其他类型的云服务。当然,你也可以通过设置计划任务等方法达到和此功能一样的效果。
+设置入口:后台「设定 → 系统 → 备份」,填入云服务所提供的对应参数即可。
+## 恢复
+该操作涉及修改数据库,请多备份几个工作日的 backup,数据无价请谨慎操作!
+一般情况下回滚只会导致 analyze 数据页丢失 IP & PV 的数据。
+Linux 和 macOS 可直接上传备份包,并且无需修改包名一致即可回滚,以下操作仅针对使用 Windows 用户访问后端回滚的情况。
+在后台「其他 → 备份」中点击「立即备份」,将之前在电脑里的 `backup.zip` 上传到刚刚生成的备份目录里进行重命名替换。
+例:假如刚刚生成的备份是 `backup-2022-09-01_23:33:33.zip`,将想进行回滚的备份包 `backup-2022-01-14_05:14:19.zip` 修改为刚刚生成的备份一样的名字:
+```bash
+mv ~/mx-space/core/data/mx-space/backup/2022-01-14_05:14:19/backup-2022-01-14_05:14:19.zip backup-2022-09-01_23:33:33.zip
+```
+不要在 Windows 下重命名,Windows 不支持将英文冒号作为文件名的一部分。
+替换完成后会提示「数据库有变动,将在 x 秒后重载页面」,重载后请先检查文章、评论等有没有丢失。
+## 命令行备份(v12+)
+自 v12 起,Mix Space 使用 PostgreSQL 作为数据库。你可以直接使用 `pg_dump` 进行命令行备份:
+```bash
+pg_dump postgresql://mx:mx@localhost:5432/mx_core > backup.sql
+```
+恢复时执行:
+```bash
+psql postgresql://mx:mx@localhost:5432/mx_core < backup.sql
+```
+请根据实际情况修改连接字符串中的用户名、密码、主机和数据库名。
+
+================================================================================
+## 版本更新
+Path: /docs/use/update
+================================================================================
+
+Mix Space 分为前端和后端两个部分,因此更新的时候二者也需要分开更新。
+## 小版本更新(常规)
+根据部署方式的不同,更新方式也有所不同。
+### Docker 部署
+进入 core 所在文件夹,执行:
+```bash
+docker compose pull && docker compose up -d
+```
+### 源码部署
+进入克隆 core 的文件夹,执行 `git pull origin master` 拉取新版本源码,随后正常进行构建:
+```bash
+pnpm i
+pnpm build
+pnpm bundle
+```
+随后进入 `./apps/core`,执行以下命令启动服务:
+```bash
+pm2 start ecosystem.config.js
+```
+## 大版本更新
+v12 是一次重大升级,数据库从 MongoDB 迁移到 PostgreSQL。不能简单 `docker compose pull` 升级,请务必阅读专用升级指南。
+ }
+ />
+## 前端更新
+请根据自己所部署的主题跳转到对应的更新部分完成更新。
+
+
+
+================================================================================
+## 常见问题
+Path: /docs/use/faq
+================================================================================
+
+## 部署相关
+### 忘记后台密码怎么办?
+如果你配置了 OAuth 登录(GitHub / Google),可以先通过第三方账号登录后台,再在「设定 → 个人信息」中修改密码。
+如果没有配置 OAuth,可以通过数据库直接修改密码字段来重置。
+### 如何修改网站标题和描述?
+登录后台,进入「设定 → SEO 优化」,修改网站标题和网站描述,保存后立即生效。
+### 后台地址是什么?
+默认后台地址为 `https://你的域名/proxy/qaqdmin`。如果开启了后台反代(「设定 → 后台附加设置」),也可以通过 API 地址直接访问。
+### 启动报错 `JWT_SECRET is required`
+JWT 密钥是必填项。在环境变量或 `docker-compose.yml` 中添加 `JWT_SECRET=你的随机字符串`(16-32 位)。
+### 启动报错 `SNOWFLAKE_WORKER_ID is required`
+单实例部署填 `SNOWFLAKE_WORKER_ID=1` 即可。
+## 内容相关
+### 文章的 URL 规则是什么?
+文章 URL 格式为 `/{分类 slug}/{文章 slug}`。分类 slug 和文章 slug 共同决定文章地址。例如分类 `coding` 下 slug 为 `hello-world` 的文章,URL 为 `/coding/hello-world`。
+### 如何为日记设置密码保护?
+在日记编辑面板中设置密码字段。设置后,访客需要输入密码才能查看日记内容。管理员在后台可以直接查看,不受限制。
+### 如何批量导入文章?
+在后台文章列表页面点击「导入」按钮,选择本地的 Markdown 文件。系统会自动解析 Frontmatter 中的标题、标签、分类等元数据。详见 [写作工作流](/docs/use/writing)。
+### 支持哪些编辑器格式?
+Mix Space 支持 **Markdown** 和 **Lexical 富文本**两种编辑格式。可以在编辑器中切换,也可以在设置中配置默认格式。
+## 图片与存储
+### 图片存在哪里?
+默认存储在服务器本地。你也可以配置 S3 兼容的对象存储(如 Cloudflare R2、AWS S3),详见 [图床与存储](/docs/configure/image-storage)。
+### 上传的图片 URL 格式是什么?
+- 本地存储:`/api/v2/static/{type}/{filename}`
+- S3 存储:`{自定义域名}/{前缀}/{filename}`
+自定义命名规则可以在「设定 → 文件上传设定」中配置。
+## 邮件与通知
+### 评论通知邮件不发送?
+请检查:
+1. 后台「设定 → 邮件通知设置」中是否开启了邮件提醒
+2. SMTP 配置是否正确(主机、端口、用户名、密码)
+3. 如果使用 Gmail,需要开启「应用专用密码」
+4. 服务器防火墙是否放行了 SMTP 端口(465/587)
+推荐使用 [Resend](https://resend.com) 等现代邮件 API 服务,配置更简单。
+### 如何推送到 Telegram / 微信?
+通过 Webhook 功能实现。在后台「其他 → Webhook」中创建一个 Webhook,Payload URL 填写你的通知服务地址,勾选关注的事件即可。详见 [Webhook 与事件通知](/docs/use/webhook)。
+## 数据库与迁移
+### 数据库可以迁移到另一台服务器吗?
+可以。推荐步骤:
+1. 在原服务器执行备份(后台备份或 `pg_dump`)
+2. 将备份文件传输到新服务器
+3. 在新服务器恢复数据并重启服务
+跨服务器迁移时,保持环境变量和配置一致,尤其是 `JWT_SECRET` 和加密密钥。
+### 如何从 MongoDB 迁移到 PostgreSQL?
+请参考 [v11 → v12 升级指南](/docs/migrate/v11-to-v12)。
+## 性能与优化
+### 站点访问速度慢?
+常见优化手段:
+1. **使用 CDN**:为静态资源和图片配置 CDN 加速
+2. **开启 S3 图床**:将图片托管到对象存储 + CDN
+3. **Redis 缓存**:确保 Redis 正常运行,Mix Space 大量依赖 Redis 缓存
+4. **反向代理优化**:开启 Nginx 的 gzip 压缩和静态文件缓存
+### Docker 容器占用内存过高?
+Mix Space 正常运行约需要 256-512MB 内存。如果内存占用异常,检查:
+- 是否有大量 AI 任务在后台运行
+- Redis 连接是否正常
+- 日志文件是否过大
+遇到文档中没有覆盖的问题?可以在 [GitHub Issues](https://github.com/mx-space/core/issues) 中搜索或提交新问题。
+
+================================================================================
+## 迁移概览
+Path: /docs/migrate/index
+================================================================================
+
+ }
+ href={'/docs/migrate/v11-to-v12'}
+ title="v11 → v12 升级"
+ >
+ 数据库从 MongoDB 迁移到 PostgreSQL 的完整指南
+
+ }
+ href={'/docs/migrate/from-wordpress'}
+ title="从 WordPress 迁移"
+ >
+ 将 WordPress 内容导出并导入到 Mix Space
+
+迁移前务必备份。数据无价。
+
+================================================================================
+## v11 升级到 v12
+Path: /docs/migrate/v11-to-v12
+================================================================================
+
+v12 是一次**重大版本升级**,底层数据库从 MongoDB 更换为 PostgreSQL。虽然你的文章、评论、配置等数据都会保留,但升级过程中需要执行一次数据迁移,且需要短暂的停站维护。
+**如果你当前版本低于 v11,请先升级到 v11,再执行本指南。**
+## 升级前必读(3 分钟)
+### 这次升级会变什么?
+- **数据库**:MongoDB → PostgreSQL(性能更好,数据关系更安全)
+- **备份方式**:以后用 `pg_dump` 代替 `mongodump`
+- **环境变量**:旧的 `DB_HOST`、`MONGO_CONNECTION` 等变量失效
+### 什么不会变?
+- 前端页面、API 接口和之前完全一致
+- 你的文章、评论、图片、配置全部保留
+- 登录方式、密码、API Key 不受影响
+### 我需要停站多久?
+| 数据规模 | 预估时间 |
+|---------|---------|
+| 文章 < 100 篇,评论 < 1000 条 | 5–10 分钟 |
+| 文章 < 1000 篇,评论 < 1 万条 | 10–30 分钟 |
+| 大型站点 | 30–60 分钟 |
+## 第一步:备份(必须)
+无论你用 Docker 还是源码部署,先执行备份:
+```bash
+# 进入你放 docker-compose.yml 的文件夹,或者 core 源码文件夹
+cd ~/mx-space/core
+# 备份 MongoDB 数据
+docker exec -i $(docker ps -q -f name=mongo) mongodump --archive > backup-mongo-$(date +%Y%m%d).archive
+# 同时打包整个数据目录(包含配置文件、图片等)
+tar czvf mx-space-full-backup-$(date +%Y%m%d).tar.gz ./data
+```
+**验证备份**:
+- `backup-mongo-YYYYMMDD.archive` 文件大小不为 0
+- `mx-space-full-backup-YYYYMMDD.tar.gz` 包含 `data/mx-space` 目录
+## Docker 部署升级
+### 1. 停止当前服务
+```bash
+cd ~/mx-space/core
+docker compose down
+```
+### 2. 更新配置文件
+```bash
+# 备份旧配置(以防万一)
+cp docker-compose.yml docker-compose.yml.v11.backup
+# 拉取 v12 的 docker-compose.yml(已内置 PostgreSQL)
+wget -O docker-compose.yml https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
+```
+### 3. 启动新数据库
+```bash
+# 只启动 PostgreSQL 和 Redis,先不启动主服务
+docker compose up -d postgres redis
+```
+等待 10 秒后检查状态:
+```bash
+docker compose ps
+```
+预期看到 `postgres` 和 `redis` 状态都是 `healthy` 或 `Up`。
+### 4. 执行数据迁移
+这是最关键的一步。执行前请确保没有用户在发文章或评论。
+```bash
+docker compose run --rm app npx tsx scripts/migrate-mongo-to-postgres.ts --mode apply
+```
+**预期输出**:
+- 看到 `Rows allocated: XXXX`,数字和你的文章/评论数量接近
+- 看到 `Missing refs: 0`(如果有少量数字,通常不影响)
+- 最后出现 `Migration completed successfully`
+**如果报错怎么办?**
+| 错误提示 | 原因 | 解决 |
+|---------|------|------|
+| `Connection refused` | PostgreSQL 还没启动好 | 等 30 秒重试 |
+| `Missing refs > 0` | 有孤儿数据 | 通常可忽略,截图记录后继续 |
+| 其他错误 | 未知问题 | **不要继续**,保留日志,回滚到 v11(见下方回滚章节) |
+### 5. 启动 v12
+```bash
+docker compose up -d
+```
+### 6. 验证(逐项检查)
+- [ ] 打开首页,文章列表正常显示
+- [ ] 打开一篇文章,内容和评论都在
+- [ ] 登录后台(`你的域名/proxy/qaqdmin`),能正常登录
+- [ ] 后台「其他 → 备份」页面能正常打开
+- [ ] 发一篇测试文章,能正常发布和显示
+- [ ] 删除测试文章,正常删除
+**全部通过 = 升级成功。**
+## 第三步:清理旧数据库(可选)
+建议 v12 稳定运行 **48 小时** 后再执行清理。保留旧数据是回滚的最后保障。
+### Docker 用户
+```bash
+cd ~/mx-space/core
+# 删除旧 MongoDB 容器
+docker compose rm -f mongo
+# 删除 MongoDB 数据卷(名字可能不同,先查看再删)
+docker volume ls
+docker volume rm mx-space_mongo_data # 请替换为实际卷名
+```
+### 源码用户
+```bash
+# 停止 MongoDB 服务
+sudo systemctl stop mongod
+# 是否卸载 MongoDB 请自行决定,建议至少保留备份文件 30 天
+```
+## 常见问题
+### 迁移会删除我的 MongoDB 数据吗?
+**不会。** 迁移是读取 MongoDB → 写入 PostgreSQL,MongoDB 原封不动。这就是回滚安全的根本原因。
+### 图片和附件会丢吗?
+**不会。** 图片、附件存在文件系统或对象存储里,不在数据库中,完全不受影响。
+### 迁移可以中断后再继续吗?
+**可以。** 重复执行迁移命令不会重复导入已迁过的数据,所以可以放心重试。
+### 我需要改前端吗?
+**一般不需要。** 官方主题(Shiro / Kami / Yohaku)直接兼容。只有直接调用 API 的第三方工具可能需要更新 SDK。
+### 为什么要换数据库?
+PostgreSQL 是更成熟的关系型数据库,数据一致性更好,未来做复杂查询和统计分析也更方便。对日常使用而言,你感觉不到明显变化,但长期更稳定可靠。
+
+================================================================================
+## 从 WordPress 迁移
+Path: /docs/migrate/from-wordpress
+================================================================================
+
+Mix Space 原生支持 Markdown 文件导入,这让从 WordPress 迁移变得相对简单。本指南将帮助你完成从导出到导入的完整流程。
+## 迁移前准备
+在开始之前,建议你:
+- [ ] 备份 WordPress 站点的所有数据和文件
+- [ ] 准备好 Mix Space 的运行环境(参考 [快速开始](/docs/getting-started/quick-start))
+- [ ] 确认 Mix Space 后台可以正常访问
+Mix Space 目前没有直接导入 WordPress WXR 格式的功能,需要先将内容转换为 Markdown 格式。
+## 迁移步骤
+### 导出 WordPress 内容
+在 WordPress 后台,进入「工具 → 导出」,选择「所有内容」,下载得到一个 XML 文件(WXR 格式)。
+如果你使用的是 WordPress.com,可以在「工具 → 导出」中导出站点内容。
+### 转换为 Markdown
+使用社区工具将 WordPress XML 转换为带有 Frontmatter 的 Markdown 文件。推荐工具:
+| 工具 | 说明 |
+|------|------|
+| [wordpress-export-to-markdown](https://github.com/lonekorean/wordpress-export-to-markdown) | 自动生成 Frontmatter,支持分类和标签 |
+| [wp2md](https://github.com/axdiamond/wp2md) | 轻量级转换工具 |
+以 `wordpress-export-to-markdown` 为例:
+```bash
+npx wordpress-export-to-markdown \
+ --input=wordpress.xml \
+ --output=markdown \
+ --frontmatter=true \
+ --save-attached-images=true
+```
+转换后会得到一组 `.md` 文件,每个文件的 Frontmatter 中包含标题、日期、分类、标签等信息。
+### 在 Mix Space 创建分类
+登录 Mix Space 后台,进入「分类」页面,提前创建好你在 WordPress 中使用的分类。确保分类名称一致,导入时系统才能正确匹配。
+如果导入时找不到对应分类,系统会自动创建新分类。
+### 导入 Markdown 文件
+登录 Mix Space 后台,进入「文章」页面,点击「导入」按钮,批量选择上一步生成的 Markdown 文件。
+系统会自动解析 Frontmatter 中的以下字段:
+| Frontmatter 字段 | 映射到 |
+|-------------------|--------|
+| `title` | 文章标题 |
+| `date` | 创建时间 |
+| `categories` | 分类 |
+| `tags` | 标签 |
+| `slug` | URL 路径 |
+| `status` | 发布状态(`publish` → 已发布) |
+### 处理图片
+WordPress 文章中的图片通常存放在 `wp-content/uploads/` 目录。迁移图片有三种方案:
+**方案一:迁移到 Mix Space 本地存储**
+将 WordPress 的 `uploads` 目录中的图片上传到 Mix Space 后台的「文件」管理中,然后批量替换文章中的图片链接。
+**方案二:使用对象存储**
+在 Mix Space 中配置 S3 图床(详见 [图床与存储](/docs/configure/image-storage)),将图片上传到对象存储,然后批量替换链接。
+**方案三:保留原链接**
+如果原 WordPress 站点的图片链接仍然可用,可以暂时保留不做处理。但建议最终迁移到 Mix Space 的存储中,避免原站点关闭后图片丢失。
+推荐使用批量查找替换的方式更新文章中的图片 URL:
+```sql
+-- 在数据库中批量替换图片链接(请先备份!)
+UPDATE posts SET text = REPLACE(text, 'old-domain.com/wp-content/uploads', 'new-domain.com/api/v2/static/image');
+```
+### 验证迁移结果
+迁移完成后,逐一检查以下内容:
+- [ ] 文章数量是否与原站点一致
+- [ ] 文章内容和格式是否正确(特别是代码块、表格等)
+- [ ] 分类和标签是否正确匹配
+- [ ] 图片是否正常显示
+- [ ] 文章 slug 是否与旧站一致(影响 SEO)
+## 评论迁移
+Mix Space 目前没有直接导入 WordPress 评论的功能。评论数据需要手动迁移或借助脚本辅助。
+如果你的站点评论较多,可以考虑:
+1. 通过脚本读取 WordPress 导出的 XML 中的评论数据
+2. 调用 Mix Space API 批量创建评论
+3. 或者接受从零开始,不迁移历史评论
+## SEO 过渡建议
+迁移完成后,建议进行以下 SEO 相关操作:
+| 操作 | 说明 |
+|------|------|
+| **301 重定向** | 将旧 WordPress 链接重定向到新的 Mix Space 链接 |
+| **更新 Sitemap** | Mix Space 会自动生成新的 Sitemap |
+| **提交搜索引擎** | 在百度/Bing 站长工具中重新提交站点地图 |
+| **保留 robots.txt** | 确保新的 robots.txt 配置正确 |
+### URL 映射规则
+WordPress 和 Mix Space 的 URL 结构不同,需要做重定向映射:
+| WordPress URL | Mix Space URL |
+|---------------|---------------|
+| `/?p=123` | `/{分类 slug}/{文章 slug}` |
+| `/2024/01/hello-world/` | `/{分类 slug}/{文章 slug}` |
+建议在 Nginx 中配置 rewrite 规则:
+```nginx
+# 示例:将 WordPress 固定链接重定向到 Mix Space
+location / {
+ # 如果旧文章有固定链接格式,可以逐条重定向
+ # rewrite ^/2024/01/hello-world/$ /coding/hello-world permanent;
+}
+```
+## 参考资源
+- [社区博文:从 WordPress 迁移数据到 Mix Space](https://blog.fosky.top/2024/10/09/wordpress-to-mix-space.html)
+- [GitHub: wordpress-export-to-markdown](https://github.com/lonekorean/wordpress-export-to-markdown)
+
+================================================================================
+## 开发指南
+Path: /docs/develop/index
+================================================================================
+
+Mix Space 是完全开源的,欢迎每一位开发者参与贡献。无论你是想修复 Bug、添加新功能,还是基于我们的 API 开发自己的前端主题,这里都能帮助你快速上手。
+## 技术栈
+| 层级 | 技术 |
+|------|------|
+| 后端框架 | [NestJS](https://nestjs.com/) 11 + Fastify |
+| 语言 | [TypeScript](https://www.typescriptlang.org/) |
+| 数据库 | [PostgreSQL](https://www.postgresql.org/) 16 + [Drizzle ORM](https://orm.drizzle.team/) |
+| 缓存 | [Redis](https://redis.io/) 7 |
+| 前端框架 | [React](https://react.dev/) / [Vue 3](https://vuejs.org/) |
+| 容器化 | [Docker](https://www.docker.com/) |
+## 环境要求
+在开始之前,请确保你的开发环境已安装以下工具:
+- [ ] [Node.js](https://nodejs.org/) >= 22(推荐使用 `.nvmrc` 中的版本)
+- [ ] [pnpm](https://pnpm.io/)(通过 Corepack 启用:`corepack enable`)
+- [ ] [PostgreSQL](https://www.postgresql.org/) >= 16
+- [ ] [Redis](https://redis.io/) >= 7
+- [ ] [Git](https://git-scm.com/)
+## 快速开始(后端)
+```bash
+# 克隆仓库
+git clone https://github.com/mx-space/core
+cd core
+# 安装依赖
+pnpm i
+# 启动 PostgreSQL 和 Redis
+docker compose up -d postgres redis
+# 启动开发服务器(端口 2333)
+pnpm dev
+```
+ 提交 PR 时请确保使用 pnpm 安装依赖,项目根目录只保留 `pnpm-lock.yaml`。
+## 了解更多
+
+================================================================================
+## 后端开发
+Path: /docs/develop/backend
+================================================================================
+
+## 项目结构
+`apps/core/src/` 是后端的核心源码目录,主要结构如下:
+```
+src/
+├── modules/ # 业务模块(Post、Note、User 等)
+├── processors/ # 全局处理器(Database、Gateway、Redis 等)
+├── common/ # 公共工具(装饰器、过滤器、拦截器、管道)
+├── database/ # 数据库 schema 与迁移文件
+├── constants/ # 常量定义
+├── types/ # 全局类型声明
+├── utils/ # 工具函数
+├── app.module.ts # 根模块
+└── main.ts # 应用入口
+```
+每个业务模块通常包含 `module.ts`、`controller.ts`、`service.ts` 三个标准文件,遵循 NestJS 的模块化设计。
+## 添加新模块
+标准的 NestJS 模块结构如下:
+```
+src/modules/example/
+├── example.module.ts
+├── example.controller.ts
+├── example.service.ts
+└── dto/
+ └── example.dto.ts
+```
+然后在 `app.module.ts` 中导入新模块即可。如果模块需要数据库支持,先在 `database/schema/` 中定义表结构,再通过 Drizzle ORM 进行操作。
+## 数据库
+Mix Space 使用 [Drizzle ORM](https://orm.drizzle.team/) 管理 PostgreSQL 数据库。
+- **Schema 位置**: `apps/core/src/database/schema/`
+- **迁移文件位置**: `apps/core/src/database/migrations/`
+- **配置文件**: `apps/core/drizzle.config.ts`
+### 常用命令
+```bash
+# 生成迁移
+pnpm drizzle-kit generate
+# 执行迁移
+pnpm drizzle-kit migrate
+```
+Schema 中统一使用 `snake_case` 命名字段,Drizzle 配置已开启 `casing: 'snake_case'` 以确保自动映射。
+## API 设计
+### RESTful 规范
+- 使用标准的 HTTP 方法:`GET`、`POST`、`PATCH`、`DELETE`
+- URL 使用名词复数,如 `/posts`、`/notes`
+- 嵌套资源通过路径表达,如 `/posts/:id/comments`
+### 响应格式
+接口返回统一使用 `snake_case`,结构如下:
+```json
+{
+ "data": {},
+ "pagination": {
+ "page": 1,
+ "per_page": 10,
+ "total": 100
+ }
+}
+```
+### 分页
+列表接口默认支持分页查询,通过 `page` 和 `per_page` 参数控制,最大 `per_page` 通常限制为 50。
+## 测试
+后端使用 [Vitest](https://vitest.dev/) 进行测试,测试文件位于 `apps/core/test/` 目录。
+```bash
+# 运行测试
+pnpm test
+# 监听模式
+pnpm test:watch
+```
+测试环境通过 `test/setup.ts` 完成初始化,包括内存数据库和其他依赖的启动。编写测试时请注意保持测试的独立性,避免测试之间产生状态污染。
+## 代码规范
+- **ESLint**: 统一代码风格,提交前运行 `pnpm lint`
+- **Prettier**: 自动格式化,建议开启编辑器保存时自动格式化
+- **Commit Message**: 请遵守 [Conventional Commits](https://www.conventionalcommits.org/) 规范,仓库内可使用 `pnpm commit` 引导生成
+更多关于文档贡献的规范,请参阅 [贡献文档](/docs/develop/contribute)。
+
+================================================================================
+## 前端开发
+Path: /docs/develop/frontend
+================================================================================
+
+> 为什么要写这一节?
+>
+> 我希望不再是只有 Kami 一个风格,能有更多主题可供选择。
+Mix Space 采用前后端分离架构,后端不提供模板渲染,因此前端项目可以使用任何框架和架构设计。前端与后端完全解耦,你可以自由选择 React、Vue、Svelte 或其他技术栈来构建自己的主题。
+虽然开发比较自由,但在接口调用、数据定义和路由约定上仍需保持一致。本节将具体说明前端项目的开发规范。
+## 路由约定
+[Kami](https://github.com/mx-space/kami) 是由 Next.js、React 开发的原始项目,经过长时间的沉淀,前端项目路由的组织上建议遵守以下约定:
+> 路由的约定能很大程度保证网站因更换不同前端主题导致 SEO 异常、死链接等问题。
+约定如下:
+| Path | Description | Mark |
+| ------------------------ | -------------------------------- | -------- |
+| `/` | 主页 | 强制要求 |
+| `/posts` | 博文列表 | 强制要求 |
+| `/posts/:category/:slug` | 博文详情页 | 强制要求 |
+| `/pages/:slug` | 独立页面详情页 | 强制要求 |
+| `/notes/:nid` | 日记详情页 | 强制要求 |
+| `/feed` | RSS 订阅 | 强制要求 |
+| `/:category/:slug` | 302 -> `/posts/:category/:slug` | 建议 |
+| `/category/:slug` | 分类中文章列表页 | 建议 |
+| `/notes` | 日记列表或者跳转最新日记页 | 建议 |
+| `/notes/latest` | 最新日记详情页 | 建议 |
+| `/friends` | 友链 | 建议 |
+| `/says` | 一言详情页 | 可选 |
+| `/sitemap` | 站点地图 | 建议 |
+| `/timeline` | 时间线 | 可选 |
+| `/recently` | 动态页 | 可选 |
+| `/favorite/:type` | 附加页 | 可选 |
+| `/projects` | 项目页 | 可选 |
+| `/projects/:id` | 项目详情页 | 可选 |
+## 框架选择建议
+建议选择附带 SSR 功能的现代化框架:
+- React:Next.js、[RakkasJS](https://github.com/rakkasjs/rakkasjs)、umi
+- Vue: Vite (vite-ssr)、NuxtJS
+小程序:
+- React: Remax、taro
+- Vue: uni-app
+## 接口调用与 SDK 的使用
+考虑到单独编写接口定义和返回类型太麻烦,这里提供一个 SDK 方便开发。
+> SDK 仍在 beta 阶段,未来接口可能出现变化。
+详见:[api-client](https://github.com/mx-space/core/tree/master/packages/api-client)
+
+================================================================================
+## 后台单独部署
+Path: /docs/develop/admin
+================================================================================
+
+在正常情况下,你不需要单独部署后台,因为后台已经被打包到了后端中。
+如果你有以下需求:
+- 想使用其他域名作为后台地址
+- 想使用其他端口作为后台地址
+那么你可以选择单独部署后台,或者你可以参考 [反向代理配置](/themes/kami#反向代理)。
+## 拉取源文件
+```bash
+cd mx-space
+git clone https://github.com/mx-space/mx-admin.git --depth 1
+```
+## 修改配置文件
+进入到后台源码目录,找到 `.env.production` 文件,取消对应配置项的注释,然后修改为你的配置。
+例如:
+```yaml
+VITE_APP_BASE_API=https://server.test.cn/api/v2
+VITE_APP_WEB_URL=https://www.test.cn
+VITE_APP_GATEWAY=https://server.test.cn
+# # VITE_APP_PUBLIC_URL=https://fastly.jsdelivr.net/gh/mx-space/admin-next@gh-pages/
+```
+其他可以定义的配置在文件 `/src/configs.ts` 中。
+## 构建
+ 构建 mx-admin 需要的内存至少为 2 GiB,如果你服务器内存不足,你可以在本地构建成功后,将产物上传到服务器。
+ 在 Windows 系统上,mx-admin 无法正常构建,你可以使用 WSL2 或者 Linux 系统。
+```bash
+pnpm i
+pnpm build
+```
+## 部署产物
+构建生成的产物在 dist 目录下,你可以直接把它们移动到你准备好的后台网站的根目录下。
+假设你准备的后台网站域名是 `admin.test.cn`,
+网站根目录为 `/var/www/admin.test.cn/`,
+那么,你把 dist 目录下的所有文件移动到 `/var/www/admin.test.cn/` 目录下即可。
+## 修改后端配置
+编辑 Core 的 `.env` 文件,修改 `ALLOWED_ORIGINS` ,添加你的后台域名。
+示例域名为 `admin.test.cn` 。
+例如:
+```yaml
+# THIS ENV FILE EXAMPLE ONLY FOR DOCKER COMPOSE
+# SEE https://docs.docker.com/compose/environment-variables/#the-env-file
+JWT_SECRET=7294c34e0b28ad28 # 此处填写一个长度不小于 16 个字符,不大于 32 个字符的字符串
+ALLOWED_ORIGINS=test.cn,www.test.cn,admin.test.cn
+```
+然后重新启动 Core 即可:
+```bash
+docker compose up -d
+```
+
+================================================================================
+## 贡献文档
+Path: /docs/develop/contribute
+================================================================================
+
+我们随时欢迎你对 Mix Space 的文档做出贡献,但撰写文档是一件不易之事,我们更加希望你能规范贡献内容,减少我们的工作量。
+ 部分内容来自于 https://github.com/mx-space/docs-archived/pull/163
+在撰写本文档之前,请确保你有基础的 Markdown 知识,并了解 Markdown 的语法,如果你不够了解,请使用 Typora 等 Markdown 编辑器进行撰写。
+目前 Mix Space 的文档使用的框架是 [Fumadocs](https://fumadocs.vercel.app/),请在撰写之前详细阅读它的文档,并在本地运行开发服务器检查效果,确保符合预期后再提交 Pull Request。
+## 本地预览
+```bash
+# 安装依赖
+pnpm i
+# 启动开发服务器
+pnpm dev
+```
+在浏览器中打开 `http://localhost:3000` 预览你的修改。
+## 添加新页面
+文档内容位于 `content/docs/` 目录下,添加新页面的步骤如下:
+1. 在对应章节文件夹下新建文件夹或 `.mdx` 文件
+2. 如果新建了文件夹,在文件夹内创建 `meta.json` 定义标题和页面顺序
+3. 编写 `.mdx` 文件内容
+4. 在 `meta.json` 的 `pages` 数组中添加新页面路径
+示例 `meta.json`:
+```json
+{
+ "title": "章节标题",
+ "pages": ["index", "new-page"]
+}
+```
+## 规范
+- 文档只写最容易理解的方式,不要教别人改源码
+- 中英文之间加空格
+- 撰写 Git Commit Message 时尽可能遵守 [Conventional Commits](https://www.conventionalcommits.org/) 规范,不了解可使用 `pnpm commit` 引导生成
+## 常见问题
+
+
+为什么要写这么全面呢?甚至教别人改动源码。
+这是极不正确的文档写法。
+别人会写的自然会写,不会写的教他,他会不知道这个地方到底要不要搞、怎么搞、是不是有另外一种方法。
+更多的选择只会影响新手的判断,让他们不知道到底该怎么做。
+偏偏就是出现改动源码的地方就是有多种选择:
+你可以在文件后方传入值,比如 `node index.js --arg1=value1`
+你可以改动源码,在 xxx/xxx.ts 第 xxx 行到 xxx 行,修改对应的配置。
+你甚至可以写一个插件,在插件中进行配置。
+你这样让用户怎么选择?文档部署应该只选择最容易让人读明白的部署方式,这种改动源码的提一嘴在哪个文件就是了,为什么要写具体行数 & 告诉别人怎么改呢?
+如果碰到了一个 object,用户改漏了一个逗号,那这个问题的责任谁来承担呢?文档编写者吗?开发者吗?用户吗?
+很明显都不是,也很明显都要承担责任。不要让局面陷入到如此困境中 😕
+如果你有魔改方面的内容,可以提交到对应区域的社区部署教程内。
+
+
+这些面板程序随时都有可能会发生变化,我们无法保证文档的时效性。
+我们也不建议这样写任何官方类文档,因为会使得你的文档结构更加复杂,并且难以维护。
+本质上服务器面板部署方式的核心还是那几种方式。
+如果你有相关内容,可以提交到对应区域的社区部署教程内。
+
+
+## 提交 PR
+文档仓库地址:[github.com/mx-space/docs](https://github.com/mx-space/docs)
+1. Fork 仓库到你的账号
+2. 在功能分支上进行修改
+3. 本地预览确认无误后提交
+4. 向原仓库发起 Pull Request
+我们希望文档的结构能够更加简洁易用,这样对开发者,对用户都有好处。
+
+================================================================================
+## 参考手册
+Path: /docs/reference/index
+================================================================================
+
+不需要通读,遇到问题时来查。
+ }>
+ 所有环境变量的完整列表和说明
+
+ }>
+ 按症状分类的常见问题与解决方案
+
+ }>
+ 在 GitHub 上查看 API Client 文档
+
+================================================================================
+## 常见错误与解决
+Path: /docs/reference/common-issues
+================================================================================
+
+## 无法启动服务
+### `Error: JWT_SECRET is required`
+- **原因**:JWT 签名密钥未设置,这是启动服务的必填项。
+- **解决**:在环境变量中添加 `JWT_SECRET`,设置一个随机字符串即可。
+### `Error: SNOWFLAKE_WORKER_ID is required`
+- **原因**:Snowflake 工作节点 ID 未设置。
+- **解决**:在环境变量中添加 `SNOWFLAKE_WORKER_ID=1`(单实例部署填 1 即可)。
+### `Connection refused to postgres:5432`
+- **原因**:PostgreSQL 服务未启动,或连接配置错误。
+- **解决**:
+ 1. 确认 PostgreSQL 容器或服务已正常运行;
+ 2. 检查 `PG_HOST`、`PG_PORT`、`PG_USER`、`PG_PASSWORD` 是否正确;
+ 3. Docker 部署时,注意容器之间的网络是否互通。
+## 无法访问后台
+### 502 Bad Gateway
+- **原因**:反向代理(Nginx/Caddy)配置错误,无法正确代理到后端服务。
+- **解决**:检查反向代理配置中的 upstream 地址和端口,确认后端服务端口是否为 `2333`(或你自定义的 `PORT`)。
+### 证书错误
+- **原因**:HTTPS/SSL 证书配置有问题,或使用了自签名证书但客户端不信任。
+- **解决**:检查证书是否过期,确认 Nginx/Caddy 的 SSL 配置正确,必要时重新申请证书。
+## 功能异常
+### 搜索不工作
+- **原因**:Algolia 配置缺失或错误,索引未建立。
+- **解决**:
+ 1. 进入后台检查 Algolia 的 `IndexName`、`AppID`、`ApiKey` 是否填写正确;
+ 2. 确认 Algolia 控制台中索引已创建且有数据;
+ 3. 保存配置后等待片刻,让系统自动同步索引。
+### 第三方登录失败
+- **原因**:OAuth 应用的回调地址(Callback URL)与后台配置不一致。
+- **解决**:
+ 1. 在 GitHub/Google 控制台核对 `Authorization callback URL`;
+ 2. 在 Mix Space 后台复制正确的回调地址并填入 OAuth 应用;
+ 3. 确认 `ALLOWED_ORIGINS` 中包含了你的前端域名。
+## 数据相关
+### 备份文件无法下载
+- **原因**:备份目录权限不足,或备份路径配置错误。
+- **解决**:检查备份目录的读写权限,确认运行服务的用户有权访问该目录。
+### 回滚后数据丢失
+- **原因**:回滚时使用了错误的备份文件,或备份文件本身已损坏。
+- **解决**:
+ 1. 确认使用的是正确的备份文件(注意时间戳);
+ 2. 回滚前务必先对当前数据做一次备份;
+ 3. 若备份文件损坏,尝试使用更早的备份。
diff --git a/public/llm.txt b/public/llm.txt
new file mode 100644
index 00000000..2c31ec2d
--- /dev/null
+++ b/public/llm.txt
@@ -0,0 +1,116 @@
+# Mix Space — llm.txt
+
+> Mix Space is an AI-powered headless CMS for personal blogs and content sites.
+> Documentation: https://mx-space.js.org/docs
+
+## What is Mix Space?
+
+Mix Space is a self-hosted, open-source CMS built with a headless architecture. It consists of:
+
+- **Core (Backend)**: NestJS 11 + Fastify + PostgreSQL 16 + Redis 7
+- **Admin Dashboard**: Vue 3 + Naive UI + TanStack Query
+- **Frontend Themes**: Next.js (Shiro, Yohaku) or other community themes
+
+Source code: https://github.com/mx-space/core
+
+## Quick Start (Docker)
+
+```bash
+git clone https://github.com/mx-space/core.git --depth=1
+cd core
+# Edit JWT_SECRET and ALLOWED_ORIGINS in docker-compose.yml
+docker compose up -d
+# Access admin at http://localhost:2333/proxy/qaqdmin
+```
+
+## Architecture
+
+- **API prefix**: `/api/v2` in production, no prefix in dev (port 2333)
+- **Auth**: JWT + Passkey + OAuth (GitHub/Google) via better-auth
+- **Database**: PostgreSQL 16 (Drizzle ORM)
+- **Cache**: Redis 7
+- **Response format**: All keys auto-converted to snake_case
+ - Array → `{ data: [...] }`
+ - Paginated → `{ data: [...], pagination: {...} }`
+ - `@Bypass` → skip transform
+
+## Content Types
+
+| Type | URL Format | Notes |
+|------|-----------|-------|
+| Post (文章) | `/{category-slug}/{post-slug}` | Has category, tags, pin, related posts |
+| Note (日记) | `/notes/{nid}` or `/notes/{y}/{m}/{d}/{slug}` | Has mood, weather, password, topic |
+| Page (页面) | `/{slug}` | Standalone pages (about, friends, etc.) |
+| Say (说说) | Short-form content, like tweets | |
+| Project (项目) | Portfolio showcase items | |
+
+All content types support Markdown and Lexical rich text editing.
+
+## AI Features
+
+Requires configuring at least one LLM provider (OpenAI / OpenAI-compatible / Anthropic / OpenRouter).
+
+| Feature | Description |
+|---------|-------------|
+| AI Summary | Auto-generate article summaries, multi-language |
+| AI Insights | Deep reading companion (TL;DR, structure map, Mermaid) |
+| AI Translation | Markdown + Lexical dual strategy, translation glossary |
+| AI Writer | Auto-generate title and SEO slug, bulk slug backfill |
+| AI Comment Review | Binary/score spam detection |
+| AI Agent | In-editor chat with AI |
+| AI Task Queue | Unified task management (batch, bulk, retry) |
+
+## Key Configuration Sections
+
+All config is managed via admin UI (设定 → System settings):
+
+- **SEO**: Title, description, keywords, sitemap, RSS feed
+- **Mail**: SMTP or Resend, used for notifications and subscriptions
+- **Comments**: Anti-spam, AI review, guest policy, IP blocking, image uploads
+- **File Upload**: Custom naming templates, S3 image storage
+- **OAuth**: GitHub and Google login setup
+- **Friend Links**: Application rules, avatar internalization
+- **Backup**: Auto backup to S3
+- **AI**: Multi-provider, per-feature model assignment, auto-trigger hooks
+
+## API Token
+
+Create tokens in admin (设定 → 账号与安全 → API Token). Required for:
+- Obsidian plugin
+- `@mx-space/api-client` SDK
+- Custom scripts and automation
+
+## Snippets / Serverless
+
+Extension system supporting JSON, Text, YAML, and Function types:
+- Function snippets = serverless cloud functions (custom API routes at `/s/{path}`)
+- Used for: Bilibili integration, music lists, custom data endpoints
+- Community snippets: https://github.com/mx-space/snippets
+
+## Webhook
+
+Push events to external services (Telegram, Slack, etc.). 30+ event types including:
+- Content CRUD (post, note, page, comment)
+- AI events (translation, insights)
+- Link applications
+
+## Deployment Options
+
+| Method | Difficulty | Best For |
+|--------|-----------|----------|
+| Docker | Easy | Most users (recommended) |
+| One-click script | Easy | Quick automated setup |
+| Source build | Hard | Developers |
+
+## Documentation Pages
+
+Full docs at https://mx-space.js.org/docs:
+
+- Getting Started: what you need, quick start
+- Deploy: Docker, one-script, source, reverse proxy, SSL, external services
+- Configure: environment variables, SEO, OAuth, Algolia, encryption, account security, image storage
+- Themes: Yohaku, Shiro, Kami, Yun, community themes
+- Use: writing workflow, content management, comments, friends, says, projects, files, analytics, AI features, webhook, mail & subscribe, serverless, cron tasks, backup, update, FAQ
+- Migrate: v11→v12 (MongoDB→PostgreSQL), WordPress
+- Develop: backend, frontend, admin, contribute
+- Reference: common issues
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 00000000..7fb0bf5b
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,10 @@
+User-agent: *
+Allow: /
+
+Sitemap: https://mx-space.js.org/sitemap.xml
+
+# LLM / AI crawlers
+User-agent: *
+Allow: /llm.txt
+Allow: /llm-full.txt
+Allow: /agent-skills/
diff --git a/scripts/generate-sitemap.ts b/scripts/generate-sitemap.ts
index 9a6f1124..3c2a3040 100644
--- a/scripts/generate-sitemap.ts
+++ b/scripts/generate-sitemap.ts
@@ -7,11 +7,14 @@ async function generate() {
// 根据 meta.json 文件结构生成路径
const pages = await fg([
- 'content/docs/core/**/*.mdx',
- 'content/docs/development/**/*.mdx',
- 'content/docs/document/**/*.mdx',
+ 'content/docs/getting-started/**/*.mdx',
+ 'content/docs/deploy/**/*.mdx',
+ 'content/docs/configure/**/*.mdx',
+ 'content/docs/develop/**/*.mdx',
'content/docs/themes/**/*.mdx',
- 'content/docs/usage/**/*.mdx',
+ 'content/docs/use/**/*.mdx',
+ 'content/docs/migrate/**/*.mdx',
+ 'content/docs/reference/**/*.mdx',
'!content/docs/**/meta.json',
'!content/docs/**/_*.mdx'
])
diff --git a/tsconfig.json b/tsconfig.json
index 755e6448..4f8fc183 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,6 +6,7 @@
"allowJs": true,
"skipLibCheck": true,
"strict": true,
+ "ignoreDeprecations": "6.0",
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
diff --git a/utils/get-contributors.ts b/utils/get-contributors.ts
index 08611358..1d9ee993 100644
--- a/utils/get-contributors.ts
+++ b/utils/get-contributors.ts
@@ -21,7 +21,8 @@ export interface Contributor {
);
if (!response.ok) {
- throw new Error(`Failed to fetch contributors: ${response.statusText}`);
+ console.warn(`Failed to fetch contributors: ${response.statusText}`);
+ return [];
}
const contributors = (await response.json()) as Contributor[];