Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

墨痕 Mohen

一个开箱即用、可自托管的开源个人博客框架。基于 Next.js 15 App Router,文章存数据库、后台可视化写作、内容可一键导出为标准 Markdown——你随时可以带走全部内容。

git clone <your-fork-url> my-blog && cd my-blog
cp .env.example .env          # 改 DATABASE_URL / AUTH_SECRET / ADMIN_PASSWORD
npm install
npm run db:push              # 建表(SQLite 零配置)
npm run db:seed              # 可选:写入示例文章
npm run dev                  # http://localhost:3000

后台入口在页脚版权行的「管理」链接,或直达 /admin/login。


为什么是它

说明
数据库为单一内容源 文章、分类、标签、评论、订阅者、访问日志全在数据库里。写作不需要 commit,换设备不需要 clone。
内容不被锁定 后台一键导出全站为带 YAML frontmatter 的 Markdown,Hugo / Jekyll / Hexo 可直接读取;同样支持批量导入。
零第三方依赖的互动 评论、点赞、收藏、订阅、阅读量全部自建,不依赖 Giscus / Disqus / 任何 SaaS。
一个配置文件 站点名称、导航、作者、赞赏位、功能开关全部集中在根目录 site.config.ts,改完即热更新。
LLM 友好 内置 /llms.txt 与 /llms-full.txt,遵循 llmstxt.org 规范。
可观测 后台「访问管理」页查看访问日志、按 IP 封禁,封禁在 middleware 层生效。

技术栈

Next.js 15(App Router · RSC)· React 19 · TypeScript · Tailwind CSS 4 · Prisma · Auth.js v5 · MDX(shiki 高亮)· KaTeX · FlexSearch · Zod · Vitest

快速开始

环境要求

Node.js ≥ 20 · npm ≥ 10

1. 安装与配置

npm install
cp .env.example .env

必填项:

变量 说明
DATABASE_URL 本地默认 file:./dev.db(SQLite,零配置)。生产改用 PostgreSQL 连接串,并同步把 prisma/schema.prisma 的 provider 改为 postgresql。
AUTH_SECRET Auth.js 会话密钥,openssl rand -base64 32 生成。
ADMIN_EMAIL / ADMIN_PASSWORD 后台登录凭证。密码支持明文或 bcrypt 哈希($2 开头)。

可选项(不配则对应功能自动降级,不会报错):

变量 作用
NEXT_PUBLIC_SITE_URL 站点根地址。生产必须设置,影响 RSS / Sitemap / OG 图。
NEXT_PUBLIC_SITE_NAME、NEXT_PUBLIC_SITE_DESCRIPTION 覆盖 site.config.ts 中的同名字段。
SMTP_HOST/PORT/USER/PASS/FROM 邮件通知(订阅确认 / 评论通知 / 新文章推送)。缺任一则不发信。
MEDIA_LOCAL_DIR 媒体本地存储目录。留空走默认 <项目根>/data/uploads,Docker 下与 SQLite 共享 ./data 卷

完整列表见 .env.example。环境变量在 lib/env.ts 用 Zod 惰性校验,缺失时给出可执行的修复提示,而不是让程序在运行时行为异常。

2. 初始化数据库

npm run db:push    # 开发:直接把 schema 推到数据库
npm run db:seed    # 可选:写入 4 篇示例文章

生产环境建议改用迁移:npm run db:migrate。

3. 启动

npm run dev

4. 改成你自己的博客

编辑根目录 site.config.ts——这是整个框架里唯一需要你改的文件:站点名称、短名、描述、语言、作者资料、顶部导航、每页条数、赞赏二维码、功能开关。

功能开关(features)关闭后,对应模块在前台完全不渲染,不留下空的 UI 骨架:

features: {
  comments: true,   // 评论 + 楼中楼回复
  subscribe: true,  // 邮件订阅
  reactions: true,  // 点赞 / 收藏
  search: true,     // 全文搜索
  rss: true,        // /rss.xml
  llmsTxt: true,    // /llms.txt 与 /llms-full.txt
  accessLog: true,  // 访问日志(高流量站点可关闭以减轻数据库压力)
}

头像、赞赏码等静态资源放在 public/ 下。

功能一览

内容:Markdown/MDX 写作(GFM、数学公式 KaTeX、代码高亮 shiki、callout 指令)、草稿/发布、定时发布、分类、标签、归档、全文搜索(中文 bigram 分词)、相关文章、上下篇导航、阅读时长、目录(TOC)。

互动:评论与楼中楼回复、后台审核、点赞、收藏、邮件订阅(含确认与退订)。

后台:文章增删改查、实时预览(编辑/预览/分屏三模式)、Markdown 导入导出、草稿分享链接(带随机令牌,可轮换撤销)、友链管理、语录管理、订阅者管理、访问日志与 IP 封禁。

SEO / 分发:每篇文章动态生成 OG 图、sitemap.xml、robots.txt、RSS、llms.txt / llms-full.txt、规范链接、结构化元信息。草稿预览页自动标记 noindex。

内容导入导出

后台「文章」页的工具栏提供两个按钮:

  • 导出:全站文章打包成单个 .md 备份文件(<!-- blog-export: slug --> 分隔),可直接喂给任何静态博客生成器。
  • 导入:上传 .md 或 .zip,按 slug 覆盖或跳过,返回逐篇的导入结果与告警。

底层实现在 lib/post-io.ts,往返转换有完整测试覆盖。

命令

命令 说明
npm run dev 开发服务器
npm run build / npm start 生产构建 / 启动
npm run lint ESLint
npm run typecheck tsc --noEmit
npm test Vitest 单元测试(135 项,覆盖内容转换/搜索/限流/反垃圾/版本快照/配置等纯函数)
npm run lighthouse 桌面+移动 × 首页+文章页 性能审计(需先 npm run build && npm run start)
npm run test:watch 测试 watch 模式
npm run db:push 把 schema 推到数据库(开发)
npm run db:migrate 创建并应用迁移(生产)
npm run db:generate 重新生成 Prisma Client
npm run db:seed 写入示例数据

目录结构

.
├── site.config.ts      # 站点唯一配置文件(改这里)
├── app/
│   ├── (前台页面)       # 首页 / 博客 / 分类 / 标签 / 归档 / 搜索 / 关于 / 友链
│   ├── admin/          # 后台:文章、评论、订阅者、友链、语录、访问管理
│   ├── api/            # 评论、点赞、收藏、订阅、浏览量、导入导出、分享令牌、安全校验、健康检查
│   ├── preview/[slug]/ # 草稿预览(令牌访问,noindex)
│   ├── rss.xml/ llms.txt/ llms-full.txt/
│   ├── sitemap.ts  robots.ts
│   └── blog/[id]/opengraph-image.tsx   # 动态 OG 图(路径用 cuid id 锚定;旧 /blog/[slug] 自动 308 重定向)
├── components/         # UI 组件(含 admin/ 后台组件)
├── lib/                # 领域逻辑
│   ├── content.ts      # 文章查询层
│   ├── post-io.ts      # Markdown 导入导出
│   ├── search.ts       # FlexSearch + 中文分词
│   ├── env.ts          # Zod 环境变量校验
│   ├── rate-limit.ts   # 滑动窗口限流
│   ├── mail.ts         # SMTP 邮件
│   └── site-config.ts  # 配置聚合(不要直接改,改 site.config.ts)
├── prisma/
│   ├── schema.prisma   # 数据模型(SQLite / PostgreSQL 双支持)
│   └── seed.ts
├── tests/              # Vitest 单元测试
└── docs/               # 设计文档

部署

  • Docker:docker compose up -d --build(默认内置 SQLite,数据持久化到 ./data;切换到 PostgreSQL 的方法见 docker-compose.yml 注释)。
  • Vercel / Node 平台:设置环境变量后 npm run build && npm start。

部署前务必设置 NEXT_PUBLIC_SITE_URL 为真实域名,否则 RSS、Sitemap、OG 图里的链接会指向 localhost。完整步骤见 DEPLOY.md。

⚠️ 开发期间不要运行 npm run build——构建与 dev server 共用 .next 目录,会导致缓存损坏。开发期用 npm run typecheck 验证;全量构建请先停掉 dev server。

安全

  • 后台由 middleware 守卫(Auth.js),未登录访问 /admin/* 跳转登录页。
  • 登录失败 5 次锁定 15 分钟。
  • 评论、订阅等写接口按 IP 滑动窗口限流(lib/rate-limit.ts,单实例内存实现;多实例部署请替换为 Redis)。
  • IP 封禁在 middleware 层生效,命中直接返回 403。
  • 密码支持 bcrypt 哈希存储。

已知限制

  • 限流与登录锁定为单实例内存实现,多副本部署需换成 Redis 等共享存储。
  • 图片使用原生 <img>(关闭了 next/image 优化),以规避远程图源白名单配置。
  • 文章正文以 Markdown 存入数据库,未做版本历史。

贡献

欢迎提交 Issue 与 PR,请先阅读 CONTRIBUTING.md。提交代码前请确保 npm run typecheck && npm test && npm run lint 全部通过。

许可

MIT

About

墨痕 Mohen —— 开箱即用、可自托管的开源个人博客框架,基于 Next.js 15 App Router

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages