Next.js 博客接入 Decap CMS 完整教程(GitHub OAuth)
博客文章全用 Markdown 存 GitHub,每次发文都要手敲 frontmatter、提交、推送,格式还容易写错。接入一个 CMS 之后,可以在网页后台用可视化编辑器写文章,点发布就自动 commit 到仓库,静态站点重新构建即可生效。
这篇文章记录给 Next.js 博客接入 Decap CMS(原 Netlify CMS)的完整过程,包括后台页面、config.yml、GitHub OAuth 授权服务,以及一个很典型的坑。
为什么选 Decap CMS
- 免费:不需要服务器,不需要数据库,只是一个静态页面 + GitHub API
- 基于 Git:文章就是仓库里的 Markdown,随时可以退回纯手动流程
- 无后端:内容直接读写 GitHub,静态博客天然契合
对比 Strapi、Contentful 这类方案,它们功能更强但需要额外部署后端或付费,个人博客用不上。
第一步:准备后台页面
在 public/admin/ 下新建两个文件。
public/admin/index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex" />
<title>内容管理</title>
</head>
<body>
<script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>
meta robots 一定要写 noindex,否则搜索引擎会把后台页面也收录进去。
第二步:写 config.yml
public/admin/config.yml:
backend:
name: github
repo: yourname/your-repo
branch: main
base_url: https://oauth.example.com
auth_endpoint: auth
media_folder: "public/images"
public_folder: "/images"
collections:
- name: blog
label: 博客文章
folder: content
create: true
slug: "{{slug}}"
fields:
- { label: 标题, name: title, widget: string }
- { label: 路径标识, name: slug, widget: string, required: false }
- { label: 发布日期, name: date, widget: datetime, date_format: "YYYY-MM-DD", time_format: false }
- { label: 标签, name: tags, widget: list, required: false }
- { label: 摘要, name: description, widget: text }
- { label: 正文, name: body, widget: markdown }
几点说明:
folder要和博客实际存放 Markdown 的目录一致,本站是contentslug用{{slug}}会自动按标题生成文件名,中文标题会变成拼音或原字符,建议手动填英文短横线形式date_format只保留日期,避免 frontmatter 里出现带时区的长字符串
第三步:部署 GitHub OAuth 授权服务
Decap CMS 登录要经过 GitHub OAuth,必须有服务端保管 client_secret,所以需要一个授权服务。官方的做法是部署一个现成模板,社区版本很多,搜索 netlify-cms-oauth 可以找到。
大致流程:
- GitHub → Settings → Developer settings → OAuth Apps → 新建
Homepage URL填博客域名,Authorization callback URL填授权服务的回调地址- 拿到 Client ID 和 Client Secret
- 把授权服务模板部署到 Vercel / Cloudflare Workers,配置这两个环境变量
- 把平台分配的域名填回
config.yml的base_url
第四步:绕开默认域名打不开的问题
这是最容易卡住的地方。授权服务部署在 Vercel 后,默认的 xxx.vercel.app 域名在国内经常无法访问,表现为点「登录」后页面一直白屏或者报网络错误。
解决办法是给这个项目绑定自己的域名:
- 在 Vercel 项目设置里添加自定义域名,例如
oauth.example.com - 到 DNS 服务商加一条 CNAME 记录指向 Vercel
- 等证书签发完成后,把
config.yml的base_url改成https://oauth.example.com - 同步修改 GitHub OAuth App 里的回调地址,否则会提示 redirect_uri 不匹配
改完重新部署,后台就能正常登录了。
第五步:静态导出的路由问题
本项目用的是 output: 'export',public/admin/index.html 会被原样复制到 out/admin/index.html。访问 /admin/ 时需要服务器把目录请求映射到 index.html,Apache 默认支持,Nginx 需要:
location /admin/ {
index index.html;
try_files $uri $uri/ /admin/index.html;
}
如果访问 /admin/ 出现 404,先查这里。
使用体验
接好之后,写文章的流程变成:打开 /admin/ → 新建文章 → 填标题和标签 → 写正文 → 发布。CMS 会直接向仓库提交一个 commit,等到静态站点重新构建完成,文章就上线了。
图片上传会存到 public/images,Markdown 里自动写入 /images/xxx 的路径,和 Next.js 的静态资源规则一致。
常见问题
登录后提示 404 Not Found?
八成是 base_url 写错或 OAuth 回调地址没同步修改。检查 GitHub OAuth App 的 callback URL 是否和授权服务实际地址完全一致。
发布后网站没更新?
Decap CMS 只负责提交到 GitHub,不负责构建。如果你的站点是手动上传 out/,需要重新 npm run build 再部署一次。
中文文件名的文章会不会出问题?
能正常生成,但 URL 会变成一长串百分号编码,分享和统计时不好看。建议在 slug 字段手动填英文。
后台页面能被别人访问吗?
能访问,但没有 GitHub 权限就无法登录和修改。额外建议在服务器上给 /admin/ 加一层访问限制,或者只在内网使用。
能不能不用 OAuth 直接填 Token?
Decap CMS 支持 local_backend 本地模式开发,但线上必须走 OAuth,不要试图把 token 写进前端代码。