在线写作与 GitHub 提交
这个站点的在线写作功能分成两条清楚的入口:
- 首页的
新建文档:进入/write,用于创建一篇新的 Markdown 文档。 - 文档阅读页的
在线编辑:进入/write?path=...,只编辑当前正在阅读的这篇文档。
本地 Markdown 导入不再作为首页主入口,而是放在 /write 写作页内部。这样首页负责创建,文档页负责编辑,导入只是新建文档流程里的一个补充能力。
写入链路
浏览器写 Markdown
-> Vercel Serverless API
-> GitHub OAuth 校验身份
-> GitHub Contents API 写入仓库
-> Vercel 自动重新构建站点文档内容仍然以 Markdown 文件为源头,默认写入 docs/src/docs/。图片会上传到 docs/src/public/assets/uploads/,Markdown 中保存 /assets/uploads/... 路径。
为什么需要 Vercel API
浏览器页面不能直接保存 GitHub token。只要把 token 写进前端代码、构建环境变量或静态资源里,任何访问网站的人都有机会拿到它。
所以成熟可用的做法是:
- 前端只负责写作、导入、上传和提交动作。
- GitHub OAuth 的
client_secret放在 Vercel Serverless Function。 /api/github/*完成登录校验、用户白名单校验、路径校验和 GitHub 写入。
GitHub Pages 是纯静态托管,不能运行这些 API,所以只能阅读文档,不能站内提交。
GitHub OAuth App 配置
进入 GitHub:
Settings -> Developer settings -> OAuth Apps -> New OAuth App填写:
| 配置项 | 示例 |
|---|---|
| Application name | Justin Docs Writer |
| Homepage URL | https://你的域名.vercel.app |
| Authorization callback URL | https://你的域名.vercel.app/api/github/oauth/callback |
创建后得到:
Client IDClient Secret
Client Secret 只能放在 Vercel 环境变量里,不能提交到 GitHub。
Vercel 环境变量
在 Vercel 项目中进入:
Settings -> Environment Variables添加:
| 变量名 | 示例值 | 说明 |
|---|---|---|
GITHUB_CLIENT_ID | OAuth App 的 Client ID | 公开 ID |
GITHUB_CLIENT_SECRET | OAuth App 的 Client Secret | 服务端密钥 |
GITHUB_OWNER | chizhang977 | 仓库拥有者 |
GITHUB_REPO | justin | 仓库名 |
GITHUB_BRANCH | master | 写入分支 |
GITHUB_ALLOWED_USERS | chizhang977 | 允许在线提交的 GitHub 用户,多个用户用英文逗号分隔 |
GITHUB_OAUTH_SCOPE | public_repo | 公开仓库写入权限,私有仓库改成 repo |
GITHUB_ALLOWED_PREFIXES | docs/src/docs/,docs/src/index.md | 允许编辑的 Markdown 路径 |
配置完成后,重新部署 Vercel。
新建文档流程
- 打开首页。
- 点击
新建文档。 - 在写作页选择分类目录、文件名。
- 在 Vditor 编辑器中写 Markdown,默认使用类似 Typora 的即时渲染模式。
- 需要检查排版时,可以用工具栏切换分屏预览、预览或全屏模式。
- 点击
GitHub 登录完成授权。 - 点击
提交。 - 等待 Vercel 自动构建完成后访问新文档。
新建文档时会保存本地草稿。没有提交前,即使登录 GitHub 导致页面跳转,回到 /write 后也会恢复上次未提交的新建草稿。
编辑当前文档流程
- 打开任意文档阅读页。
- 点击文档信息栏中的
在线编辑。 - 页面进入
/write?path=当前文档路径。 - 如果未登录,会先显示登录面板,不会创建空白新文档。
- 登录后自动读取当前文档内容。
- 修改后点击
提交。 - 提交成功后页面自动返回该文档阅读页。
这条流程不会让你手动选择目录,也不会误把“编辑当前文档”变成“新建文档”。
导入本地 Markdown
导入属于新建文档流程。
- 打开
/write。 - 点击左侧或顶部的
导入。 - 选择本地
.md、.markdown、.mdown文件,也可以拖入写作页设置区。 - 系统自动读取标题:优先 frontmatter 的
title,其次第一个一级标题,最后使用文件名。 - 确认分类目录、文件名和标题。
- 点击
提交写入 GitHub。
导入文件建议控制在 3MB 以内。导入后按新建文档提交,如果目标路径已经存在,接口会拒绝覆盖,避免误删已有内容。
图片上传
写作编辑器支持插入图片链接,也支持上传本地图片。
上传本地图片时,浏览器会把图片交给:
/api/github/asset接口会校验 GitHub 登录状态和用户白名单,然后把图片写入:
docs/src/public/assets/uploads/YYYY/MM/Markdown 中保存的图片路径类似:
支持的图片类型:
pngjpgjpegwebpgifsvg
单张图片建议不超过 4MB。更大的截图或动图应先压缩,否则会影响仓库体积和页面加载速度。
编辑器交互
写作页使用 Vditor 作为统一 Markdown 编辑器,新建、导入和编辑当前文档都进入同一个编辑器实例,不再维护两套编辑体验。
- 默认模式是
ir即时渲染,写 Markdown 时会像 Typora 一样直接显示排版效果。 - 工具栏支持标题、加粗、斜体、删除线、引用、无序列表、有序列表、任务列表、缩进、代码块、行内代码、链接、表格、图片上传、撤销、重做、编辑模式切换、分屏预览、预览、全屏和大纲。
- 上传图片会继续走
/api/github/asset,图片写入仓库静态资源目录后再把 Markdown 图片语法插入当前光标位置。 Ctrl + S或Command + S会触发提交,提交成功后自动返回文档阅读页。
文档站最终显示效果仍以 VitePress 构建结果为准。Vditor 负责提供稳定、完整的在线写作体验,GitHub 仍然是 Markdown 源文件的唯一存储位置。
安全边界
Markdown 编辑接口默认只允许写入:
docs/src/docs/
docs/src/index.md图片上传接口只写入:
docs/src/public/assets/uploads/同时建议保留:
GITHUB_ALLOWED_USERS=chizhang977这样即使其他 GitHub 用户进入 /write 并完成 OAuth 授权,也不能通过接口提交内容。
上线验收清单
- 打开 Vercel 线上首页,点击
新建文档。 - 确认
/write能正常打开,编辑器能输入标题、段落、代码块、表格。 - 点击
GitHub 登录,确认能跳转 GitHub OAuth。 - 授权后确认能回到
/write,并显示当前 GitHub 用户。 - 新建一篇测试文档并提交。
- 到 GitHub 仓库确认 Markdown 文件已经生成。
- 等待 Vercel 自动构建,确认线上能访问新文档。
- 打开这篇文档,点击
在线编辑,确认能读取当前文档内容。 - 修改后再次提交,确认 GitHub 产生新的 commit。
- 在写作页插入一张小图片,确认图片文件写入
docs/src/public/assets/uploads/,线上文档能正常显示。
常见问题
提交后为什么页面没有马上变化
提交成功只代表 Markdown 或图片已经写进 GitHub。线上页面需要等待 Vercel 构建完成后才会更新。
GitHub Pages 能不能站内提交
不能。GitHub Pages 没有服务端函数,无法安全保存 GitHub OAuth Secret。
为什么 OAuth scope 默认用 public_repo
这个博客仓库是公开仓库,public_repo 已经能满足公开仓库内容写入。只有当仓库改成私有仓库时,才需要把 GITHUB_OAUTH_SCOPE 改成 repo。