本文记录了我为 Astro 博客集成 Decap CMS 的完整过程,包括遇到的问题和解决方案。
什么是 Decap CMS
Decap CMS(原 Netlify CMS)是一个开源的内容管理系统,专为静态网站设计。它的特点是:
- 基于 Git:内容存储在 GitHub 仓库,不需要数据库
- Web 编辑器:在浏览器中直接编辑文章
- 自动提交:发布时自动提交到 GitHub
- 免费开源:完全免费使用
为什么需要 CMS
之前写博客的流程是:
打开 VS Code → 创建 MD 文件 → 手写 frontmatter → 写正文 → git add/commit/push → 等待构建
这个流程有几个痛点:
- 需要打开编辑器
- 需要手动写 YAML 格式的 frontmatter
- 需要手动执行 git 命令
- 不能随时随地写文章
集成 Decap CMS 后:
打开网页 → 填表单 → 写正文 → 点击发布 → 完成
集成步骤
第 1 步:创建配置文件
在 public/admin/ 目录下创建两个文件:
config.yml:
backend:
name: github
repo: 你的用户名/你的仓库名
branch: main
base_url: https://你的域名
auth_endpoint: api/auth
media_folder: "public/img"
public_folder: "/img"
# 开启编辑工作流
publish_mode: editorial_workflow
# 中文界面
locale: "zh_Hans"
collections:
- name: "life"
label: "生活随笔"
folder: "src/content/blog/life"
create: true
delete: true
slug: "{{slug}}"
fields:
- { label: "标题", name: "title", widget: "string", required: true }
- { label: "链接", name: "link", widget: "string", required: true }
- { label: "日期", name: "date", widget: "datetime", required: true }
- { label: "分类", name: "categories", widget: "list", required: false }
- { label: "标签", name: "tags", widget: "list", required: false }
- { label: "描述", name: "description", widget: "text", required: false }
- { label: "封面", name: "cover", widget: "image", required: false }
- { label: "草稿", name: "draft", widget: "boolean", default: false }
- { label: "正文", name: "body", widget: "markdown", required: true }
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>博客编辑器</title>
</head>
<body>
<script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>
第 2 步:创建 OAuth 认证 API
Decap CMS 需要通过 GitHub OAuth 来获取权限。在 src/pages/api/auth/ 目录下创建两个文件:
index.ts(认证入口):
import type { APIRoute } from 'astro';
const GITHUB_CLIENT_ID = import.meta.env.GITHUB_CLIENT_ID;
export const GET: APIRoute = async ({ redirect }) => {
const authUrl = new URL('https://github.com/login/oauth/authorize');
authUrl.searchParams.set('client_id', GITHUB_CLIENT_ID);
authUrl.searchParams.set('scope', 'repo,user');
return redirect(authUrl.toString());
};
export const prerender = false;
callback.ts(认证回调):
import type { APIRoute } from 'astro';
const GITHUB_CLIENT_ID = import.meta.env.GITHUB_CLIENT_ID;
const GITHUB_CLIENT_SECRET = import.meta.env.GITHUB_CLIENT_SECRET;
export const prerender = false;
export const GET: APIRoute = async ({ url }) => {
const code = url.searchParams.get('code');
if (!code) {
return new Response('Missing code parameter', { status: 400 });
}
try {
const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
client_id: GITHUB_CLIENT_ID,
client_secret: GITHUB_CLIENT_SECRET,
code,
}),
});
const tokenData = await tokenResponse.json();
if (tokenData.error) {
return new Response(`OAuth error: ${tokenData.error_description}`, { status: 400 });
}
const { access_token } = tokenData;
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>认证成功</title>
<script>
(function() {
function receiveMessage(e) {
window.opener.postMessage(
'authorization:github:success:{"token":"${access_token}","provider":"github"}',
e.origin
);
}
window.addEventListener("message", receiveMessage, false);
window.opener.postMessage("authorizing:github", "*");
})();
</script>
</head>
<body>
<p>认证成功,正在完成登录...</p>
</body>
</html>
`;
return new Response(html, {
headers: { 'Content-Type': 'text/html' },
});
} catch (error) {
return new Response('Authentication failed', { status: 500 });
}
};
第 3 步:配置 Astro
在 astro.config.mjs 中添加 Vercel 适配器:
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'static',
adapter: vercel(),
// ... 其他配置
});
安装依赖:
pnpm add @astrojs/vercel
第 4 步:创建 GitHub OAuth 应用
- 打开 https://github.com/settings/developers
- 点击 “New OAuth App”
- 填写信息:
- Application name:
MyBlog CMS - Homepage URL:
https://你的域名 - Authorization callback URL:
https://你的域名/api/auth/callback
- Application name:
- 点击 “Register application”
- 复制
Client ID和生成Client Secret
第 5 步:配置 Vercel 环境变量
在 Vercel 项目设置中添加环境变量:
| Name | Value |
|---|---|
GITHUB_CLIENT_ID | 你的 Client ID |
GITHUB_CLIENT_SECRET | 你的 Client Secret |
第 6 步:部署
git add .
git commit -m "feat: 集成 Decap CMS"
git push
Vercel 会自动构建和部署。
遇到的问题和解决方案
问题 1:页面白屏
原因:index.html 中的 <body> 标签为空
解决:把 <script> 标签放到 <body> 里面
问题 2:Vercel 部署失败
错误:EISDIR: illegal operation on a directory
原因:api/auth/index.ts 和 api/auth/callback.ts 目录结构冲突
解决:确保 API 路由文件都在 api/auth/ 目录下,并添加 export const prerender = false
问题 3:登录后没反应
原因:OAuth 回调窗口和主窗口之间的消息传递失败
解决:使用 Decap CMS 标准的消息传递方式,先发送 authorizing:github,再监听消息回复
最终效果
集成完成后,访问 https://你的域名/admin/index.html 即可:
- 点击 “Login with GitHub” 登录
- 选择分类,点击 “New” 创建新文章
- 填写表单,编辑内容
- 点击 “Publish” 发布
文章会自动提交到 GitHub,Vercel 自动构建,博客自动更新。
可用功能
| 功能 | 说明 |
|---|---|
| 创建文章 | 在线创建新文章 |
| 编辑文章 | 修改已有文章 |
| 删除文章 | 删除不需要的文章 |
| 上传图片 | 拖拽上传图片 |
| 草稿功能 | 保存草稿,稍后发布 |
| 中文界面 | 界面显示中文 |
总结
Decap CMS 虽然界面不够美观,但功能够用,最重要的是:
- 免费:不需要付费
- 无数据库:内容存在 GitHub
- 自动化:发布自动触发构建
- 随时随地:只要有浏览器就能写文章
如果你也在用 Astro 搭建博客,推荐试试 Decap CMS!