简单文档

Nuxt Studio 升级开发规划

基于 Nuxt 4、Nuxt Content v3 与 Nuxt Studio 的内容编辑能力升级方案。

背景

当前项目已经升级到 Nuxt 4、Nuxt Content v3 与 pnpm 11,内容系统采用 content/docscontent/blog 两个集合,站点支持文档、博客、RSS、Atom、sitemap、robots、OG 图片与静态生成。

本次规划目标是在现有内容体系上接入 Nuxt Studio,让内容编辑者可以在浏览器中编辑 Markdown、frontmatter、MDC 组件和媒体资源,并通过 GitHub 提交内容变更。

参考官方文档:

核心结论

Nuxt Studio 不是一个纯静态后台页面。生产环境中的登录、鉴权、Git 提交和发布流程依赖服务端路由,因此官方要求部署在支持 SSR 的平台上,并使用 nuxt build 生成生产产物。

当前项目的 GitHub Actions 主要执行 pnpm run generate,再将 .output/public 通过 rsync 上传为静态站点。这个部署模式无法完整承载 Nuxt Studio。

推荐路线是将主站升级为 SSR/hybrid 部署:

  • 继续对 //docs/**/blog/** 等内容页执行 prerender。
  • 生产运行 .output/server/index.mjs
  • Studio 管理界面挂载在 /_studio/admin
  • 使用 GitHub OAuth 登录,并由 Nuxt Studio 将内容变更提交到 GitHub 仓库。

当前项目适配点

已具备条件

  • 项目已使用 Nuxt 4 与 Nuxt Content v3。
  • content.config.ts 已定义 docsblog 两个 collection。
  • 内容文件以 Markdown 为主,适合 Studio 编辑。
  • 已有 Docker SSR 构建路线,Dockerfile 运行 pnpm build 并启动 .output/server/index.mjs
  • 已有 content:check 脚本,可作为 Studio 发布后的内容质量守门。

需要先处理的问题

  1. Dockerfile 需要复制 pnpm-workspace.yaml
    当前 pnpm 11 的构建脚本审批配置位于 pnpm-workspace.yaml。如果 Docker deps stage 只复制 package.jsonpnpm-lock.yaml.npmrcbetter-sqlite3 的原生构建许可可能不会进入容器安装环境。
  2. CI/CD 需要从纯静态部署调整为 SSR/hybrid
    Studio 生产编辑依赖服务端路由,不能只上传 .output/public。需要将部署目标切换为 Node SSR 或 Docker 服务。
  3. Content schema 需要更适合 Studio 表单
    当前 schema 运行时可用,但对 Studio 的编辑体验不够明确。应显式声明 titledescriptionnavigationimgdatelinks 等字段,并为 media、icon、textarea 等输入类型提供编辑器提示。
  4. CSP 需要为 Studio 单独验证
    当前全站启用严格 CSP。Studio 可能涉及浏览器侧 SQLite、IndexedDB、media draft service worker、外部 OAuth 跳转等能力。接入后需要对 /_studio/**/__nuxt_studio/** 做浏览器实测,必要时单独放宽 route rules。

推荐架构

内容编辑者

/_studio

GitHub OAuth

Nuxt Studio Server Routes

GitHub Repository

GitHub Actions

SSR / Hybrid Deploy

lijue.net

实施阶段

阶段一:部署基础调整

目标:让项目具备稳定的 SSR/hybrid 生产部署能力。

任务:

  • 修改 Dockerfile deps stage,复制 pnpm-workspace.yaml
  • 将 CI 构建命令从单纯 pnpm run generate 调整为 pnpm build
  • 部署 .output/server,生产运行 node .output/server/index.mjs
  • 保留现有 prerender 设置,让公开内容页仍然静态化输出。
  • 确认微信签名服务、RSS、Atom、sitemap、robots 在 SSR 模式下行为一致。

验收:

  • pnpm install --frozen-lockfile 通过。
  • pnpm build 通过。
  • Docker 镜像构建通过。
  • 生产环境能访问首页、文档页、博客页、RSS、Atom、sitemap、robots。

阶段二:接入 Nuxt Studio 模块

目标:本地与生产环境能打开 Studio 管理界面。

任务:

  • 安装 nuxt-studio
  • nuxt.config.tsmodules 中加入 nuxt-studio
  • 配置 Studio 路由,建议先使用默认 /_studio
  • 配置 GitHub 仓库信息:
studio: {
  route: '/_studio',
  repository: {
    provider: 'github',
    owner: 'estel-li',
    repo: 'estel_docs',
    branch: 'main',
    private: false
  },
  git: {
    commit: {
      messagePrefix: 'content:'
    }
  },
  editor: {
    iconLibraries: ['lucide', 'simple-icons', 'vscode-icons', 'devicon']
  }
}

验收:

  • 本地开发环境能打开 /_studio
  • 生产构建包含 Studio 路由。
  • 不影响现有 docs/blog 页面渲染。

阶段三:配置 GitHub OAuth

目标:编辑者可通过 GitHub 登录 Studio,并将内容变更发布到仓库。

GitHub OAuth App 建议配置:

Homepage URL:
https://lijue.net

Authorization callback URL:
https://lijue.net/__nuxt_studio/auth/github

生产环境变量:

NUXT_STUDIO_AUTH_GITHUB_CLIENT_ID=...
NUXT_STUDIO_AUTH_GITHUB_CLIENT_SECRET=...
NUXT_STUDIO_AUTH_GITHUB_MODERATORS=editor@example.com,admin@example.com

说明:

  • GitHub OAuth 登录后可以自动用于 Git 操作,不需要额外 Personal Access Token。
  • 即使官方将 GitHub moderators 标为可选,也建议配置白名单,避免编辑入口过宽。
  • 不建议第一阶段使用 Google OAuth,因为 Google 登录不能直接提供 Git 写入能力,仍需单独配置 Git token。

验收:

  • 生产环境能完成 GitHub OAuth 登录。
  • 非白名单用户不能进入编辑流程。
  • 白名单用户能编辑内容并发布。
  • GitHub 仓库出现以 content: 开头的提交。

阶段四:优化 Content Schema

目标:让 Studio 自动生成更清晰的 frontmatter 表单。

任务:

  • z@nuxt/content re-export 改为 zod/v4
  • 显式定义 titledescriptionnavigationlinksdraft 等字段。
  • 为博客集合定义 imgdateupdatedcategorytags
  • 对适合可视化编辑的字段使用 property() 提供编辑器提示。

示例方向:

import { defineCollection, defineContentConfig, property } from '@nuxt/content'
import { z } from 'zod/v4'

const linkSchema = z.object({
  label: z.string(),
  icon: z.string(),
  to: z.string(),
  target: z.string().optional()
})

const navigationSchema = z.union([
  z.boolean(),
  z.object({
    title: z.string().optional(),
    description: z.string().optional(),
    icon: property(z.string()).editor({ input: 'icon' }).optional()
  })
])

博客 img 字段有两种路线:

  • 若继续使用远程图床,保留普通 z.string()
  • 若希望 Studio 管理 /public 媒体库,改为 media editor,并逐步把图片迁入 public 或外部 media provider。

验收:

  • Studio 中 docs/blog frontmatter 表单清晰可编辑。
  • 新建博客时能看到必填字段。
  • pnpm content:check 能继续校验内容质量。

阶段五:接入自定义 MDC 组件编辑

目标:让编辑者可以在 Studio 中插入项目已有的内容组件。

任务:

  • app/components/content 下的 MDC 内容组件标记为全局组件。
  • 通过 Studio editor 配置限制可用组件范围。
  • 为常用组件补充 props 类型,方便 Studio 生成编辑面板。

建议先开放:

  • ECard
  • ETabs
  • Stack
  • Playground
  • FileTree
  • CodeTree
  • ButtonLink
  • SmartIcon
  • ReadMore

暂不开放:

  • 布局组件
  • 导航组件
  • 仅用于页面壳层的业务组件
  • 依赖复杂运行时状态的组件

验收:

  • Studio slash menu 可插入常用内容组件。
  • 插入组件后 Markdown 源码可读。
  • 构建与渲染正常。

阶段六:强化 CI 守门

目标:Studio 发布内容后,自动发现错误内容。

建议 CI 至少执行:

pnpm install --frozen-lockfile
pnpm content:check
pnpm typecheck
pnpm test:unit
pnpm build

可选增强:

  • 对 PR 运行 pnpm test:e2e
  • 对 main 定期运行完整 E2E。
  • 将内容检查结果作为 GitHub status check。

验收:

  • Studio 发布错误 frontmatter 时 CI 能失败。
  • Studio 发布坏链接或坏图片引用时 CI 能失败。
  • main 分支始终保持可部署。

风险与对策

纯静态部署不兼容 Studio 生产编辑

风险:只部署 .output/public 会导致登录、发布、Git 写入等功能不可用。

对策:切换为 SSR/hybrid 部署,保留 prerender 优势。

内容编辑者可能破坏文件命名约定

风险:当前内容依赖数字前缀控制排序,例如 1.简单文档/2.installation.md。Studio 编辑者如果随意重命名文件,可能影响路由和导航顺序。

对策:在编辑规范中明确文件命名规则;首阶段仅允许编辑现有文件,谨慎开放新建与重命名能力。

远程图床与 Studio Media Library 体验不一致

风险:当前博客大量使用远程图片 URL。Studio Media Library 默认管理 /public,不能天然管理外部图床。

对策:第一阶段保留远程 URL;第二阶段评估接入 S3、R2 或继续使用现有图床。

CSP 影响 Studio 管理界面

风险:严格 CSP 可能拦截 Studio 的 worker、blob、OAuth 或媒体预览能力。

对策:为 Studio 路由单独配置 routeRules,并用浏览器 E2E 实测登录、编辑、发布和媒体上传。

最小可行版本

MVP 范围:

  • SSR/hybrid 部署可用。
  • /_studio 可登录。
  • GitHub OAuth 可鉴权。
  • 白名单编辑者可编辑现有 docs/blog Markdown。
  • 发布后 GitHub 产生 commit。
  • CI 自动构建并部署。
  • 不开放复杂媒体管理和大规模组件库。

不在 MVP 范围:

  • 多角色权限系统。
  • 自定义工作流审批。
  • 外部媒体存储迁移。
  • 多分支草稿预览。
  • 与微信签名服务联动。

最终验收清单

  • pnpm install --frozen-lockfile 通过。
  • pnpm content:check 通过。
  • pnpm typecheck 通过。
  • pnpm test:unit 通过。
  • pnpm build 通过。
  • Docker 构建通过。
  • 生产 /_studio 可打开。
  • GitHub OAuth 登录成功。
  • 非授权用户无法编辑。
  • 授权用户可编辑 docs 页面并发布。
  • 授权用户可编辑 blog frontmatter 并发布。
  • 自定义 MDC 组件可插入并渲染。
  • 发布后 GitHub 产生内容提交。
  • CI 自动部署成功。
  • 首页、文档、博客、RSS、Atom、sitemap、robots 行为正常。

推荐落地顺序

  1. 修复 Dockerfile pnpm workspace 复制问题。
  2. 将部署链路切换到 SSR/hybrid。
  3. 安装并启用 nuxt-studio
  4. 配置 GitHub OAuth 与 moderators。
  5. 优化 content.config.ts schema。
  6. 开放第一批内容组件给 Studio。
  7. 恢复并强化 CI 内容质量检查。
  8. 生产环境小范围试用。
  9. 根据编辑体验再迭代媒体库、组件属性和权限策略。