一个面向 Vercel 部署的全栈 Serverless 校园墙项目,基于 Next.js 16 App Router + React 18 + TypeScript + Tailwind CSS + Neon PostgreSQL + Auth.js v5。支持访客匿名投稿、用户账号体系、内容审核、管理后台、第三方登录、人机验证与邮件通知。
部署指南:详细的开发 / 预发布 / 生产部署步骤请查看 部署指南 →。
快速本地开发:
npm install && cp .env.example .env.local && npm run dev,访问 http://localhost:3000。
- 首页瀑布流:卡片式帖子网格,支持分类筛选、搜索、点赞与评论。
- 投稿:支持分类选择、富文本/Markdown 风格内容、图片上传(R2 预签名 URL)、匿名代号;登录用户可选择实名或匿名发布。
- 账号系统(基于 Auth.js v5):
- 用户名 / 邮箱 + 密码注册与登录(Credentials Provider)
- 邮箱验证链接
- 密码重置、个人信息管理
- 第三方 OAuth 预留:GitHub、Google、Microsoft、QQ(通过管理后台站点配置 + Auth.js Provider 开启)
- 权限体系:四级 RBAC(user / moderator / admin / superadmin)。
- 管理后台:先审后发、敏感词 / 封禁规则、分类管理、公告编辑、举报处理、站点配置(SMTP / OAuth / 人机验证)、用户管理。
- 安全防护:
- scrypt-sha256 密码哈希
- Auth.js 签名的 JWT session cookie(HttpOnly)
- 数据库敏感配置使用
pgcrypto对称加密 - 滑窗速率限制
- 可选 Cloudflare Turnstile / 极验 Geetest v4 人机验证
- 服务端 XSS 过滤与敏感词拦截
- 邮件通知:基于 Resend,开发模式可打印邮件到控制台;支持在管理后台配置 SMTP。
- Serverless 友好:Neon serverless driver、无 bcrypt 依赖、Vercel 一键部署。
- Next.js 16.2.9(Turbopack,实验性 serverActions)
- React 18 + TypeScript 5(strict 模式)
- Tailwind CSS 3
- Auth.js v5(
next-auth@5.0.0-beta.31,JWT session strategy) - Neon PostgreSQL(
@neondatabase/serverless) - AWS SDK for S3(兼容 Cloudflare R2)
复制 .env.example 为 .env.local 并配置。完整说明与分环境配置步骤见 部署指南。
| 变量 | 说明 |
|---|---|
DATABASE_URL |
Neon PostgreSQL 连接字符串 |
AUTH_SECRET |
Auth.js v5 签名密钥,生产至少 32 字符 |
NEXT_PUBLIC_SITE_URL |
站点根地址,用于生成邮件/回调链接 |
ADMIN_TOKEN |
管理后台紧急入口口令 |
RESEND_API_KEY |
Resend 邮件 API Key(dev 模式可省略) |
EMAIL_FROM |
发件人地址,如 校园墙 <noreply@your-domain.com> |
VERIFICATION_PEPPER |
验证码/重置 token 额外盐值 |
| 变量 | 说明 |
|---|---|
SITE_SETTINGS_SECRET |
站点配置加密密钥(缺省派生自 AUTH_SECRET) |
OAUTH_*_CLIENT_ID / CLIENT_SECRET / REDIRECT_URI / SCOPE |
GitHub / Google / Microsoft / QQ OAuth 兜底配置 |
TURNSTILE_SECRET / NEXT_PUBLIC_TURNSTILE_SITE_KEY |
Cloudflare Turnstile 人机验证 |
GEETEST_CAPTCHA_ID / GEETEST_CAPTCHA_KEY |
极验 Geetest v4 人机验证 |
R2_ACCOUNT_ID / R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY / R2_BUCKET / R2_PUBLIC_BASE / R2_MAX_FILE_SIZE |
Cloudflare R2 图片上传 |
NEXT_PUBLIC_SITE_NAME |
站点名称 |
MODERATION_KEYWORDS |
默认敏感词,英文逗号分隔 |
DEFAULT_POST_AUTHOR |
未填写代号时的默认作者名 |
SCRYPT_MAXMEM |
scrypt 内存上限(字节,可选) |
未配置
DATABASE_URL时项目会自动进入 demo 内存模式,便于本地 UI 验证;生产环境务必配置真实数据库。
npm install
# 复制并编辑环境变量
cp .env.example .env.local
# 初始化数据库(可选,不配置 DATABASE_URL 则进入 demo 模式)
psql "$DATABASE_URL" -f supabase/schema.sql
npm run dev如果是从旧版自研鉴权迁移,保留 users 表数据并切换到 Auth.js v5 表结构:
# 默认 dry-run,先预览将要执行的 SQL
DATABASE_URL="..." node scripts/migrate-to-authjs.mjs
# 确认无误后执行
DATABASE_URL="..." node scripts/migrate-to-authjs.mjs --execute执行 supabase/schema.sql 创建表结构,主要表包括:
users:用户账号accounts、sessions、verification_tokens:Auth.js v5 标准表(OAuth 关联、会话、邮箱验证/密码重置/魔法链接 token)posts、comments:内容与评论reports、audit_logs:举报与操作日志categories、announcements:分类与公告moderation_settings:敏感词 / 封禁规则site_settings、site_settings_audit:加密站点配置与变更审计rate_limit_events:滑窗速率限制
campus_confessions/
├── app/ # Next.js App Router
│ ├── admin/page.tsx # 管理后台入口页面
│ ├── api/
│ │ ├── admin/ # 管理后台 API
│ │ │ ├── announcement/ # 公告编辑
│ │ │ ├── captcha/ # 人机验证配置读写
│ │ │ ├── categories/ # 分类 CRUD
│ │ │ ├── logs/ # 操作日志查询
│ │ │ ├── pending/ # 待审核帖子
│ │ │ ├── posts/[id]/ # 帖子审核/修改/删除
│ │ │ ├── published/ # 已发布帖子列表
│ │ │ ├── reports/ # 举报处理
│ │ │ ├── search/ # 帖子搜索
│ │ │ ├── settings/ # 基础 moderation 配置
│ │ │ ├── site-settings/ # SMTP / OAuth / 加密配置
│ │ │ └── users/ # 用户列表 / 角色状态修改
│ │ ├── auth/ # 账号认证 API
│ │ │ ├── [...nextauth]/ # Auth.js v5 核心端点(session / providers / csrf / callback / signout)
│ │ │ ├── captcha-config/ # 当前启用人机验证类型与站点 key
│ │ │ ├── me/ # 当前登录用户信息
│ │ │ ├── oauth-providers/ # 前端渲染已启用 OAuth 按钮
│ │ │ ├── password/ # 修改密码
│ │ │ ├── password/forgot/ # 忘记密码
│ │ │ ├── password/reset/ # 重置密码
│ │ │ ├── register/ # 用户注册
│ │ │ └── verify-email/ # 邮箱验证回调
│ │ ├── posts/ # 帖子 API(列表 / 发布 / 详情 / 评论 / 点赞)
│ │ ├── reports/ # 举报提交
│ │ ├── upload/sign/ # R2 预签名上传 URL
│ │ └── users/me/ # 当前用户资料与会话列表
│ ├── forgot-password/page.tsx # 忘记密码页
│ ├── login/page.tsx # 登录页
│ ├── post/[id]/page.tsx # 帖子详情页
│ ├── profile/page.tsx # 个人资料页
│ ├── publish/page.tsx # 投稿页
│ ├── register/page.tsx # 注册页
│ ├── reset-password/page.tsx # 重置密码页
│ ├── verify-email/page.tsx # 邮箱验证页
│ ├── globals.css # 全局样式
│ ├── layout.tsx # 根布局
│ └── page.tsx # 首页
├── components/ # React 组件
│ ├── auth/ # 认证相关组件
│ │ ├── auth-shell.tsx # 登录/注册页面外壳
│ │ ├── captcha.tsx # 统一人机验证组件(Turnstile / Geetest)
│ │ ├── forgot-password-form.tsx
│ │ ├── login-form.tsx # 登录表单(密码 / OAuth)
│ │ ├── oauth-buttons.tsx # OAuth 登录按钮
│ │ ├── profile-form.tsx # 个人资料编辑
│ │ ├── register-form.tsx # 注册表单
│ │ ├── reset-password-form.tsx
│ │ ├── turnstile.tsx # Cloudflare Turnstile 包装
│ │ ├── user-menu.tsx # 顶部用户下拉菜单
│ │ └── verify-email-form.tsx
│ ├── admin-captcha-settings.tsx
│ ├── admin-dashboard.tsx # 管理后台总控
│ ├── admin-site-settings.tsx # SMTP / OAuth 配置面板
│ ├── admin-users-panel.tsx # 用户管理面板
│ ├── announcement-sidebar.tsx # 侧边公告栏
│ ├── category-nav.tsx # 分类导航
│ ├── detail-client.tsx # 帖子详情客户端交互
│ ├── home-feed.tsx # 首页帖子流
│ ├── home-section.tsx # 首页区块
│ ├── post-card.tsx # 帖子卡片
│ ├── publish-form.tsx # 投稿表单(含匿名选项)
│ ├── rich-text-editor.tsx # 富文本编辑器
│ └── ui.tsx # 通用 UI 组件
├── lib/ # 业务逻辑与工具
│ ├── auth/ # Auth.js v5 配置与适配器
│ │ ├── config.ts # Edge-safe 配置、JWT / session / 路由保护回调
│ │ ├── adapter.ts # 自定义数据库适配器(Web Crypto,兼容 Edge)
│ │ ├── index.ts # Auth.js 主入口:handlers / auth / signIn / signOut + 兼容工具
│ │ ├── password-provider.ts # Credentials Provider(邮箱/用户名 + 密码)
│ │ └── resend.ts # 邮件发送封装(Resend / dev 控制台输出)
│ ├── auth-validators.ts # 账号相关 Zod-like 校验
│ ├── captcha.ts # 统一人机验证抽象层
│ ├── db.ts # Neon SQL 连接与 demo 降级
│ ├── demo-data.ts # demo 示例数据
│ ├── geetest.ts # 极验 Geetest v4 服务端校验
│ ├── moderation.ts # 敏感词 / IP / 别名 / IP 解析
│ ├── passwords.ts # scrypt 密码哈希与校验
│ ├── permissions.ts # RBAC 角色与权限
│ ├── posts.ts # 帖子数据访问层
│ ├── r2.ts # R2/S3 预签名上传
│ ├── rate-limit.ts # 滑窗速率限制
│ ├── sanitize.ts # XSS 过滤与纯文本提取
│ ├── site-settings.ts # 站点配置读写与缓存
│ ├── turnstile.ts # Cloudflare Turnstile 校验
│ ├── types.ts # TypeScript 类型定义
│ ├── users.ts # 用户数据访问层
│ └── validators.ts # 通用表单校验 schema
├── scripts/
│ ├── smoke-test.mjs # 端到端与单元冒烟测试(约 113 项)
│ ├── auth-http-test.mjs # 运行中 dev server 的 Auth.js HTTP 集成测试
│ └── migrate-to-authjs.mjs # 旧版自研鉴权 → Auth.js v5 迁移脚本
├── supabase/
│ └── schema.sql # 完整数据库 Schema
├── docs/
│ └── deployment.md # 开发 / 预发布 / 生产部署指南
├── middleware.ts # 全局路由守卫(登录态 / 认证页重定向)
├── next.config.mjs # Next.js 配置
├── package.json # 依赖与脚本
├── tailwind.config.ts # Tailwind 配置
├── tsconfig.json # TypeScript 配置
├── eslint.config.mjs # ESLint 配置
├── postcss.config.mjs # PostCSS 配置
├── .env.example # 环境变量示例
├── .gitignore
└── README.md
| 文件 | 用途 |
|---|---|
app/layout.tsx |
根布局,注入全局字体与样式。 |
app/page.tsx |
首页,渲染分类导航与帖子流。 |
app/publish/page.tsx |
投稿页面。 |
app/post/[id]/page.tsx |
帖子详情与评论区。 |
app/admin/page.tsx |
管理后台,需 ADMIN_TOKEN 或已登录管理员。 |
app/login/page.tsx |
登录页,调用 Auth.js signIn。 |
app/register/page.tsx |
注册页。 |
app/profile/page.tsx |
已登录用户个人资料管理(受 middleware 保护)。 |
app/forgot-password/page.tsx |
忘记密码,发送重置链接。 |
app/reset-password/page.tsx |
通过 token 重置密码。 |
app/verify-email/page.tsx |
邮箱验证回调页。 |
| 文件 | 用途 |
|---|---|
app/api/auth/[...nextauth]/route.ts |
Auth.js v5 核心 catch-all 路由:session、providers、CSRF、credentials callback、signout。 |
app/api/auth/register/route.ts |
用户注册,含人机验证与初始邮箱验证邮件。 |
app/api/auth/password/route.ts |
修改密码。 |
app/api/auth/password/forgot/route.ts |
发送密码重置邮件。 |
app/api/auth/password/reset/route.ts |
校验 token 并重置密码。 |
app/api/auth/verify-email/route.ts |
邮箱验证链接校验。 |
app/api/auth/me/route.ts |
当前登录用户信息。 |
app/api/auth/oauth-providers/route.ts |
返回已启用的 OAuth Provider 列表。 |
app/api/auth/captcha-config/route.ts |
返回当前人机验证配置。 |
app/api/posts/route.ts |
帖子列表(GET)与发布(POST),含敏感词拦截、昵称唯一性校验、登录用户关联。 |
app/api/posts/[id]/route.ts |
帖子详情 / 更新 / 删除。 |
app/api/posts/[id]/comments/route.ts |
评论列表与提交。 |
app/api/posts/[id]/like/route.ts |
点赞。 |
app/api/admin/users/route.ts |
用户分页列表 / 修改角色与状态。 |
app/api/admin/captcha/route.ts |
人机验证配置读写。 |
app/api/admin/site-settings/route.ts |
SMTP / OAuth 等加密站点配置读写。 |
app/api/admin/site-settings/test/route.ts |
配置连通性测试(如 SMTP)。 |
app/api/admin/settings/route.ts |
moderation 基础配置。 |
app/api/admin/posts/[id]/route.ts |
审核 / 编辑 / 删除帖子。 |
app/api/admin/pending/route.ts |
待审核列表。 |
app/api/admin/published/route.ts |
已发布列表。 |
app/api/admin/reports/route.ts |
举报列表与关闭。 |
app/api/admin/categories/route.ts |
分类 CRUD。 |
app/api/admin/announcement/route.ts |
公告编辑。 |
app/api/admin/logs/route.ts |
操作日志。 |
app/api/admin/search/route.ts |
管理员搜索帖子。 |
app/api/upload/sign/route.ts |
签发 R2 预签名上传 URL。 |
app/api/users/me/route.ts |
当前用户资料更新。 |
app/api/users/me/sessions/route.ts |
当前用户会话列表。 |
| 文件 | 用途 |
|---|---|
lib/auth/config.ts |
Edge-safe Auth.js 配置、JWT/session 回调、路由保护 authorized 回调。 |
lib/auth/adapter.ts |
自定义数据库适配器,使用 Web Crypto 兼容 Edge Runtime。 |
lib/auth/index.ts |
Auth.js 主入口(handlers / auth / signIn / signOut)及兼容工具(getCurrentUser / requireUser / isAdminRequest 等)。 |
lib/auth/password-provider.ts |
Credentials Provider,支持邮箱或用户名 + 密码登录。 |
lib/auth/resend.ts |
邮件发送:Resend 真实发送 / dev 模式控制台输出。 |
lib/users.ts |
用户 CRUD、getUserById、listUsers、countUsers。 |
lib/passwords.ts |
scrypt 哈希与密码校验。 |
lib/permissions.ts |
RBAC 角色等级与权限矩阵。 |
lib/moderation.ts |
敏感词、IP、别名拦截与 IP 解析。 |
lib/captcha.ts |
统一人机验证:配置读取、Turnstile / Geetest 分发。 |
lib/turnstile.ts |
Cloudflare Turnstile 服务端校验。 |
lib/geetest.ts |
极验 Geetest v4 服务端校验。 |
lib/site-settings.ts |
站点设置缓存读写,敏感值加密存储。 |
lib/posts.ts |
帖子数据层与搜索/列表/审核。 |
lib/sanitize.ts |
富文本 XSS 过滤与纯文本提取。 |
lib/rate-limit.ts |
滑窗速率限制。 |
lib/r2.ts |
R2/S3 预签名上传。 |
lib/db.ts |
Neon 连接封装与无数据库时的 demo 降级。 |
lib/demo-data.ts |
内存模式示例数据。 |
lib/types.ts |
全项目 TypeScript 类型。 |
lib/validators.ts |
通用表单 schema。 |
lib/auth-validators.ts |
账号表单 schema。 |
| 文件 | 用途 |
|---|---|
components/admin-dashboard.tsx |
管理后台标签页总控。 |
components/admin-users-panel.tsx |
用户管理表格。 |
components/admin-site-settings.tsx |
SMTP / OAuth 配置 UI。 |
components/admin-captcha-settings.tsx |
人机验证配置 UI。 |
components/publish-form.tsx |
投稿表单,登录用户可切换匿名。 |
components/auth/login-form.tsx |
登录表单(密码 / OAuth)。 |
components/auth/register-form.tsx |
注册表单。 |
components/auth/captcha.tsx |
根据后端配置渲染 Turnstile 或 Geetest。 |
components/auth/oauth-buttons.tsx |
第三方登录按钮。 |
components/auth/profile-form.tsx |
个人资料编辑。 |
components/auth/user-menu.tsx |
顶部用户菜单,调用 Auth.js signOut。 |
components/home-feed.tsx / home-section.tsx / post-card.tsx |
首页帖子流与卡片。 |
components/detail-client.tsx |
帖子详情互动。 |
components/rich-text-editor.tsx |
富文本编辑器。 |
| 文件 | 用途 |
|---|---|
middleware.ts |
Edge-safe 路由守卫:未登录访问 /profile 重定向到 /login;已登录访问 /login 等跳回首页。 |
scripts/smoke-test.mjs |
约 113 项端到端与单元冒烟测试。 |
scripts/auth-http-test.mjs |
针对运行中 dev server 的 Auth.js HTTP 集成测试。 |
scripts/migrate-to-authjs.mjs |
旧表 → Auth.js v5 表结构迁移脚本(保留 users 数据)。 |
supabase/schema.sql |
完整 PostgreSQL schema。 |
docs/deployment.md |
开发 / 预发布 / 生产部署指南。 |
npm run dev # 开发服务器(Turbopack)
npm run build # 生产构建
npm run lint # ESLint 检查
npm run typecheck # TypeScript 类型检查
npm test # 运行 smoke tests(不依赖 dev server)
node scripts/auth-http-test.mjs # HTTP 集成测试(需要先运行 npm run dev)最简部署:推送代码到 GitHub → 在 Vercel 导入项目 → 配置环境变量 → 初始化 Neon 数据库 → Build。
详细步骤(含 staging / production / 故障排查)请查看 部署指南。
- 生产环境必须设置
AUTH_SECRET、ADMIN_TOKEN、DATABASE_URL、RESEND_API_KEY、EMAIL_FROM。 - 本项目使用 Auth.js v5 JWT session strategy;Credentials Provider 不支持 database strategy,因此 session cookie 内为签名 JWT,服务端通过
auth()读取。 middleware.ts仅导入 Edge-safe 的authConfig,不可引入lib/auth/index.ts中的 Node.js runtime 依赖(如password-provider/adapter中的node:crypto)。- 图片上传默认使用 Cloudflare R2;如需其他存储,可替换
lib/r2.ts与app/api/upload/sign/route.ts。 - 人机验证在开发环境未配置密钥时会自动放行,方便本地调试;生产务必配置并启用。
- OAuth Client Secret、SMTP 密码等建议在「管理后台 → 站点配置」中维护,会加密写入数据库;环境变量仅作为兜底。
- 旧环境变量
SESSION_SECRET已废弃,统一由AUTH_SECRET取代。