My blog

My blog

wrCBDjdh·2026-05-23·33 阅读

wrCBDjdh 个人博客 — 项目文档

概述

基于 Next.js 14 (App Router) 构建的全栈个人博客系统,集成了文章发布、评论互动、友情链接管理、用户认证等完整功能模块。采用 Neon Serverless PostgreSQL 作为数据库,Prisma 作为 ORM,部署在 Vercel 平台,支持 Docker 容器化运行。


技术栈

前端

技术版本用途
Next.js14.2.5React 框架 (App Router)
React18.3.1UI 库
TypeScript5.5.4类型安全
Tailwind CSS3.4.7原子化 CSS 框架
react-markdown9.0.1Markdown 文章渲染
remark-gfm4.0.0GFM 扩展 (表格/删除线等)
date-fns3.6.0日期格式化
react-hot-toast2.4.1交互提示组件
clsx2.1.1条件 class 拼接

后端

技术版本用途
Next.js API Routes14.2.5服务端 API
Prisma5.17.0ORM / 数据库操作
PostgreSQL (Neon)数据库 (Serverless)
NextAuth.js4.24.7身份认证 (Credentials + JWT)
bcryptjs2.4.3密码哈希

存储 & 部署

服务用途
Neon (postgresql)数据库托管
imgbb图片托管 (免费图床)
AWS S3 SDKS3 兼容存储 (R2)
Vercel前端部署
Docker (Alpine)容器化部署

项目结构

personal-blog/
├── prisma/
│   ├── schema.prisma       # 数据库模型定义 (User, Post, Comment, Like, RateLimit, FriendLink, ChatMessage)
│   ├── seed.ts             # 管理员账号初始化脚本
│   └── dev.db              # 开发环境 SQLite 数据库
│
├── src/
│   ├── app/                # Next.js App Router 页面 & API
│   │   ├── page.tsx        # 首页 — 个人资料、最近文章、统计数据、时钟
│   │   ├── layout.tsx      # 全局布局 — Header + Footer + Session 提供
│   │   ├── globals.css     # 全局样式、Tailwind、Prose 排版
│   │   ├── articles/       # 文章列表 ([id]/page.tsx — 文章详情)
│   │   ├── admin/          # 管理后台 (仪表盘、文章 CRUD、友链管理、登录)
│   │   ├── account/        # 账号设置 (昵称、头像、密码修改)
│   │   ├── friends/        # 友情链接展示页
│   │   ├── login/          # 用户登录
│   │   ├── register/       # 用户注册
│   │   └── api/            # API 路由 (auth, posts, comments, likes, upload, account, admin, friendlinks, chat, init, user)
│   │
│   ├── components/         # 共享组件
│   │   ├── Header.tsx      # 顶部导航栏 (响应式)
│   │   ├── Footer.tsx      # 底部 (GitHub/Email/Bilibili 链接)
│   │   ├── PostCard.tsx    # 文章卡片 (封面、标题、摘要、统计数据)
│   │   ├── Comment.tsx     # 评论区组件
│   │   ├── CommentForm.tsx # 评论表单
│   │   ├── LikeButton.tsx  # 点赞按钮 (支持登录/未登录状态)
│   │   ├── Clock.tsx       # 实时时钟组件
│   │   ├── Quote.tsx       # 首页名言组件
│   │   ├── Icons.tsx       # SVG 图标集 (GitHub, Email, Bilibili)
│   │   ├── ImageUploader.tsx   # 图片上传 (imgbb)
│   │   ├── FriendLinkAvatar.tsx # 友链头像
│   │   └── SessionProvider.tsx  # NextAuth Session 上下文
│   │
│   ├── lib/
│   │   ├── prisma.ts       # Prisma 客户端单例 (全局缓存)
│   │   ├── auth.ts         # NextAuth 配置 (Credentials 登录、速率限制、JWT 回调)
│   │   └── r2.ts           # imgbb 文件上传封装
│   │
│   ├── types/
│   │   └── index.ts        # 类型声明 (next-auth 扩展、Post, Product, Comment)
│   │
│   └── middleware.ts       # CSRF 保护 + 管理后台鉴权中间件
│
├── public/
│   ├── favicon.png
│   └── avatars/            # 本地头像资源
│
├── Dockerfile              # 多阶段 Docker 构建 (node:20-alpine)
├── next.config.js          # Next.js 配置 (图片域名、安全头、CSP、跨域隔离)
├── tailwind.config.ts      # Tailwind 主题扩展 (颜色、字体、动画)
├── tsconfig.json           # TypeScript 配置 (路径别名 @/ → ./src/)
├── postcss.config.js       # PostCSS 配置
└── .env.example            # 环境变量模板

数据库模型

User (用户)

字段类型说明
idString (cuid)主键
emailString (unique)邮箱 / 登录名
passwordStringbcrypt 哈希密码
nameString?昵称
roleString (default: "user")角色 (admin/user)
avatarString?头像 URL
bioString?个人简介
githubString?GitHub 链接
twitterString?Twitter 链接
bilibiliString?Bilibili 链接
isVerifiedBoolean是否验证
createdAtDateTime创建时间

Post (文章)

字段类型说明
idString (cuid)主键
titleString标题
contentStringMarkdown 正文
summaryString?摘要
coverImageString?封面图
publishedBoolean (default: true)发布状态
viewCountInt (default: 0)阅读量
authorIdString → User作者外键
createdAtDateTime创建时间
updatedAtDateTime更新时间

Comment (评论)

字段类型说明
idString (cuid)主键
contentString评论内容
nicknameString?游客昵称
postIdString? → Post所属文章
userIdString? → User登录用户
createdAtDateTime创建时间

Like (点赞)

字段类型说明
idString (cuid)主键
postIdString? → Post文章
userIdString? → User用户
createdAtDateTime创建时间

唯一约束: [postId, userId] — 每用户每篇文章只能点赞一次

RateLimit (速率限制)

字段类型说明
idString (cuid)主键
identifierString (unique)标识 (邮箱/IP)
countInt尝试次数
firstAttemptBigInt首次尝试时间戳
expiresAtDateTime锁定过期时间

FriendLink (友情链接)

字段类型说明
idString (cuid)主键
nameString网站名称
urlString网站 URL
descriptionString?描述
avatarString?头像
orderInt (default: 0)排序权重
isActiveBoolean是否启用
createdAtDateTime创建时间

核心功能

1. 文章系统

  • Markdown 编写 (支持 GFM 语法扩展)
  • 封面图、摘要、阅读量统计
  • 点赞 + 评论互动
  • 管理后台 CRUD (新建/编辑/删除/发布/草稿)
  • imgbb 图片上传集成 (支持拖拽上传)

2. 用户认证

  • Credentials 登录 (邮箱 + 密码)
  • JWT Session 策略 (30 天有效期)
  • bcrypt 密码加密存储
  • 速率限制: 5 次尝试 / 15 分钟窗口, 超限封禁 30 分钟
  • 管理员种子脚本 (prisma/seed.ts)

3. 安全防护

  • CSP 内容安全策略: 限制脚本/样式/图片/字体来源
  • HSTS: 强制 HTTPS (1 年, 包含子域名)
  • CSRF 保护: 中间件验证 Origin/Referer 头, 支持 ALLOWED_ORIGINS 白名单
  • 安全头: X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Permissions-Policy
  • 跨域隔离: Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy
  • API body 限制: 10MB (Server Actions)

4. 友情链接

  • 后台添加/排序/管理
  • 前端展示 (网格布局, 头像 + 描述)

5. 响应式设计

  • 移动端自适应 (汉堡菜单)
  • Tailwind CSS 响应式断点
  • 卡片网格 1/2/3 列自适应

环境变量

# Database - Neon PostgreSQL
DATABASE_URL="postgresql://neondb_owner:密码@ep-xxx.aws.neon.tech:5432/neondb?sslmode=require"

# NextAuth
NEXTAUTH_SECRET="运行 node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\" 生成"
NEXTAUTH_URL="https://你的vercel域名.vercel.app"

# imgbb (免费图床)
IMGBB_API_KEY="从 https://imgbb.com 获取"

# Init Secret
INIT_SECRET="运行 node -e \"console.log(require('crypto').randomBytes(16).toString('hex'))\" 生成"

# Admin Account
ADMIN_EMAIL="你的邮箱"
ADMIN_PASSWORD="你的密码"

运行方式

# 开发
npm run dev                # 启动开发服务器 (localhost:3000)

# 数据库
npm run db:push            # 推送 schema 到数据库
npm run db:studio          # 打开 Prisma Studio 数据管理
npm run db:seed            # 初始化管理员账号

# 构建 & 部署
npm run build              # 生产构建
npm start                  # 启动生产服务器

# Docker
docker build -t blog .     # 构建镜像
docker run -p 3000:3000 blog

API 路由一览

路由方法说明
/api/auth/...POSTNextAuth 认证 (登录/登出/会话)
/api/registerPOST用户注册
/api/postsGET/POST文章列表 / 新建
/api/posts/[id]GET/PUT/DELETE文章详情 / 更新 / 删除
/api/commentsGET/POST评论列表 / 发表
/api/likesPOST/DELETE点赞 / 取消
/api/uploadPOST图片上传 (imgbb)
/api/accountGET/PUT用户信息 / 更新
/api/adminGET管理后台统计
/api/friendlinksGET/POST友情链接列表 / 添加
/api/initPOST系统初始化
/api/userGET用户信息

设计风格

  • 配色: Amber 暖色调渐变背景 (#fffbeb → #f3e8ff → #ffedd5)
  • 主色: Sky Blue (primary-500: #0ea5e9)
  • 字体: Inter (无衬线), CSS 变量 --font-inter
  • 卡片: 毛玻璃效果 (bg-white/70 backdrop-blur-sm), 圆角 + 阴影
  • 动画: gradientBreath 呼吸渐变, fadeInUp 入场
  • 排版: 自定义 prose 样式 (代码块暗色主题、引用块、图片圆角)

评论 (0)

暂无评论,快来抢沙发吧