.r2.cloudflarestorage.com` |
| Region | `auto` |
| 自定义域名 | R2 绑定的自定义域名或 `r2.dev` 公开访问地址 |
### AWS S3 [#aws-s3]
| 字段 | 值 |
| ------- | ------------------------------ |
| S3 服务端点 | 留空(使用默认)或区域端点 |
| Region | 如 `us-east-1`、`ap-southeast-1` |
| 自定义域名 | CloudFront 分发域名 |
### 阿里 OSS / 腾讯 COS [#阿里-oss--腾讯-cos]
按照对应服务的 S3 兼容接口文档填写 Endpoint 和 Region 即可。
## 评论图片专用前缀 [#评论图片专用前缀]
在「评论图片路径前缀」字段中,可以为读者评论上传的图片设置独立的存储路径前缀。该字段额外支持 `{readerId}` 占位符,按读者 ID 组织目录。
留空则使用默认路径:`comments/{readerId}/{Y}/{m}/{md5}.{ext}`
## 备份到 S3 [#备份到-s3]
在「设定 → 备份」中也可以配置 S3 信息,将数据库备份文件同时上传到 S3 存储,实现异地备份。详见 [备份与恢复](/docs/use/backup-restore)。
# 功能配置概览 (/docs/configure)
## 我想实现的功能 [#我想实现的功能]
| 我想实现... | 查看文档 |
| ---------------------- | ----------------------------------------- |
| 设置第三方登录(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) |
| 加密敏感配置 | [Key 加密](/docs/configure/encryption) |
| 了解所有环境变量 | [环境变量参考](/docs/configure/environment) |
## 快速导航 [#快速导航]
查看所有支持的环境变量及其说明
SEO 元数据、Sitemap、RSS、百度/Bing 推送
所有者信息、API Token、Passkey、OAuth 绑定
S3 对象存储配置、CDN 加速、自定义存储路径
配置 GitHub、Google 等第三方登录
加密数据库中的敏感配置项
# OAuth 2.0 登录 (/docs/configure/oauth)
Mix Space 支持通过第三方 OAuth 账号登录后台,免去记忆密码的麻烦。目前支持 GitHub 和 Google 两种 OAuth 服务商。
OAuth 登录基于 better-auth 实现,不走 Clerk 等第三方认证服务,所有数据存储在你自己的数据库中。
## 前置条件 [#前置条件]
在配置 OAuth 之前,请确保:
* 后端服务已正常运行
* 前端和后端都已配置好 HTTPS(OAuth 回调要求 HTTPS)
* 你有 GitHub 或 Google 的开发者账号
## 配置 GitHub 登录 [#配置-github-登录]
### 创建 GitHub OAuth 应用 [#创建-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-登录]
### 创建 Google OAuth 客户端 [#创建-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**
### 在后台配置 [#在后台配置-1]
登录后台,进入「设定 → 登录方式」,在 Google 部分填入 Client ID 和 Client Secret,保存。
### 测试并绑定 [#测试并绑定-1]
在前端登录页面点击 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-提示application-suspended]
* 检查 GitHub OAuth 应用的状态,可能因为长时间未使用被暂停
* 确认 Client Secret 未过期(GitHub Secret 有过期时间设置)
### Google 提示「未验证应用」 [#google-提示未验证应用]
* 在 Google Cloud Console 中将应用发布为「正式版」
* 或者添加测试用户账号
# SEO 与站点优化 (/docs/configure/seo)
Mix Space 内置了 SEO 基础功能,包括自定义站点元数据、自动生成 Sitemap 和 RSS Feed,以及百度/Bing 搜索引擎推送。
## SEO 基础设置 [#seo-基础设置]
进入后台「设定 → SEO 优化」,配置以下信息:
| 配置项 | 说明 |
| ------------ | -------------------- |
| **网站标题** | 站点名称,显示在浏览器标签和搜索结果中 |
| **网站描述** | 一段简短的站点描述,用于搜索引擎结果摘要 |
| **浅色图标 URL** | 浅色模式下的站点图标 |
| **深色图标 URL** | 深色模式下的站点图标 |
| **关键字** | 站点关键词列表,用于搜索引擎识别站点主题 |
这些信息会自动应用到前端页面的 `` 标签中。
## 网站地址 [#网站地址]
进入后台「设定 → 网站设置」,正确填写站点地址:
| 配置项 | 说明 |
| -------------- | --------------------------------------------- |
| **前端地址** | 你的前端主题地址(如 `https://example.com`) |
| **管理后台地址** | 后台管理地址(如 `https://example.com/proxy/qaqdmin`) |
| **API 地址** | 后端 API 地址 |
| **Gateway 地址** | WebSocket 网关地址 |
「前端地址」非常重要,Sitemap 和 RSS 中的链接都基于此地址生成。请确保填写正确的完整 URL(包含 `https://`)。
## Sitemap [#sitemap]
Mix Space 自动生成 Sitemap 文件,无需额外配置。
访问 `https://你的API地址/sitemap` 即可获取标准的 XML Sitemap,其中包含所有已发布内容的 URL 和更新时间。
Sitemap 缓存 1 小时,内容更新后会自动刷新。
## RSS Feed [#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 搜索引擎推送 |
| **Bing API 密钥** | Bing Webmaster Tools 的 API 密钥 |
在 [Bing Webmaster Tools](https://www.bing.com/webmasters) 中注册并验证站点后,可以在 API 设置中获取密钥。
搜索引擎推送会在内容创建和更新时自动触发,无需手动操作。
# 使用 AI Agent 部署 (/docs/deploy/agent)
如果你不熟悉 Linux 运维,或者不想手动执行命令,可以使用 AI 编程助手来帮你完成整个部署过程。你只需要用自然语言描述需求,Agent 会自动在服务器上执行操作。
## 支持的 Agent 工具 [#支持的-agent-工具]
| 工具 | 说明 | 适用场景 |
| -------------------- | ------------------------ | --------------- |
| **Claude Code** | Anthropic 的终端编程助手,支持远程执行 | 推荐新手使用 |
| **Codex CLI** | OpenAI 的命令行 Agent | 习惯 OpenAI 生态的用户 |
| **Cursor** | AI 代码编辑器,支持终端 | 想在编辑器里操作的用户 |
| **其他 MCP/SSH Agent** | 任何能 SSH 到服务器的 AI 工具 | 高级用户 |
以下以 Claude Code 为例,其他 Agent 工具的流程类似——核心都是让 Agent 通过 SSH 连接到你的服务器并执行部署命令。
## 准备工作 [#准备工作]
### 准备一台服务器 [#准备一台服务器-step]
你需要一台已安装 Linux 的服务器(推荐 Ubuntu 22.04+),并确保:
* 可以通过 SSH 连接
* 有 root 或 sudo 权限
* 80 和 443 端口未占用
记录以下信息:
* 服务器 IP 地址
* SSH 端口(默认 22)
* 登录用户名和密码(或 SSH 密钥)
### 准备域名 [#准备域名-step]
将你的域名 A 记录指向服务器 IP:
| 记录类型 | 名称 | 值 |
| ---- | ----- | ------------ |
| A | `@` | 你的服务器 IP |
| A | `www` | 你的服务器 IP(可选) |
### 安装 Agent 工具 [#安装-agent-工具-step]
以 Claude Code 为例,在本地电脑上安装:
```bash
npm install -g @anthropic-ai/claude-code
```
其他工具请参考各自的安装文档。
## 开始部署 [#开始部署]
### 将 Mix Space 文档交给 Agent [#将-mix-space-文档交给-agent-step]
| 地址 | 功能 |
| :----------------------------------------------------------------------------- | :---------------------- |
| [https://mx-space.js.org/llms.txt](https://mx-space.js.org/llms.txt) | 可被 LLMs 采集使用的文档目录索引 TXT |
| [https://mx-space.js.org/llms-full.txt](https://mx-space.js.org/llms-full.txt) | 可被 LLMs 完整采集使用的文档 TXT |
为了让 Agent 了解 Mix Space 的部署方式,先让它读取文档。在 Agent 对话中发送:
```
请帮我部署 Mix Space。先阅读以下文档了解部署方式:
- https://mx-space.js.org/llms.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-你的信息-step]
将以下信息提供给 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-自动执行-step]
Agent 会依次执行以下操作:
1. **SSH 连接**到你的服务器
2. **安装 Docker**(如果尚未安装)
3. **克隆配置文件**并编辑环境变量
4. **启动服务** `docker compose up -d`
5. **安装 Nginx** 并配置反向代理
6. **申请 SSL 证书**(Certbot 或其他方式)
7. **验证**服务可以通过 HTTPS 访问
你只需要在 Agent 询问时确认操作即可。
### 验证部署 [#验证部署-step]
让 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 模板 [#常用-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) 页面。
# 社区部署方案 (/docs/deploy/community)
你可以参考他们的部署方式,但我们不保证它们的可用性。如果你也有教程想要与大家分享的话,欢迎您向文档提交
[Pull Request](https://github.com/mx-space/docs/pulls) 以分享您的部署方式。
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
# Docker 部署 (/docs/deploy/docker)
## 安装 Docker [#安装-docker-step]
不论在海外还是中国大陆境内我们都可以使用 Linuxmirrors 提供的 Docker 安装脚本来安装 Docker 和 Docker Compose,它具备可在多种系统上安装 Docker 的能力:
```bash
bash <(curl -sSL https://linuxmirrors.cn/docker.sh)
```
也可使用 Docker 官方提供的安装脚本(海外):
```bash
curl -fsSL https://get.docker.com | bash -s docker
```
对于 Docker 镜像加速,请在网络上自行搜索或自行搭建,也可使用 1Panel 安装服务器管理的同时安装 Docker 和镜像加速。
例如 1Panel 提供了 `docker.1panel.top` 镜像加速源,使用方法是在 Docker 全局设置或在 `docker-compose.yml` 的 image 前添加镜像域名,例如 `docker.1panel.top/innei/mx-server:latest`
如果您成功安装了 Docker 和 Docker-Compose,可以通过以下命令查看版本:
```bash
docker -v
docker-compose -v
```
## 拉取编排文件 [#拉取编排文件-step]
自 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
# 拉取 docker-compose.yml 文件(Gh-Proxy 全球)
wget "https://gh-proxy.org/https://github.com/mx-space/core/blob/master/docker-compose.yml"
```
## 配置环境变量 [#配置环境变量-step]
我们需要正确配置环境变量,打开获取到的`docker-compose.yml`文件,找到 Core 的配置。
可以看到`environment`字段(下方示例代码高亮部分)
```yaml
app:
container_name: mx-server
image: innei/mx-server:latest
// [!code word:environment]
environment:
- TZ=Asia/Shanghai
- NODE_ENV=production
- DB_HOST=mongo
- REDIS_HOST=redis
- ALLOWED_ORIGINS=localhost
- JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING
volumes:
- ./data/mx-space:/root/.mx-space
```
### 配置生成 [#配置生成]
在下方的组件中填入配置,点击复制后粘贴到 `docker-compose.yml` 的 `environment` 字段中,覆盖`JWT_SECRET` 和 `ALLOWED_ORIGINS` 的值,如果需要开启加密功能,请添加并将 `ENCRYPT_ENABLE` 的值改为 `true`,并填入 `ENCRYPT_KEY`。
### 变量介绍 [#变量介绍]
### 启动服务 [#启动服务]
```bash
docker compose up -d
```
启动后,请按以下清单确认服务正常:
* [ ] `docker compose ps` 显示所有服务状态为 healthy
* [ ] `curl http://localhost:2333/api/v2/ping` 返回 `pong`
* [ ] 浏览器能打开后台初始化页面 `http://你的域名/proxy/qaqdmin`
## 下一步 [#下一步]
将域名指向你的服务,并配置 HTTPS
部署前端主题完成整套系统
# 使用外部数据库 (/docs/deploy/external-services)
如果你需要使用来自远端或非容器内的 Redis / PostgreSQL 服务,可以通过环境变量或启动参数传入配置。
## 外部 Redis [#外部-redis]
支持传入的参数:
| 参数 | 说明 |
| ---------------- | ----------------- |
| `redis_host` | Redis 服务地址,域名或 IP |
| `redis_port` | Redis 服务端口 |
| `redis_password` | Redis 服务密码 |
| `disable_cache` | 是否禁用缓存,默认不启用 |
### Docker 部署 [#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 [#外部-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-部署-1]
在 `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` 重启服务。
### 源码部署 [#源码部署-1]
修改 `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
```
# 选择部署方式 (/docs/deploy)
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) — 完成整套系统
# 反向代理 (/docs/deploy/reverse-proxy)
## 为什么需要反向代理 [#为什么需要反向代理]
Mix Space 默认运行在本地端口(后端 `2333`,前端 `2323`),反向代理可以将域名请求转发到对应端口,并提供 HTTPS、WebSocket 支持。
## 图形化面板 [#图形化面板]
现代服务器面板(如 1Panel、宝塔面板)自带的反向代理已足以满足 Mix Space 的需求(包括 WebSocket),非高级用户建议使用图形化界面操作。
### 宝塔面板 [#宝塔面板]
进入 `网站`,在 `反向代理` 栏目下点击 `添加反代`。
* `域名` 填入你将要使用的域名
* `目标` 填写 `URL 地址` + `http://127.0.0.1:2333`
### 1Panel [#1panel]
进入 `网站 > 网站`,创建一个新网站,选择 `反向代理`。
* `主域名` 填入你将要使用的域名,并勾选 `监听 IPV6`
* 代理类型选择 `http`,地址填入 `127.0.0.1:2333`
## Cloudflare Tunnel [#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 手写配置 [#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`
# 源码部署 (/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 [#构建--bundle]
```bash
pnpm build
pnpm bundle
```
### 配置 ecosystem.config.js [#配置-ecosystemconfigjs]
在 `./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)。
# HTTPS / SSL 证书 (/docs/deploy/ssl)
Mix Space 的后台管理、OAuth 登录等功能要求使用 HTTPS。现代浏览器也会标记 HTTP 站点为不安全,影响访问体验。本页介绍几种常见的 SSL 证书获取和配置方式。
## 获取证书 [#获取证书]
### 自动证书(Let's Encrypt + Certbot) [#自动证书lets-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-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-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://` 链接。
# 5 分钟快速体验 (/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 摘要、翻译等功能
# 准备工作 (/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 分钟快速体验](/docs/getting-started/quick-start),在本地先跑起来看看。
# 常见错误与解决 (/docs/reference/common-issues)
## 无法启动服务 [#无法启动服务]
### `Error: JWT_SECRET is required` [#error-jwt_secret-is-required]
* **原因**:JWT 签名密钥未设置,这是启动服务的必填项。
* **解决**:在环境变量中添加 `JWT_SECRET`,设置一个随机字符串即可。
### `Error: SNOWFLAKE_WORKER_ID is required` [#error-snowflake_worker_id-is-required]
* **原因**:Snowflake 工作节点 ID 未设置。
* **解决**:在环境变量中添加 `SNOWFLAKE_WORKER_ID=1`(单实例部署填 1 即可)。
### `Connection refused to postgres:5432` [#connection-refused-to-postgres5432]
* **原因**:PostgreSQL 服务未启动,或连接配置错误。
* **解决**:
1. 确认 PostgreSQL 容器或服务已正常运行;
2. 检查 `PG_HOST`、`PG_PORT`、`PG_USER`、`PG_PASSWORD` 是否正确;
3. Docker 部署时,注意容器之间的网络是否互通。
## 无法访问后台 [#无法访问后台]
### 502 Bad Gateway [#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. 若备份文件损坏,尝试使用更早的备份。
# 参考手册 (/docs/reference)
不需要通读,遇到问题时来查。
所有环境变量的完整列表和说明
按症状分类的常见问题与解决方案
在 GitHub 上查看 API Client 文档
# 从 WordPress 迁移 (/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-内容]
在 WordPress 后台,进入「工具 → 导出」,选择「所有内容」,下载得到一个 XML 文件(WXR 格式)。
如果你使用的是 WordPress.com,可以在「工具 → 导出」中导出站点内容。
### 转换为 Markdown [#转换为-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-创建分类]
登录 Mix Space 后台,进入「分类」页面,提前创建好你在 WordPress 中使用的分类。确保分类名称一致,导入时系统才能正确匹配。
如果导入时找不到对应分类,系统会自动创建新分类。
### 导入 Markdown 文件 [#导入-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-过渡建议]
迁移完成后,建议进行以下 SEO 相关操作:
| 操作 | 说明 |
| ----------------- | ---------------------------------- |
| **301 重定向** | 将旧 WordPress 链接重定向到新的 Mix Space 链接 |
| **更新 Sitemap** | Mix Space 会自动生成新的 Sitemap |
| **提交搜索引擎** | 在百度/Bing 站长工具中重新提交站点地图 |
| **保留 robots.txt** | 确保新的 robots.txt 配置正确 |
### URL 映射规则 [#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)
# 迁移概览 (/docs/migrate)
数据库从 MongoDB 迁移到 PostgreSQL 的完整指南
将 WordPress 内容导出并导入到 Mix Space
迁移前务必备份。数据无价。
# v11 升级到 v12 (/docs/migrate/v11-to-v12)
v12 是一次**重大版本升级**,底层数据库从 MongoDB 更换为 PostgreSQL。虽然你的文章、评论、配置等数据都会保留,但升级过程中需要执行一次数据迁移,且需要短暂的停站维护。
**如果你当前版本低于 v11,请先升级到 v11,再执行本指南。**
## 升级前必读(3 分钟) [#升级前必读3-分钟]
### 这次升级会变什么? [#这次升级会变什么]
* **数据库**:MongoDB → PostgreSQL(性能更好,数据关系更安全)
* **备份方式**:以后用 `pg_dump` 代替 `mongodump`
* **环境变量**:旧的 `DB_HOST`、`MONGO_CONNECTION` 等变量失效
### 什么不会变? [#什么不会变]
* 前端页面、API 接口和之前完全一致
* 你的文章、评论、图片、配置全部保留
* 登录方式、密码、API Key 不受影响
### 我需要停站多久? [#我需要停站多久]
| 数据规模 | 预估时间 |
| ------------------------ | -------- |
| 文章 \< 100 篇,评论 \< 1000 条 | 5–10 分钟 |
| 文章 \< 1000 篇,评论 \< 1 万条 | 10–30 分钟 |
| 大型站点 | 30–60 分钟 |
***
## 升级 Checklist [#升级-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 部署的
适合进阶用户,手动编译部署的
***
## 数据迁移工具:`@mx-space/mongo-pg-cli` [#数据迁移工具mx-spacemongo-pg-cli]
无论 Docker 部署还是源码部署,**核心步骤是同一个 CLI**:
```bash
npx @mx-space/mongo-pg-cli@latest --mode dry-run
npx @mx-space/mongo-pg-cli@latest --mode apply
```
它做三件事:
1. 读取 v11 的 MongoDB
2. 在目标 PostgreSQL 上跑 v12 的 schema migration
3. 分配 Snowflake ID,把每个 collection 的数据写进对应 PG 表
**两种模式**:
* `dry-run`(默认):只读,不写入。先跑这个看报告
* `apply`:写入。可重复执行,不会重复导入
**环境变量**(最少 2 个):
| 变量 | 说明 |
| --------------------- | -------------------------------------------------------------- |
| `MONGO_URI` | v11 MongoDB 连接串,如 `mongodb://127.0.0.1:27017/mx-space` |
| `PG_URL` | v12 PostgreSQL 连接串,如 `postgres://mx:mx@127.0.0.1:5432/mx_core` |
| `SNOWFLAKE_WORKER_ID` | 迁移产生的行的 worker id,建议留 `900–999` 给迁移用,默认 `900` |
完整参数与故障排查见 CLI 自身的 [README](https://www.npmjs.com/package/@mx-space/mongo-pg-cli)。
需要 **Node.js 22+** 来跑 `npx`。如果服务器没有 Node,下面的 Docker 流程提供了用镜像内置 CLI 的备选方案。
***
## Docker 部署升级 [#docker-部署升级]
### 停止应用,保留 MongoDB 容器 [#1-停止应用保留-mongodb-容器]
**关键**:只停 `app` 服务,**不要** `docker compose down`。MongoDB 容器需要继续运行,迁移脚本会从中读取数据。
```bash
cd ~/mx-space/core
# 只停业务进程,让 mongo 继续跑
docker compose stop app
```
确认 MongoDB 仍在运行并对宿主机暴露 27017 端口:
```bash
docker ps | grep mongo
docker port $(docker ps -q -f name=mongo) | grep 27017
# 期望看到类似 27017/tcp -> 0.0.0.0:27017
# 没暴露则在旧 compose 里 ports: ["27017:27017"],重启 mongo 容器
```
### 更新配置文件 [#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`。也确认 PostgreSQL 端口 5432 已映射到宿主机:
```bash
docker port postgres | grep 5432
# 期望看到 5432/tcp -> 0.0.0.0:5432
```
### 执行数据迁移 [#4-执行数据迁移]
这是最关键的一步。执行前请确保没有用户在发文章或评论。
#### 方式 A(推荐):宿主机直接 `npx` [#方式-a推荐宿主机直接-npx]
要求服务器装了 Node.js 22+。`npx` 会自动下载 CLI,连接 mongo 与 pg 两个本地端口:
```bash
MONGO_URI="mongodb://127.0.0.1:27017/mx-space" \
PG_URL="postgres://mx:mx@127.0.0.1:5432/mx_core" \
npx @mx-space/mongo-pg-cli@latest --mode dry-run
```
确认报告无致命错误后,再 apply:
```bash
MONGO_URI="mongodb://127.0.0.1:27017/mx-space" \
PG_URL="postgres://mx:mx@127.0.0.1:5432/mx_core" \
npx @mx-space/mongo-pg-cli@latest --mode apply
```
如果你的 mongo 数据库名不是 `mx-space`、PG 凭证不是 `mx:mx`,对应替换。
#### 方式 B:服务器没装 Node.js — 用临时 Node 容器跑 [#方式-b服务器没装-nodejs--用临时-node-容器跑]
跑一个一次性的 Node 容器代替 host node。容器需同时访问 mongo 和 postgres,最简单是 `--network host`(Linux 服务器适用;macOS/Windows 的 Docker Desktop 不支持,请改用方式 A):
```bash
docker run --rm --network host \
-e MONGO_URI="mongodb://127.0.0.1:27017/mx-space" \
-e PG_URL="postgres://mx:mx@127.0.0.1:5432/mx_core" \
node:22-alpine \
npx -y @mx-space/mongo-pg-cli@latest --mode apply
```
如果 `--network host` 不可用,可改为 `--network ` 并先把旧 mongo 容器接入该网络(`docker network connect mx-space_mx-space mongo`),再用容器名 `mongo:27017` 与 `postgres:5432` 连接。
#### 预期输出 [#预期输出]
* `Rows allocated: XXXX`,数字与你的文章/评论数量接近
* `Missing refs: 0`(少量孤儿数据可接受)
* 最后出现 `✅ Migration finished without missing references.`
#### 如果报错怎么办? [#如果报错怎么办]
| 错误提示 | 原因 | 解决 |
| ------------------------------- | ------------------- | ------------------------------------------ |
| `MongoServerSelectionError` | mongo 端口未暴露 / 网络未联通 | 检查 mongo 容器是否映射 27017,或确认 `--network` 设置正确 |
| `Connection refused` (postgres) | PG 还没启动好 | 等 30 秒重试 |
| `Missing refs > 0` | 有孤儿数据 | 通常可忽略,截图记录后继续 |
| 其他错误 | 未知问题 | **不要继续**,保留日志,回滚到 v11(见下方回滚章节) |
### 启动 v12 [#5-启动-v12]
```bash
docker compose up -d
```
### 验证(逐项检查) [#6-验证逐项检查]
* [ ] 打开首页,文章列表正常显示
* [ ] 打开一篇文章,内容和评论都在
* [ ] 登录后台(`你的域名/proxy/qaqdmin`),能正常登录
* [ ] 后台「其他 → 备份」页面能正常打开
* [ ] 发一篇测试文章,能正常发布和显示
* [ ] 删除测试文章,正常删除
**全部通过 = 升级成功。**
***
## 源码 / PM2 部署升级 [#源码--pm2-部署升级]
### 停止服务 [#1-停止服务]
```bash
cd ~/mx-space/core/apps/core
pm2 stop ecosystem.config.js
```
### 拉取 v12 代码 [#2-拉取-v12-代码]
```bash
cd ~/mx-space/core
git fetch origin
git checkout v12.x.x # 替换为实际 tag,或 master 上的最新 v12
pnpm i
```
### 安装 PostgreSQL [#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-执行迁移]
先试运行(只读 MongoDB,不写 PostgreSQL):
```bash
SNOWFLAKE_WORKER_ID=1 \
MONGO_URI="mongodb://localhost:27017/mx-space" \
PG_URL="postgresql://mx:mx@localhost:5432/mx_core" \
npx @mx-space/mongo-pg-cli@latest --mode dry-run
```
确认报告无致命错误(`Rows allocated` 接近真实条数、`Missing refs` 数量可接受)后,正式迁移:
```bash
SNOWFLAKE_WORKER_ID=1 \
MONGO_URI="mongodb://localhost:27017/mx-space" \
PG_URL="postgresql://mx:mx@localhost:5432/mx_core" \
npx @mx-space/mongo-pg-cli@latest --mode apply
```
`apply` 模式可重复执行:被 `Ctrl+C` 打断后再跑不会重复导入。
### 构建并启动 [#6-构建并启动]
```bash
pnpm build
pnpm bundle
cd apps/core
pm2 start ecosystem.config.js
```
### 验证 [#7-验证]
与 Docker 验证清单相同(见上方第 6 步)。
***
## 第三步:清理旧数据库(可选) [#第三步清理旧数据库可选]
建议 v12 稳定运行 **48 小时** 后再执行清理。保留旧数据是回滚的最后保障。
### Docker 用户 [#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:迁移命令就报错了 [#场景-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 启动了,但发现数据不对或功能异常 [#场景-2v12-启动了但发现数据不对或功能异常]
立即切回 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 写了新数据,又想回滚 [#场景-3已经在-v12-写了新数据又想回滚]
这种情况比较麻烦,因为新数据在 PostgreSQL 里,回滚到 v11(MongoDB)会丢失这部分。建议:
1. 优先在 v12 上排查修复问题(推荐)
2. 如需帮助,带上错误日志发 [GitHub Issue](https://github.com/mx-space/core/issues)
***
## 常见问题 [#常见问题]
### 迁移会删除我的 MongoDB 数据吗? [#迁移会删除我的-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)
# 社区分享 (/docs/themes/community)
你可以参考他们的部署方式,但我们不保证它们的可用性。如果你也有教程想要与大家分享的话,欢迎您向文档提交 [Pull Request](https://github.com/mx-space/docs/pulls) 以分享您的部署方式。
前端部署方式拓展博文教程 | By Mikuの鬆
前端部署方式拓展博文教程 | By wuhang2003
{" "}
Yohaku/Shiroi 前端部署博文教程 | By 极夜System| 平台:Selfhost
# 主题总览 (/docs/themes)
# Kami 主题 (/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 [#配置-env]
1. 复制 .env.example 为 .env
2. 编辑 .env 文件,它看起来应该是这个样子的
```yaml
# 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 主题 (/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
```
# AI 功能 (/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]
### 进入设置页面 [#进入设置页面]
登录后台,前往「设定 → AI 设定」。
### 添加 Provider [#添加-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 摘要可以为你的文章自动生成简短的内容概要,支持多语言输出。
### 开启摘要 [#开启摘要]
在「设定 → 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-精读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-翻译]
AI 翻译可以将你的文章完整翻译为多语言版本,保持 Markdown 格式、代码块、链接等技术元素不变,同时保持翻译一致性。
### 开启翻译 [#开启翻译]
在「设定 → AI 设定」中:
1. 打开「可调用 AI 翻译」开关
2. 设置「AI 翻译目标语言列表」(如 `en`、`ja`、`ko`)
3. 可选:打开「开启 AI 翻译自动生成」(文章发布后自动翻译)
### 翻译特性 [#翻译特性]
* **双策略支持**:Markdown 文章和 Lexical 富文本文章分别使用对应的翻译策略,确保格式完整保留
* **翻译词表**:系统自动维护分类名称、话题名称、心情、天气等短文本的翻译一致性
* **多语言批量翻译**:可以一次为多篇文章生成多语言翻译
* **全量翻译**:支持一键为所有已有文章生成翻译
### 手动翻译操作 [#手动翻译操作]
进入后台「AI → 翻译」页面:
* 选择文章,点击「翻译」
* 选择目标语言后开始生成
* 生成完成后可查看、编辑、删除翻译
### 翻译词表 [#翻译词表]
进入「AI → 翻译词表」页面,可以查看和管理系统自动维护的翻译词表。词表用于确保分类、话题、心情、天气等短文本在不同文章间翻译一致。
支持的管理操作:
* 按类型(分类名、话题名、心情、天气)筛选查看
* 手动编辑翻译结果
* 批量重新生成
## 写作助手 [#写作助手]
写作助手在编辑器中为你提供 AI 辅助。
### 标题和 Slug 生成 [#标题和-slug-生成]
在编辑器中撰写完内容后,可以使用 AI 自动生成:
* **标题**:根据文章内容生成一个合适的标题
* **Slug**:生成 SEO 友好的英文 URL 路径
确保在 AI 设定中配置了写作助手模型(Writer Model),或在编辑器的 AI 面板中选择了可用的 Provider。
### Slug 批量回填 [#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 Agent 允许你在编辑器中直接与 AI 对话,辅助写作和内容修改。
### 使用方式 [#使用方式]
在文章编辑器中,打开右侧的 AI Agent 面板:
1. 选择一个已配置的 Provider 和模型
2. 在对话框中输入指令,如「帮我润色这段文字」「把这段改成更口语化的风格」
3. AI 的回复可以应用到编辑器中
AI Agent 对话历史会自动保存,你可以在同一篇文章中随时继续之前的对话。
## 任务队列 [#任务队列]
所有 AI 后台任务通过统一的任务队列管理,你可以在「AI → 任务」页面查看和管理。
### 任务类型 [#任务类型]
| 任务类型 | 说明 |
| ------- | -------------- |
| 摘要生成 | 为单篇文章生成摘要 |
| 翻译生成 | 为单篇文章生成翻译 |
| 批量翻译 | 为多篇文章批量生成翻译 |
| 全量翻译 | 为所有文章生成翻译 |
| 精读生成 | 为单篇文章生成精读 |
| 精读翻译 | 翻译已生成的精读内容 |
| Slug 回填 | 为历史日记批量生成 slug |
### 任务状态 [#任务状态]
| 状态 | 说明 |
| -------------- | ------- |
| Pending | 等待执行 |
| Running | 正在执行 |
| Completed | 执行完成 |
| Partial Failed | 部分子任务失败 |
| Failed | 执行失败 |
| Cancelled | 已取消 |
### 任务管理 [#任务管理]
在任务页面中,你可以:
* 按状态和类型筛选任务
* 查看任务详情(进度、日志、耗时)
* 重试失败的任务
* 取消正在运行的任务
* 批量清理历史任务
批量翻译任务会自动分组,你可以在任务列表中展开查看每个子任务的状态。
# 站点统计与分析 (/docs/use/analytics)
Mix Space 内置了站点统计功能,你可以在后台查看访问量、独立访客、流量来源、热门路径等数据,无需集成第三方统计服务。
## 统计概览 [#统计概览]
登录后台,首页(仪表盘)即展示关键数据概览:
| 指标 | 说明 |
| -------- | ------------------ |
| **文章数** | 已发布的文章总数 |
| **日记数** | 已发布的日记总数 |
| **评论数** | 评论总数 |
| **友链数** | 已通过的友链总数 |
| **在线人数** | 当前 WebSocket 在线连接数 |
| **总阅读量** | 所有内容的阅读计数 |
| **总点赞数** | 所有内容的点赞计数 |
## 详细分析 [#详细分析]
进入后台「分析」页面,可以查看更详细的统计数据。
### 访问趋势 [#访问趋势]
| 视图 | 说明 |
| ------ | -------------------- |
| **今日** | 按小时展示今天的 IP 和 PV 数据 |
| **本周** | 按周几展示近 7 天的 IP 和 PV |
| **本月** | 按日期展示近 30 天的 IP 和 PV |
### 热门路径 [#热门路径]
展示访问量最高的页面路径列表,帮助你了解哪些内容最受欢迎。
### 流量来源 [#流量来源]
展示访客的来源渠道分布(搜索引擎、直接访问、外部链接等)。
### 设备分布 [#设备分布]
展示访客使用的设备类型和浏览器分布。
## 评论活动 [#评论活动]
分析页面还展示评论活动趋势图,可以看到评论数量的时间变化。
## 数据管理 [#数据管理]
在分析页面中,你可以:
* **按时间范围查询**:选择起止日期查看特定时间段的数据
* **查看今日/本周数据**:快速切换到常用时间范围
* **清除历史数据**:按时间范围清除分析数据
分析数据存储在 Redis 中,具有缓存机制。聚合数据缓存约 1 分钟,流量来源和设备分布数据缓存约 5 分钟。
# 备份与恢复 (/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]
自 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
```
请根据实际情况修改连接字符串中的用户名、密码、主机和数据库名。
# 评论管理 (/docs/use/comments)
Mix Space 提供了完整的评论系统,支持访客留言、登录读者评论、站长回复,以及多层嵌套讨论。你可以在后台对评论进行审核、置顶、标记垃圾等操作,也可以借助 AI 自动审核来减轻管理负担。
## 评论管理界面 [#评论管理界面]
登录后台,进入「评论」页面。页面分为三个标签:
| 标签 | 说明 |
| ------ | -------------- |
| **待审** | 未读状态的新评论,需要你审阅 |
| **已读** | 正常的已读评论 |
| **垃圾** | 被标记为垃圾的评论 |
### 常用操作 [#常用操作]
| 操作 | 说明 |
| ------------- | ----------------------- |
| **标记已读 / 未读** | 切换评论的阅读状态 |
| **标记垃圾** | 将评论标记为垃圾内容,前台不再展示 |
| **置顶** | 将评论固定在该页面的最顶部(同页面仅一条置顶) |
| **删除** | 软删除评论,内容替换为「该评论已删除」 |
| **批量操作** | 勾选多条评论后批量修改状态或批量删除 |
评论被标记为垃圾时,如果该评论附带图片,系统会自动删除这些图片文件(可在「评论图片上传」设置中关闭此行为)。
## 评论配置 [#评论配置]
进入后台「设定 → 评论设置」,可以配置以下选项:
### 基本设置 [#基本设置]
| 配置项 | 说明 |
| ------------ | ------------------------------- |
| **全站禁止评论** | 关闭全站评论功能,敏感时期专用 |
| **允许未登录评论** | 开启后访客可以以游客身份评论;关闭后仅已登录读者和站长可以评论 |
| **只展示已读评论** | 开启后,前台只展示已标记为已读的评论,未读和垃圾评论均不展示 |
| **禁止非中文评论** | 过滤非中文字符的评论内容 |
| **评论公开归属地** | 在评论旁显示评论者的 IP 归属地 |
| **自定义屏蔽关键词** | 添加需要过滤的关键词列表 |
| **自定义屏蔽 IP** | 添加需要屏蔽的 IP 地址列表 |
### 反垃圾评论 [#反垃圾评论]
打开「反垃圾评论」开关后,系统会自动检测并过滤垃圾评论。
### AI 评论审核 [#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 分钟)。
## 评论排序 [#评论排序]
前台评论支持三种排序方式:
| 排序 | 说明 |
| -------- | ------------------- |
| **置顶优先** | 置顶评论在最前,其余按时间倒序(默认) |
| **最新** | 按时间倒序 |
| **最早** | 按时间正序 |
## 悄悄话 [#悄悄话]
评论支持「悄悄话」模式,标记为悄悄话的评论仅站长可见,前台不展示给其他访客。
# 内容管理 (/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]
日记支持两种 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` 字段为未来的某个时间,内容将在指定时间自动发布。
在此之前,内容保持草稿状态,前台不可见。
# 定时任务 (/docs/use/cron-tasks)
Mix Space 内置了一组定时任务,用于自动清理过期数据、推送搜索引擎、维护系统健康。你可以在后台查看这些任务的执行状态,也可以手动触发。
## 管理入口 [#管理入口]
登录后台,进入「维护 → 定时任务」页面。
## 内置任务列表 [#内置任务列表]
| 任务 | 说明 | 默认执行频率 |
| -------------- | ------------------- | -------- |
| **清理访问记录** | 清理过期的访问分析记录 | 每月 1 日凌晨 |
| **清理 IP 访问记录** | 重置 IP 访问计数 | 每日凌晨 |
| **清理喜欢数** | 重置文章的点赞和阅读计数缓存 | 每日凌晨 |
| **清理临时文件** | 删除临时目录中的过期文件 | 每日凌晨 3 点 |
| **推送百度搜索** | 将新内容推送到百度搜索引擎 | 每日凌晨 1 点 |
| **推送 Bing 搜索** | 将新内容推送到 Bing 搜索引擎 | 每日凌晨 1 点 |
| **删除过期 JWT** | 清理数据库中过期的 JWT 令牌 | 每日凌晨 1 点 |
| **重建搜索索引** | 重建 Algolia 等搜索服务的索引 | 每日凌晨 4 点 |
| **清理评论图片上传** | 清理未被引用和过期的评论图片 | 每 15 分钟 |
搜索引擎推送任务(百度、Bing)需要先在「设定」中配置对应的 Token / API 密钥并开启推送,否则任务不会实际推送数据。
## 任务状态 [#任务状态]
| 状态 | 说明 |
| ---- | ------------- |
| 等待中 | 任务已创建,等待执行 |
| 执行中 | 任务正在运行 |
| 已完成 | 任务执行成功 |
| 部分失败 | 多步骤任务中有部分步骤失败 |
| 失败 | 任务执行失败 |
| 已取消 | 任务被手动取消 |
## 手动触发 [#手动触发]
在定时任务页面中,点击任务旁的「执行」按钮可以手动触发该任务。适用于:
* 首次配置搜索引擎推送后,立即推送已有内容
* 清理了大量垃圾评论后,手动清理评论图片
* 搜索索引异常时,手动重建
## 任务日志 [#任务日志]
每个任务执行后会保留日志记录,包含:
* 任务类型和执行时间
* 执行结果(成功/失败)
* 详细的执行输出
* 失败时的错误信息
对于失败的任务,可以点击「重试」按钮重新执行。
## 清理历史任务 [#清理历史任务]
在任务列表中,可以批量清理已完成的历史任务记录,保持列表整洁。
# 常见问题 (/docs/use/faq)
## 部署相关 [#部署相关]
### 忘记后台密码怎么办? [#忘记后台密码怎么办]
如果你配置了 OAuth 登录(GitHub / Google),可以先通过第三方账号登录后台,再在「设定 → 个人信息」中修改密码。
如果没有配置 OAuth,可以通过数据库直接修改密码字段来重置。
### 如何修改网站标题和描述? [#如何修改网站标题和描述]
登录后台,进入「设定 → SEO 优化」,修改网站标题和网站描述,保存后立即生效。
### 后台地址是什么? [#后台地址是什么]
默认后台地址为 `https://你的域名/proxy/qaqdmin`。如果开启了后台反代(「设定 → 后台附加设置」),也可以通过 API 地址直接访问。
### 启动报错 `JWT_SECRET is required` [#启动报错-jwt_secret-is-required]
JWT 密钥是必填项。在环境变量或 `docker-compose.yml` 中添加 `JWT_SECRET=你的随机字符串`(16-32 位)。
### 启动报错 `SNOWFLAKE_WORKER_ID is required` [#启动报错-snowflake_worker_id-is-required]
单实例部署填 `SNOWFLAKE_WORKER_ID=1` 即可。
## 内容相关 [#内容相关]
### 文章的 URL 规则是什么? [#文章的-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 格式是什么? [#上传的图片-url-格式是什么]
* 本地存储:`/api/v2/static/{type}/{filename}`
* S3 存储:`{自定义域名}/{前缀}/{filename}`
自定义命名规则可以在「设定 → 文件上传设定」中配置。
## 邮件与通知 [#邮件与通知]
### 评论通知邮件不发送? [#评论通知邮件不发送]
请检查:
1. 后台「设定 → 邮件通知设置」中是否开启了邮件提醒
2. SMTP 配置是否正确(主机、端口、用户名、密码)
3. 如果使用 Gmail,需要开启「应用专用密码」
4. 服务器防火墙是否放行了 SMTP 端口(465/587)
推荐使用 [Resend](https://resend.com) 等现代邮件 API 服务,配置更简单。
### 如何推送到 Telegram / 微信? [#如何推送到-telegram--微信]
通过 Webhook 功能实现。在后台「其他 → Webhook」中创建一个 Webhook,Payload URL 填写你的通知服务地址,勾选关注的事件即可。详见 [Webhook 与事件通知](/docs/use/webhook)。
## 数据库与迁移 [#数据库与迁移]
### 数据库可以迁移到另一台服务器吗? [#数据库可以迁移到另一台服务器吗]
可以。推荐步骤:
1. 在原服务器执行备份(后台备份或 `pg_dump`)
2. 将备份文件传输到新服务器
3. 在新服务器恢复数据并重启服务
跨服务器迁移时,保持环境变量和配置一致,尤其是 `JWT_SECRET` 和加密密钥。
### 如何从 MongoDB 迁移到 PostgreSQL? [#如何从-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 容器占用内存过高? [#docker-容器占用内存过高]
Mix Space 正常运行约需要 256-512MB 内存。如果内存占用异常,检查:
* 是否有大量 AI 任务在后台运行
* Redis 连接是否正常
* 日志文件是否过大
遇到文档中没有覆盖的问题?可以在 [GitHub Issues](https://github.com/mx-space/core/issues) 中搜索或提交新问题。
# 文件管理 (/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}` → 按类型和日期分目录存储
修改文件命名模板后,仅对新上传的文件生效。已上传的文件不会自动重命名。
# 友链管理 (/docs/use/friends)
友情链接(友链)是博客之间互相推荐的方式。Mix Space 支持完整的友链管理流程:添加、审核、健康检查、自动头像转内链。
## 管理友链 [#管理友链]
登录后台,进入「友链」页面。你可以:
| 操作 | 说明 |
| ---------- | ------------------ |
| **新增友链** | 点击右上角「+」,填写友链信息后保存 |
| **编辑友链** | 点击友链条目进入编辑 |
| **删除友链** | 删除不再需要的友链 |
| **审核友链申请** | 在「审核中」标签页查看并审批申请 |
### 友链状态 [#友链状态]
| 状态 | 说明 |
| --- | ----------- |
| 已通过 | 正常展示在友链列表中 |
| 审核中 | 等待站长审批的友链申请 |
| 已过期 | 友链已过期 |
| 已屏蔽 | 被手动屏蔽的友链 |
| 已拒绝 | 审核未通过的友链 |
### 友链类型 [#友链类型]
| 类型 | 说明 |
| ------------------ | ------- |
| **友链(Friend)** | 普通友情链接 |
| **收藏(Collection)** | 收藏的站点链接 |
## 友链申请 [#友链申请]
如果开启了友链申请功能,访客可以通过前端页面提交友链申请。
### 开启友链申请 [#开启友链申请]
进入后台「设定 → 友链设定」,打开「允许申请友链」开关。
### 申请流程 [#申请流程]
### 访客提交申请 [#访客提交申请]
访客在前端友链页面填写站点名称、URL、头像、描述和邮箱(可选),提交申请。
### 站长收到通知 [#站长收到通知]
系统会通过邮件(如已配置)通知站长有新的友链申请。
### 站长审批 [#站长审批]
在后台「友链」页面的「审核中」标签查看申请:
* 点击「通过」审批友链
* 点击「拒绝」可填写拒绝理由,系统会通过邮件发送给申请者
审核通过后,系统会自动通过邮件通知申请者(前提是申请者填写了邮箱且邮件服务已配置)。
## 友链配置项 [#友链配置项]
进入后台「设定 → 友链设定」:
| 配置项 | 说明 |
| ----------- | ---------------------------------- |
| **允许申请友链** | 开启后前端展示友链申请入口 |
| **允许子路径友链** | 允许申请子路径形式的友链(如 `example.com/blog`) |
| **友链头像转内链** | 审核通过后自动下载友链头像到本地,避免外部头像加载失败 |
### 头像转内链 [#头像转内链]
打开「友链头像转内链」后,当友链审核通过时,系统会自动下载该友链的头像文件并存储到本地。这样即使原始头像链接失效,你的友链页面仍然可以正常显示头像。
头像转内链仅支持常见图片格式(JPEG、PNG、WebP、GIF 等),其他格式的头像不会被转换。
## 友链健康检查 [#友链健康检查]
在后台友链页面,点击「健康检查」按钮,系统会批量检测所有已通过友链的可达性。不可达的友链会被标记,方便你及时清理失效链接。
## 头像批量迁移 [#头像批量迁移]
如果你在后期才开启头像转内链功能,已有友链的头像仍然是外部链接。在友链页面点击「迁移头像」按钮,可以批量将所有已通过友链的外部头像下载到本地。
# 使用指南 (/docs/use)
部署完成后,这篇指南帮助你日常使用 Mix Space。
## 内容管理 [#内容管理]
文章、日记、页面的发布与管理,分类、专题与草稿
后台编辑器、Obsidian 插件、Markdown 导入导出
评论审核、反垃圾、AI 审核、评论图片上传
友链添加与审核、申请规则、头像转内链
发布短内容、碎片化想法与一句话动态
管理和展示个人项目与作品集
图片、图标、文件的上传管理与自定义命名
## AI 功能 [#ai-功能]
摘要、精读、多语言翻译、写作助手、评论审核、AI Agent
## 扩展与集成 [#扩展与集成]
扩展 Mix Space 能力的云函数、自定义路由与数据接口
将内容事件推送到外部服务(Telegram、Slack 等)
邮件服务配置、读者订阅推送、Bark 通知
## 系统管理 [#系统管理]
访问量、流量来源、设备分布和热门路径
系统定时清理、搜索引擎推送、索引重建
手动备份、自动备份到 S3、数据回滚
Docker 与源码部署的更新方式、大版本升级指引
## 常见问题 [#常见问题]
部署、内容、存储、邮件、数据库等常见疑问
# 邮件与订阅 (/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` |
| **开启评论通知** | 收到新评论时推送 |
| **开启请求被限流时通知** | 可以在一定程度上预警被攻击 |
# 项目展示 (/docs/use/projects)
Mix Space 内置了项目展示功能,你可以在后台管理自己的项目信息,前端主题会将这些项目以卡片等形式展示出来。
## 管理项目 [#管理项目]
登录后台,进入「项目管理」页面。
### 添加项目 [#添加项目]
点击右上角「+」,填写项目信息:
| 字段 | 说明 |
| -------- | -------------------- |
| **名称** | 项目名称(必填,唯一) |
| **描述** | 项目简介(必填) |
| **详情** | 项目的详细介绍(支持 Markdown) |
| **预览地址** | 项目在线预览 URL |
| **文档地址** | 项目文档 URL |
| **项目地址** | 项目源码仓库 URL |
| **头像** | 项目图标或 Logo URL |
| **截图** | 项目截图 URL 列表 |
### 编辑和删除 [#编辑和删除]
在项目列表中可以编辑已有项目或删除不再需要项目。
所有 URL 字段都需要填写完整的 HTTP/HTTPS 地址。
## 前端展示 [#前端展示]
项目数据通过 API 提供给前端主题。不同主题的展示方式可能不同,常见的展示形式包括:
* 项目卡片网格
* 带截图的项目详情页
* 按时间排列的项目列表
具体展示效果取决于你使用的前端主题。
# 说说管理 (/docs/use/says)
「说说」是 Mix Space 中一种轻量级的内容类型,适合发布碎片化的想法、一句话感悟、状态更新等短内容。类似微博或 Twitter 的一条推文。
## 管理说说 [#管理说说]
登录后台,进入「说说」页面。
### 发布说说 [#发布说说]
1. 点击右上角「+」新建
2. 填写以下字段:
| 字段 | 说明 |
| ------ | ------------------- |
| **内容** | 说说正文(必填) |
| **来源** | 发布来源(如「网页」「iPhone」) |
| **作者** | 引用他人的话时填写原作者 |
3. 点击保存即可发布
### 编辑和删除 [#编辑和删除]
在说说列表中,点击条目可以编辑内容,点击删除按钮可以移除说说。
说说内容会实时推送到前端主题。如果你的主题支持说说模块,说说会以时间线的形式展示。
## 随机说说 API [#随机说说-api]
系统提供了一条随机说说的 API 接口,前端主题可以使用这个接口在页面中随机展示一条说说,增加页面的趣味性。
## 与其他功能的联动 [#与其他功能的联动]
* **订阅推送**:如果开启了读者订阅,新说说发布时可以通知订阅者
* **Webhook**:说说创建、更新、删除都会触发对应的 Webhook 事件
* **实时推送**:说说发布后通过 WebSocket 实时推送到在线用户
# 云函数与 Snippet (/docs/use/serverless)
Snippet 是 Mix Space 的扩展机制。每个 Snippet 是一段可配置的代码片段,可以为你的站点添加自定义数据接口、动态路由、前端脚本注入等能力。
## 功能总览 [#功能总览]
| 类型 | 说明 | 典型用途 |
| ---------------- | --------- | ------------- |
| **JSON / JSON5** | 结构化数据片段 | 配置数据、映射表 |
| **Text** | 纯文本片段 | 公告、自定义 HTML |
| **YAML** | YAML 数据片段 | 结构化配置 |
| **Function** | 可执行函数 | 云函数 API、自定义路由 |
Function 类型的 Snippet 就是你常听到的「云函数」。它是 Snippet 系统的一个子集,拥有最强大的扩展能力。
## 管理云函数 / Snippet [#管理云函数--snippet]
登录后台,进入「其他 → 云函数」页面。
### 导入社区云函数 [#导入社区云函数]
### 点击「下载拓展包」 [#点击下载拓展包]
在页面右上方点击「下载拓展包」按钮,弹出社区云函数列表。
### 选择并导入 [#选择并导入]
在弹窗中找到对应主题的云函数代码,点击「导入」。
### 确认启用 [#确认启用]
导入后在管理页面确认 Snippet 已启用。Function 类型的 Snippet 需要手动开启「启用」开关。
社区收录的云函数 Snippets 可以在 GitHub 查看:
### 手动创建 Snippet [#手动创建-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-类型云函数]
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 的访问方式 [#数据类型-snippet-的访问方式]
非 Function 类型的 Snippet 可以通过以下方式访问:
| 访问方式 | URL 格式 |
| ------ | ------------------------------------- |
| 按名称和分组 | `/api/v2/snippets/{reference}/{name}` |
| 按自定义路径 | `/s/{customPath}`(需要设置自定义路径) |
* **公开(Public)** Snippet 所有人可访问
* **私有(Private)** Snippet 仅管理员登录后可访问
## 前端主题集成 [#前端主题集成]
许多前端主题依赖 Snippet 提供数据。常见用法:
* Shiro 主题使用云函数提供哔哩哔哩追番、最近听歌等模块
* 自定义 CSS/JS 注入到前端页面
* 提供导航栏配置、社交链接等结构化数据
具体需要导入哪些 Snippet,请参考你使用的前端主题文档。
## 开发者文档 [#开发者文档]
如需编写自定义 Function 类型 Snippet,请参考完整的开发者文档:
# 版本更新 (/docs/use/update)
Mix Space 分为前端和后端两个部分,因此更新的时候二者也需要分开更新。
## 小版本更新(常规) [#小版本更新常规]
根据部署方式的不同,更新方式也有所不同。
### Docker 部署 [#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` 升级,请务必阅读专用升级指南。
## 前端更新 [#前端更新]
请根据自己所部署的主题跳转到对应的更新部分完成更新。
# Webhook 与事件通知 (/docs/use/webhook)
Webhook 可以将 Mix Space 中发生的事件(如发布文章、收到评论等)实时推送到你指定的外部服务。常见的用途包括:通知到 Telegram/微信、触发 CI/CD 构建、同步到第三方平台等。
## 创建 Webhook [#创建-webhook]
### 进入 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 的所有历史推送记录。
# 写作工作流 (/docs/use/writing)
Mix Space 提供了多种写作方式,无论你习惯在浏览器中编辑,还是偏爱本地 Markdown 编辑器,都能找到适合你的工作流。
## 后台编辑器 [#后台编辑器]
登录后台后,进入「文章」或「日记」页面,点击新建即可开始写作。
### 编辑器功能简介 [#编辑器功能简介]
* **Markdown 支持**:直接输入 Markdown 语法,实时预览渲染效果
* **Lexical 富文本**:提供可视化的富文本编辑体验,支持拖拽排版
* **定时发布**:设定未来的发布时间,到点自动上线
* **密码保护**:为单篇文章设置访问密码,适合私密内容
后台地址通常为 `你的域名/proxy/qaqdmin`,部署时可在配置中修改。
## Obsidian 插件 [#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]
在 Obsidian 中打开「设置 → 第三方插件」,关闭安全模式后点击「浏览」旁的「加载已解压的插件」,选择解压后的插件文件夹。
### 配置 API [#配置-api]
在插件设置中填入:
* **API Endpoint**:你的 Mix Space 地址,如 `https://example.com/api/v2`
* **Token**:在 Mix Space 后台「设定 → 安全 → API Token」中生成
### 发布内容 [#发布内容]
在 Obsidian 中打开一篇笔记,按 `Ctrl/Cmd + P` 打开命令面板,搜索「Mix Space」即可看到发布/更新命令。
## Markdown 导入导出 [#markdown-导入导出]
Mix Space 后台支持 Markdown 文件的批量导入与导出,方便你在不同平台之间迁移内容。
### 导入 Markdown [#导入-markdown]
登录后台,进入「文章」页面。
点击右上角「导入」按钮,选择本地 Markdown 文件。
系统会自动解析 Frontmatter(标题、标签、分类等),确认后完成导入。
### 导出 Markdown [#导出-markdown]
在后台文章列表中,选择需要导出的文章,点击「导出」即可下载包含完整 Frontmatter 的 Markdown 文件。
导入时如果文章已存在相同 slug,系统会提示是否覆盖,请谨慎操作。
## 写作建议 [#写作建议]
为了让你的内容更容易被检索和阅读,建议养成以下习惯:
* **使用标签**:为每篇文章添加 2–5 个标签,便于分类和关联推荐
* **设置分类**:合理划分文章分类,让读者快速定位感兴趣的主题
* **撰写摘要**:在 Frontmatter 或摘要栏中填写内容概要,有利于 SEO 和列表展示
* **规范 slug**:使用英文小写和连字符作为文章链接,避免中文 URL
# 配置 (/docs/themes/shiro/config)
# 配置项 [#配置项]
## 页脚信息 (`footer`) [#页脚信息-footer]
此部分定义页脚的部分信息,主要包括备案、建站年份和页脚导航三部分。
### 备案信息 (`otherInfo.icp`) [#备案信息-otherinfoicp]
**如何使用**: 根据示例,修改位于 `text` 的备案号以及备案号所指向的链接 `link`。
### 建站年份 (`otherInfo.date`) [#建站年份-otherinfodate]
**如何使用**: `{{now}}` 指向当前年份,其他略。
### 页脚导航 (`linkSections`) [#页脚导航-linksections]
分类包括 `name` 和 `links` 两个字段,对应分类名字及其下链接,其下链接又分为 `name`、`href`、`external` 三个字段,对应链接名字,指向链接和是否外链三个属性。
**如何使用**: 根据自己需要增删或修改特定链接及分类,需要注意如果指向外链的话需要加一行 `"external": true`。
## 站点信息 (`config.site`) [#站点信息-configsite]
此部分包含了网站的基础信息设置,例如 favicon(网站图标)的配置。
### Favicon [#favicon]
* **`favicon`**: 设置网站在浅色模式下使用的图标。
* **`faviconDark`**: 设置网站在深色模式下使用的图标。
## Hero 部分 (`config.hero`) [#hero-部分-confighero]
`hero` 部分定义了网站首页的主要欢迎信息或介绍部分,这是访问者首次进入网站时看到的部分。
### Title 模板 (`title.template`) [#title-模板-titletemplate]
包括多个元素(如 `h1`, `code`, `span`),每个元素都可以自定义文本内容和样式(通过 CSS 类)。
**如何使用**: 修改 `text` 和 `class` 字段来自定义标题的文本内容和样式。你可以通过添加或删除元素来调整标题的结构。
### 描述 (`description`) [#描述-description]
提供了对主页 `hero` 部分的简短描述。
**如何使用**: 直接修改 `description` 的值以更改介绍文本。
## 自定义脚本 (`config.custom`) [#自定义脚本-configcustom]
可以配置自定义的 CSS, Script。
### Scripts (`scripts`) [#scripts-scripts]
接受一个 [Script](https://nextjs.org/docs/app/api-reference/components/script#props) Props 参数数组。
### Styles (`styles`) [#styles-styles]
自定义 CSS。接受一个字符串数组。
### JavaScript tag (`js`) [#javascript-tag-js]
自定义 JS 脚本。接受一个字符串数组。
### CSS href link (`css`) [#css-href-link-css]
加载外部 CSS,接受一个 CSS 外部样式表链接数组。
## 模块 (`config.module`) [#模块-configmodule]
此部分配置了网站的一些特定功能模块,比如活动跟踪、捐赠支持、社交媒体链接等。
### 实时活动 (`activity`) 模块 [#实时活动-activity-模块]
* **`enable`**: 控制模块是否启用。
* **`endpoint`**: 指定活动更新的服务器端点。
**如何使用**: 若需开启活动跟踪功能,将 `enable` 设为 `true` 并设置 `endpoint` 为处理活动数据的服务器地址。
### 捐赠 (`donate`) 模块 [#捐赠-donate-模块]
* **`enable`**: 控制捐赠模块是否启用。
* **`link`**: 提供捐赠页面的链接。
* **`qrcode`**: 提供一或多个捐赠二维码图片的链接。
**如何使用**: 启用捐赠功能,并提供捐赠链接或捐赠二维码,以便支持者可以直接进行捐赠。
### 社交媒体 (`bilibili`) 模块 [#社交媒体-bilibili-模块]
* **`liveId`**: b 站直播间 ID
# 部署 (/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) 部分。~~
## 准备步骤 [#准备步骤]
### 设置主题配置 [#设置主题配置]
进入 Mix Space 后台,进入「配置与云函数」页面,点击右上角的新增按钮,在编辑页面中,填入以下设置:
* 名称:`shiro`
* 引用:`theme`
* 数据类型:`JSON`
* 数据:(点击下方的按钮复制)
请注意,这份配置你需要自行修改成符合你的需求的配置。直接使用下面的配置可能会导致你的博客无法按照你的预期运行。
下面的配置可能不全,更多配置项的信息请移步 [配置项](/docs/themes/shiro/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": {
"favicon": "/innei.svg",
"faviconDark": "/innei-dark.svg"
},
"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
}
}
}
}
```
点击按钮保存配置,随后继续进行下面的步骤。
### 配置环境变量 [#配置环境变量]
在下方的配置表格中,填入你的环境变量,然后点击复制按钮,将环境变量复制到剪贴板中。
## 通过 Vercel 部署 [#通过-vercel-部署]
### 克隆仓库 [#克隆仓库]
登陆 GitHub 账号,打开 [Innei/Shiro](https://github.com/Innei/Shiro),点击右上角的 Fork 按钮,将仓库克隆到你的账号下。
### 自定义 Favicon [#自定义-favicon]
修改你 Fork 的 Shiro 仓库中的 public 文件夹内容以使用你自己的 Favicon 。
### 打开 Vercel 创建项目 [#打开-vercel-创建项目]
登陆 Vercel 账号,点击右上角的 New Project 按钮,选择 Import Git Repository,选择你刚刚 Fork 的仓库,点击 Import 按钮,即可进入到项目配置页面。
### 键入环境变量 & 开始部署 [#键入环境变量--开始部署]
在刚刚进入的 Vercel 项目配置页面中,点击 Environment Variables,然后键盘上的 Ctrl + V 将环境变量粘贴到输入框中,然后点击 Deploy 按钮,等待部署完成。
有关配置自定义域名的教程,请参考 [Vercel 文档](https://vercel.com/docs/custom-domains)。
## 通过预构建运行 & Docker Compose [#通过预构建运行--docker-compose]
参见 [README 相关部分](https://github.com/Innei/Shiro/blob/main/README.md#whale-运行) 完成对应操作,随后配置[反向代理](/docs/deploy/reverse-proxy)。
## 完成! [#完成]
至此,你已完成了 Shiro 主题的部署,你可以访问你的博客了。
## 更新主题 [#更新主题]
使用 Vercel 托管的话,只需要在自己 Fork 的项目上 Sync Fork 即可(如图)。如果自己有魔改某些内容的话不要点击 Discard Changes,会把自己的魔改搞没了。
```bash
docker compose pull && docker compose up -d
```
# 额外功能 (/docs/themes/shiro/extra)
# 额外功能 [#额外功能]
## 扩展的 Markdown 语法 [#扩展的-markdown-语法]
参考 [https://shiro.innei.in/#/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/](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` [#processreporter-mac]
打开软件后,你会发现你的系统菜单栏中多了一个图标,点击图标,然后点击「设置」,在弹出的窗口中填入你的信息:
* Endpoint:`{你的API地址}/fn/ps/update` (请将 `{你的API地址}` 替换为你的 API 地址,如:`https://api.example.com/api/v2`)
* API Key:填入你刚刚在云函数中设置的密钥
如果你希望软件在开机时自动启动,可以勾选「Launch at login」选项。
接着关闭窗口,再次点击菜单栏中的图标,点击「Enable」即可。如果一切正常,刷新一下你的博客就可以在博客顶部看到你的动态了。
### ProcessReporter `Windows` [#processreporter-windows]
Windows 版本的使用问题,请前往 [TNXG/ProcessReporterWinpy](https://github.com/TNXG/ProcessReporterWinpy#readme) 查看。
#### 使用 GUI 版本 [#使用-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` [#processreporter-linux]
在仓库的 [Releases](https://github.com/ttimochan/processforlinux/releases) 页面下载对应的二进制包,解压运行即可,具体请参照项目的 README 进行配置运行。
安装完成后,新建 `.env.process` 文件,填入你的信息:
```yaml
# 你的 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)
## 个人状态展示 [#个人状态展示]
设置当前的状态。
### 配置云函数 [#配置云函数-1]
进入后台,点击左侧菜单栏的「其他 -> 配置与云函数」,然后点击新建按钮,在选项卡中填入以下信息:
* 名称:`status`
* 引用:`shiro`
* 数据类型:`Function`
* 请求方式:`ALL`
这个地方还需要设置一个密钥,在 Secret 中填入 `key`,在 Value 中填入你自己的密钥。
这个密钥将用于验证你的软件是否有权限更新当前状态,所以请务必设置一个复杂的密钥。
**密钥在后面的步骤中还需要用到,所以请务必记住。**
上方没有提到的选项都不需要填写,然后在右侧的代码编辑器中填入下面链接中的代码:
点击保存按钮,云函数就配置完成了。
请关注此代码的更新,它可能会随时变化,你需要及时更新它们
### 设置状态 [#设置状态]
在主页登录之后,你可以点击此头像的右下方设置状态。
# 白 / Shiro (/docs/themes/shiro)
## 核心特性 [#核心特性]
* **极致性能**:在 LightHouse 测试中表现卓越,Performance 和 Best Practice 均超过 90%
* **现代设计**:简洁而不简单的用户界面,提供流畅优雅的用户体验
* **细节至上**:采用符合物理学的 Spring 弹性动画,每一帧都如自然般舒适
* **实时通知**:通过 WebSocket 连接,访客可实时接收最新文章推送
* **活动状态**:结合 [ProcessReporter](https://github.com/Innei/ProcessReporter),在主页展示实时活动状态
* **扩展语法**:支持丰富的 Markdown 扩展语法,满足多样化写作需求
* **精美首页**:Hero 区域、活动流、时间线展示、风向标导航
* **思考系统**:独立的思考(Recently)页面,支持评论、点赞、RSS Feed
* **时间线**:按年份、类型筛选的文章/手记时间线
* **多语言**:基于 next-intl 的国际化支持
## 预览 [#预览]
## 性能测试 [#性能测试]
在 M2 MacBook Air 环境下对重负载页面的性能测试结果:
# 闭源功能 (/docs/themes/shiro/pro)
# 闭源功能 [#闭源功能]
本文档介绍 Shiro 主题闭源版本的特有功能。
## 配置项 [#配置项]
### 一言 (`hitokoto`) [#一言-hitokoto]
提供自定义首页一言的功能。
接受一个对象,包含 `random` 和 `custom` 两个可选字段。
当存在 `random` 字段时,将会随机获取一言。优先级高于 `custom` 字段。
当存在 `custom` 字段时,将会使用自定义的一言。
如果两个字段都不存在,将会使用默认的一言。
```ts
interface Hitokoto {
random?: boolean
custom?: string
}
```
### OpenPanel 模块 [#openpanel-模块]
[OpenPanel](https://openpanel.dev) 是一个交互式面板工具。
* **`enable`**: 控制 OpenPanel 功能是否启用。
* **`id`**: OpenPanel 的 ID。
* **`url`**: OpenPanel 的访问地址。
**如何使用**: 如果你使用 OpenPanel 提供交互式面板或其他功能,通过这些配置连接并显示面板。
### 签名动画 (`signature`) 模块 [#签名动画-signature-模块]
* **`svg`**: 签名的 svg 代码。
**如何使用**: 请参考[签名动画](#签名动画)部分。
### 文章列表设定 (`posts`) [#文章列表设定-posts]
* **`mode`**: 文章列表的预览模式。可选的值:`"loose"`(默认值) `"compact"`
两个模式,紧凑模式和松散模式。
## 功能特性 [#功能特性]
### AI 参与声明 [#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": ""
}
}
}
```
# 配置 (/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,无需更改配置名称。
## 第三方服务集成 [#第三方服务集成]
LinkCard 解析、Open Graph 抓取,以及 TMDB、GitHub、Bangumi、NeoDB、arXiv、LeetCode、网易云音乐、QQ 音乐等外部内容的富化,全部由 Mix Space Core 后端的 enrichment 服务接管。
主题侧**不再需要**配置 `GH_TOKEN`、`TMDB_API_KEY` 等环境变量。所有第三方凭据统一在后台「设置 → 第三方服务集成」中维护。
进入后台「设置 → 第三方服务集成」,按主题中实际使用到的链接卡片类型,启用并填入对应凭据:
| Provider | 字段 | 说明 |
| ---------- | --------- | ----------------------------------------------------- |
| GitHub | `token` | 解析仓库、Issue、PR、Discussion、Commit 卡片,规避匿名访问的 rate limit |
| TMDB | `apiKey` | 解析 TMDB 影视链接 |
| Bangumi | `enabled` | 解析 Bangumi 番剧 / 书籍链接 |
| NeoDB | `enabled` | 解析 NeoDB 条目链接 |
| arXiv | `enabled` | 解析 arXiv 论文链接 |
| LeetCode | `enabled` | 解析 LeetCode 题目链接 |
| 网易云音乐 | `enabled` | 解析网易云音乐歌曲 / 歌单链接 |
| QQ 音乐 | `enabled` | 解析 QQ 音乐歌曲 / 歌单链接 |
| Open Graph | `enabled` | 抓取通用网页的 OG 元数据 |
后端完成富化并缓存后,主题端直接读取已结构化的数据进行渲染。
## 页脚信息 (`footer`) [#页脚信息-footer]
此部分定义页脚的部分信息,主要包括备案、建站年份和页脚导航三部分。
### 备案信息 (`otherInfo.icp`) [#备案信息-otherinfoicp]
**如何使用**: 根据示例,修改位于 `text` 的备案号以及备案号所指向的链接 `link`。
### 建站年份 (`otherInfo.date`) [#建站年份-otherinfodate]
**如何使用**: `{{now}}` 指向当前年份,其他略。
### 页脚导航 (`linkSections`) [#页脚导航-linksections]
分类包括 `name` 和 `links` 两个字段,对应分类名字及其下链接,其下链接又分为 `name`、`href`、`external` 三个字段,对应链接名字,指向链接和是否外链三个属性。
**如何使用**: 根据自己需要增删或修改特定链接及分类,需要注意如果指向外链的话需要加一行 `"external": true`。
## 站点信息 (`config.site`) [#站点信息-configsite]
此部分包含了网站的基础信息设置,例如 favicon(网站图标)的配置。
### Favicon [#favicon]
* **`favicon`**: 设置网站在浅色模式下使用的图标。
* **`faviconDark`**: 设置网站在深色模式下使用的图标。
## Hero 部分 (`config.hero`) [#hero-部分-confighero]
`hero` 部分定义了网站首页的主要欢迎信息或介绍部分,这是访问者首次进入网站时看到的部分。
### Title 模板 (`title.template`) [#title-模板-titletemplate]
包括多个元素(如 `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`) [#描述-description]
提供了对主页 `hero` 部分的简短描述。
**如何使用**: 直接修改 `description` 的值以更改介绍文本。
### 一言 (`hitokoto`) [#一言-hitokoto]
提供自定义首页一言的功能。
接受一个对象,包含 `random` 和 `custom` 两个可选字段。
* 当存在 `random` 字段且值为 `true` 时,将会随机获取一言,优先级高于 `custom` 字段。
* 当存在 `custom` 字段时,将会使用自定义的一言。
* 如果两个字段都不存在,将会使用默认的一言。
```ts
interface Hitokoto {
random?: boolean
custom?: string
}
```
## 自定义脚本 (`config.custom`) [#自定义脚本-configcustom]
可以配置自定义的 CSS, Script。
### Scripts (`scripts`) [#scripts-scripts]
接受一个 [Script](https://nextjs.org/docs/app/api-reference/components/script#props) Props 参数数组。
### Styles (`styles`) [#styles-styles]
自定义 CSS。接受一个字符串数组。
### JavaScript tag (`js`) [#javascript-tag-js]
自定义 JS 脚本。接受一个字符串数组。
### CSS href link (`css`) [#css-href-link-css]
加载外部 CSS,接受一个 CSS 外部样式表链接数组。
## 模块 (`config.module`) [#模块-configmodule]
此部分配置了网站的一些特定功能模块,比如活动跟踪、捐赠支持、社交媒体链接等。
### 实时活动 (`activity`) 模块 [#实时活动-activity-模块]
* **`enable`**: 控制模块是否启用。
* **`endpoint`**: 指定活动更新的服务器端点。
**如何使用**: 若需开启活动跟踪功能,将 `enable` 设为 `true` 并设置 `endpoint` 为处理活动数据的服务器地址。
### 捐赠 (`donate`) 模块 [#捐赠-donate-模块]
* **`enable`**: 控制捐赠模块是否启用。
* **`link`**: 提供捐赠页面的链接。
* **`qrcode`**: 提供一或多个捐赠二维码图片的链接。
**如何使用**: 启用捐赠功能,并提供捐赠链接或捐赠二维码,以便支持者可以直接进行捐赠。
### 社交媒体 (`bilibili`) 模块 [#社交媒体-bilibili-模块]
* **`liveId`**: b 站直播间 ID
### OpenPanel 模块 [#openpanel-模块]
[OpenPanel](https://openpanel.dev) 是一个开源的网站分析工具。
* **`enable`**: 控制 OpenPanel 功能是否启用。
* **`id`**: OpenPanel 的 ID。
* **`url`**: OpenPanel 的访问地址。
**如何使用**: 如果你使用 OpenPanel 进行网站分析,通过这些配置连接并启用面板。
### 文章列表设定 (`posts`) [#文章列表设定-posts]
* **`mode`**: 文章列表的预览模式。可选值:`"loose"`(默认)、`"compact"`
两个模式,紧凑模式和松散模式。
### RSS 配置 (`rss`) [#rss-配置-rss]
* **`noRSS`**: 设为 `true` 可禁用 RSS 输出。
* **`custom_elements`**: 自定义 RSS 元素数组。
### 签名动画 (`signature`) 模块 [#签名动画-signature-模块]
* **`svg`**: 签名的 SVG 代码。
* **`animated`**: 是否启用动画效果,默认为 `true`。
**如何使用**: SVG 代码可通过 [此网站](https://danmarshall.github.io/google-font-to-svg-path/) 生成。
受限于 JSON 语法规则,SVG 代码需替换所有的 `"` 为 `\"`,否则会报错。
### OG 图片 (`og`) [#og-图片-og]
* **`avatar`**: 自定义 Open Graph 图片中的头像 URL。
### 订阅 (`subscription`) [#订阅-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": {
"favicon": "/favicon.svg",
"faviconDark": "/favicon-dark.svg"
},
"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": {
"enable": true,
"endpoint": "/fn/ps/update"
},
"donate": {
"enable": false,
"link": "",
"qrcode": []
},
"bilibili": {
"liveId": 0
},
"openpanel": {
"enable": false,
"id": "",
"url": ""
},
"posts": {
"mode": "loose"
},
"signature": {
"svg": "",
"animated": true
}
}
}
}
```
请注意,这份配置你需要自行修改成符合你需求的内容。更多配置项的信息请参考上方各字段说明。
配置也可写成 YAML 格式,此时数据类型应选择 `YAML`。
# 余白 / Yohaku (/docs/themes/yohaku)
## 概述 [#概述]
> 留白也是写作的一部分。
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 的关系 [#与-shiro-的关系]
Yohaku 是 Shiro 的下一代演进。如果你正在使用 Shiro,可以继续使用——Shiro 仍然是一个完整的开源主题。Yohaku 在 Shiro 的基础上提供了更精致的视觉设计和更多闭源独有功能。
## 相关链接 [#相关链接]
* [Innei/Yohaku](https://github.com/Innei/Yohaku) — 开源设计存档
* [Innei/Shiro](https://github.com/Innei/Shiro) — 开源前身
* [在线演示](https://innei.in) — Innei 的个人博客,使用 Yohaku 驱动