这篇用教程形式记录这个项目的完整上线方法,按步骤执行即可复刻同样的部署结果。

Deploy Tutorial Cover

1. 准备条件

  • 一个 GitHub 仓库(示例:FrankieChiu/fesnkie-blog
  • 一个 Vercel 项目并已绑定该仓库
  • 一个可用域名(示例:blog.fesnkie.com

2. 项目依赖与脚本

package.json 需要包含:

json
{
  "scripts": {
    "dev": "next dev",
    "dev:cms": "concurrently -k \"next dev\" \"npx decap-server\"",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "gray-matter": "4.0.3",
    "marked": "12.0.2",
    "next": "14.2.5",
    "react": "18.3.1",
    "react-dom": "18.3.1"
  }
}

3. Admin 路由映射

next.config.js

js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
        source: "/admin",
        destination: "/admin/index.html"
      }
    ];
  }
};

module.exports = nextConfig;

4. 配置 Decap CMS

项目里放两份同内容配置:

  • public/admin/config.yml
  • public/config.yml

核心配置:

yml
backend:
  name: github
  repo: FrankieChiu/fesnkie-blog
  branch: main
  base_url: https://blog.fesnkie.com
  auth_endpoint: api/auth

local_backend: false

media_folder: "public/uploads"
public_folder: "/uploads"

collections:
  - name: "posts"
    label: "Posts"
    folder: "content/posts"
    create: true
    slug: "{{slug}}"
    extension: "md"
    format: "frontmatter"
    fields:
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - { label: "Summary", name: "summary", widget: "text" }
      - { label: "Category", name: "category", widget: "string" }
      - { label: "Tags", name: "tags", widget: "list" }
      - { label: "Cover", name: "cover", widget: "image", required: false }
      - { label: "Body", name: "body", widget: "markdown" }

5. GitHub OAuth App 配置

在 GitHub 创建 OAuth App:

  • Homepage URL:https://blog.fesnkie.com
  • Authorization callback URL:https://blog.fesnkie.com/api/auth/callback

创建后拿到:

  • Client ID
  • Client Secret

6. Vercel 环境变量

在 Vercel 项目里添加:

  • GITHUB_CLIENT_ID
  • GITHUB_CLIENT_SECRET
  • GITHUB_OAUTH_SCOPE(可选,默认 repo

添加后重新部署一次(Redeploy)。

7. API 路由:授权与回调

app/api/auth/route.ts

作用:跳转到 GitHub 授权页,并写入 github_oauth_state cookie。

app/api/auth/callback/route.ts

作用:用 code 换 token,并把结果通过浏览器回传给 /admin 页面。

这两条路由是 Decap + GitHub OAuth 成功登录的关键。

8. Admin 入口页

public/admin/index.html 里需要完成三件事:

  1. 加载 Decap CMS 脚本
  2. 消费 OAuth 回调写入的 decap_oauth_message
  3. 将 token 写入 CMS 用户缓存并回到 /admin/

这是“GitHub 登录成功但后台不跳转”的核心修复点。

9. 发布流程(每天使用)

  1. 打开:https://blog.fesnkie.com/admin/
  2. GitHub 登录
  3. 新建/编辑文章
  4. 点 Publish
  5. 提交写入 GitHub
  6. Vercel 自动部署

10. 故障排查清单

登录成功但进不去后台

先查这 4 项:

  1. https://blog.fesnkie.com/config.yml 是否 200
  2. Vercel 环境变量是否齐全并已生效
  3. GitHub OAuth callback 是否精确为 /api/auth/callback
  4. public/admin/index.html 是否包含 OAuth 消费逻辑

安全注意

如果 token 曾出现在控制台或聊天记录,请立即在 GitHub 撤销 OAuth 授权再重新登录。