← 返回文章列表
技术

从前台原型到可写作的个人博客:Boker 的功能与架构

从 Vite 前台原型到 Next.js 全栈博客,记录 Boker 的功能、内容模型与权限设计。

最早的 Boker 只是一个 Vite + React 前台原型:有页头、分类筛选、文章列表和基本样式,却没有可以长期写作的内容来源。到 2026 年 9 月,我希望它成为自己能维护的技术博客:打开后台写 Markdown,保存草稿,上传图片,发布后让读者直接访问文章链接。

这篇记录第一版做了什么,以及为什么从前台原型转为一个 Next.js 全栈应用。

从页面原型转向内容系统

原型可以展示模拟文章,却不能回答几个日常问题:文章存在哪里?谁能修改?草稿何时对外可见?图片和文章一起撤回时如何控制访问?如果只给 Vite 前台再接一个独立后端,部署时还要分别处理两个服务和公开文章的服务端渲染。

最终选择 Next.js App Router + TypeScript,将公开页面、管理后台和 API 放在一个仓库;PostgreSQL 保存内容,Prisma 管理模型和迁移。这是一个模块化单体:部署时只需要一个应用进程、一个数据库和一个持久化上传目录。它也保留了 React 前台原型已有的交互与样式基础。

公开读者 ──> Next.js 页面 ──> 文章业务层 ──> PostgreSQL
管理员   ──> 后台编辑器 ──> 同源 API ────┘
                              └──> 媒体存储与读取

两个界面,一套内容规则

公开首页按发布时间倒序列出文章,每页最多 10 篇,支持分类和标签筛选。文章详情显示作者、时间、目录、代码高亮和数学公式;每篇文章生成独立的标题、摘要、canonical 和分享元数据。sitemap 只列出公开且已发布的文章。

后台提供登录与退出、文章新建和编辑、草稿保存、发布与撤回、删除、分类和标签管理、媒体上传及站点设置。正文用 CodeMirror 6 编辑 Markdown,并能实时预览;图片可以通过选择文件或粘贴插入正文。第一版刻意使用明确的“保存”操作,保存失败时保留当前编辑内容。

内容模型里,status 和 visibility 是两个独立字段。DRAFT/PUBLISHED 表示是否发布,PUBLIC/PRIVATE 表示可见范围。公开查询同时要求 PUBLISHED 与 PUBLIC;知道私密文章的 slug,也不能通过公开详情页直接读取。这个过滤条件放在业务查询中,而不是只在页面上隐藏链接。

数据与权限如何分工

数据库包含用户、会话、登录尝试、文章、分类、标签、媒体和站点设置。第一版只实际使用一个管理员账号,但模型保留了 AUTHOR 角色及文章、媒体的所有权关系。后台页面会检查会话,API 和业务层还会独立检查权限;这样即使有人绕过页面按钮调用接口,仍不能管理其他作者的内容。

图片文件放在持久化目录,数据库保存媒体记录及其引用关系。浏览器通过应用的媒体接口读取图片,Nginx 不直接暴露上传目录。已经公开发布的文章可以向匿名读者展示其图片;草稿、私密文章或未引用图片仍需相应权限。

第一版没有做的事

目前没有开放注册、评论、论坛、作者邀请界面、审核流、定时发布或全文搜索。把这些留到真实写作和阅读需求出现后再设计,可以先把发布、权限、媒体和部署这条主链路做完整。

到 2026 年 9 月 18 日,站长已在实际站点验证登录、退出、上传图片、发布、编辑和删除。下一篇会拆开一篇文章从编辑器进入数据库的过程,重点记录链接别名、版本冲突和图片权限上的具体问题。