Next.jsReact博客

nextjs-blog-template — Next.js 博客模板

作者 wanrenhuifu

一个基于 Next.js App Router 的中文静态博客模板,支持静态导出、双主题、MDX 写作与构建期全文搜索,不配置环境变量也能构建。

看看你的网站会是什么样

浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。

3 个预览视图
桌面端首页1 / 3
桌面端截图首屏预览

由服务器浏览器实际访问页面后截取。

全部页面与视图 3

截图用于了解视觉与布局,交互效果请以实际项目为准。

采集于 2026-10-14查看来源

值得关注的模板亮点

从已有项目资料中,快速了解它的特点。

01

静态导出:output: "export",产物为纯 HTML/CSS/JS,可部署到任意静态空间

02

双主题:日间竹林(宣纸米白配朱红)与夜间星月(近黑中性底配暖金星辉),按本地时间自动切换,也可手动切换

03

MDX 写作:支持 GFM 表格、KaTeX 公式、Shiki 代码高亮、自动目录与阅读时间

04

构建期生成全文搜索索引,前端做大小写不敏感子串匹配,Ctrl/Cmd + K 唤起

05

站点身份集中在 site.config.mjs,页面标题、SEO meta、RSS、sitemap、页头页脚统一取值

06

自带 GitHub Pages 部署工作流,推送 main 自动构建发布,站点地址与 basePath 自动推导

模板详细介绍

该模板面向中文个人博客,使用 Next.js App Router 并配置为静态导出(output: "export"),构建产物为纯 HTML/CSS/JS,可托管在任意静态空间。内容以 MDX 编写,每篇文章对应 content/blog/<slug>/index.mdx,支持 GFM 表格、KaTeX 公式、Shiki 代码高亮、自动目录与阅读时间。模板提供日间「竹林」与夜间「星月」两套主题,按访问者本地时间自动切换,也可手动切换。搜索索引在构建期生成,前端做大小写不敏感的子串匹配,通过 Ctrl/Cmd + K 唤起。站点身份集中在 site.config.mjs,页面标题、SEO meta、RSS、sitemap、页头页脚等均从该文件取值。README 说明模板开箱即可构建,不配置任何环境变量也能成功构建,但建议填写 NEXT_PUBLIC_SITE_URL 以避免 canonical、sitemap、RSS 指向默认的 https://example.com。评论功能依赖自建 Waline 后端,未配置时评论区显示提示;友链头像可通过脚本从 GitHub 下载,否则回退为名称首字母。README 还记录了 Windows 本地构建后预览时出现一批 404 的已知差异,并说明该问题仅影响客户端预取,不影响导航功能。

Next.js博客

适合你的项目吗?

适用场景

  • 搭建个人中文技术博客或生活记录站点
  • 需要静态托管、不依赖服务端运行时的博客部署
  • 希望用 MDX 写作并保留公式、代码高亮、目录等排版能力
  • 需要按标签、类型、年份聚合浏览文章
  • 希望集成可选评论与友链页面的个人站点

适合人群

  • 使用 Next.js App Router 并希望静态导出的博客作者
  • 偏好 MDX 写作、需要公式与代码高亮的中文内容创作者
  • 计划部署到 GitHub Pages、Cloudflare Pages、Netlify、Vercel 或对象存储的用户
  • 需要双主题、全文搜索与 SEO 基础能力(RSS、sitemap、robots、Open Graph、JSON-LD)的站点

上手与定制指南

结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。

  1. 1

    需要 Node ≥ 20.19(见 package.json 的 engines)。

  2. 2

    npm install 后 npm run dev 启动开发服务器;npm run build 生成静态产物到 out/。

  3. 3

    站点身份在 site.config.mjs 中修改;站点地址需复制 .env.example 为 .env.local 并至少填写 NEXT_PUBLIC_SITE_URL。

  4. 4

    改站名后必须重跑 npm run og 重新生成分享图,否则图片上仍是旧站名;图标可用 npm run icons 重新生成。

  5. 5

    部署到 GitHub Pages 前需在 Actions 标签页启用 Actions,并在 Settings → Pages 将 Source 设为 "GitHub Actions";项目页部署需同时正确设置 NEXT_PUBLIC_SITE_URL 与 NEXT_PUBLIC_BASE_PATH。

查看仓库使用说明

授权与来源资料

使用条件与限制

免费使用 · 保留许可声明

本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。

使用时需要遵守

  • 允许免费使用、修改、商用和分发该版本代码。
  • 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
  • 代码按现状提供;担保与责任限制以原许可证及适用法律为准。

额外费用与待核对事项

  • 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
  • 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
  • 评论功能依赖自建 Waline 后端,需要自行部署,未配置时评论区仅显示未配置提示。
  • 未设置 NEXT_PUBLIC_WALINE_SERVER_URL 时评论区显示「评论系统未配置」,评论不可用。
  • 评论需自建 Waline 后端(可部署在 Vercel + Supabase 免费层),不配置时评论区显示未配置提示。
  • 部署到 GitHub Pages 时,需在仓库 Secrets 中创建名为 WALINE_SERVER_URL 的 secret 才能让评论生效。
  • 未填写 NEXT_PUBLIC_SITE_URL 时,canonical/sitemap/RSS/JSON-LD 会回退到 https://example.com 并打印构建警告。
  • 子路径部署(项目页)需要设置 NEXT_PUBLIC_BASE_PATH,否则资源路径错误。
  • 项目页部署时漏设 BASE_PATH 会导致整站白屏,两个变量不一致会使 canonical/sitemap 链接指向错误位置。
  • 新增代码引用 public/ 下资源时须用 publicUrl() 包裹,否则子路径部署下会静默 404。
  • 只有同时设置 SITE_URL 时 BASE_PATH 才会被读取,只设 BASE_PATH 会被静默忽略。
  • 构建产物使用 trailingSlash: true,托管方需正确处理目录级 URL。
  • 友链头像需运行 npm run avatars 从 GitHub 下载,否则头像位回退为名称首字母。
  • 构建时会 ping 一次 Waline 后端以避免免费层数据库约 7 天无活动被暂停,失败只打印警告不阻断构建。
  • Windows 上本地构建后预览时控制台会出现一批 404(RSC 载荷文件名差异),仅影响客户端预取。
  • 改站名后必须重跑 npm run og 重新生成分享图,否则图片上仍是旧站名。
  • fork 出来的仓库默认不启用 Actions,需到 Actions 标签页手动启用,否则推送后不会产生 workflow 运行。
查看原文依据

Permission is hereby granted, free of charge

许可证原文

| 评论 | Waline,自建后端 | 需自建 |

README 原文

| `NEXT_PUBLIC_WALINE_SERVER_URL` | Waline 评论后端地址 | 评论区显示「评论系统未配置」 |

README 原文

| 评论 | 自建 [Waline](https://waline.js.org/) 后端(可部署在 Vercel + Supabase 免费层) | 评论区显示未配置提示 |

README 原文

> 部署到 GitHub Pages 时,让评论生效需要在仓库 Secrets 里创建名为

README 原文

| `NEXT_PUBLIC_SITE_URL` | 站点根地址,用于 canonical / sitemap / RSS / JSON-LD | 回退到 `https://example.com` 并打印构建警告 |

README 原文

| `NEXT_PUBLIC_BASE_PATH` | 子路径前缀,仅项目页部署需要 | 视为部署在根路径 |

README 原文

> 漏了 `BASE_PATH` 会**整站白屏**(CSS/JS 去根路径找)。两个值不一致则会让

README 原文

> **新增代码时若引用 `public/` 下的资源,请同样用它包一层**,否则子路径部署下会静默 404。

README 原文

> 只有同时设置了 `SITE_URL` 时 `BASE_PATH` 才会被读取;只设 `BASE_PATH` 会被静默忽略。

README 原文

对象存储等。注意 `trailingSlash: true`,托管方需正确处理目录级 URL。

README 原文

| 友链头像 | 无 —— `npm run avatars` 从 GitHub 下载 | 头像位回退为名称首字母 |

README 原文

`scripts/keepalive-waline.mjs` 会在构建时 ping 一次 Waline 后端,避免免费层数据库

README 原文

**在 Windows 上 `npm run build` 后本地预览时,控制台会出现一批 404**

README 原文

npm run og # → public/og-default.png(改站名后必须重跑)

README 原文

1. fork 出来的仓库默认**不启用 Actions** —— 到 Actions 标签页点一下启用

README 原文
https://github.com/wanrenhuifu/nextjs-blog-template/blob/main/LICENSEhttps://github.com/wanrenhuifu/nextjs-blog-template/blob/main/README.md

DeepSeek 根据仓库许可证和 README 整理 ·2026-10-14。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。

项目核对记录与介绍依据

模板资料

来源平台
GitHub
资料与维护参考分
资料较完整 · 83 / 100
技术栈
Next.js · React
网站类型
博客
这个分数如何计算

本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。

这个项目需要核对什么

记录的仓库更新时间
2026-09-15
截图检查日期
2026-10-14

已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。

目录记录的主要技术栈是 Next.js。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。

查看具体选型方法 →

介绍的制作与核对状态

介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。

审核声明: codex-user-requested-batch-review-20261017 · 2026-10-16

查看当时使用的来源资料

SHA-256: c079a84daad12aeaa64fd8fd2d251618afb18a0f60558f10b42581d3fb4cf60b

2026-10-14T21:07:24.735Z

来源文件 / 仓库
# Next.js 静态博客模板

[English](./README.en.md) · **中文**

[![Next.js](https://img.shields.io/badge/Next.js-16.2.6-black?logo=next.js)](https://nextjs.org)
[![React](https://img.shields.io/badge/React-19.2.4-087ea4?logo=react)](https://react.dev)
[![Tailwind](https://img.shields.io/badge/Tailwind-v4-38bdf8?logo=tailwindcss)](https://tailwindcss.com)
[![License](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)

一个可以直接拿来用的中文个人博客框架:静态导出、双主题、MDX 写作、全文搜索,外加工坊小工具。
**开箱即可构建** —— 不配任何环境变量也能跑起来。

> **在线示例** —— [wanrenhuifu.github.io](https://wanrenhuifu.github.io) 是这个框架的线上形态。
> 它是本站的「完整版」:除了模板自带的内容,还额外写了文章、加了雷达(AI 模型排行 + 天气预警)
> 与更多工具。模板本体只保留一个示例工具,其余按需自取。

- **日间主题**:竹林风 — 宣纸米白底色(`#FAFAF8`)配朱红主色(`#C43A1B`)
- **夜间主题**:星月夜 — 近黑中性底(`#0A0A0D`)配暖金星辉与提亮朱红;蓝色只出现在夜空辉光层,底色本身保持中性
- 主题按访问者的**本地时间**自动切换(06:00–17:59 为日间),也可手动切换

## 功能

| 功能 | 说明 | 是否需要额外配置 |
|------|------|------------------|
| 静态导出 | `output: "export"`,产物是纯 HTML/CSS/JS,可托管在任何静态空间 | — |
| 双主题 | 日间竹林 / 夜间星月,CSS 变量驱动,无闪白 | — |
| MDX 写作 | GFM 表格、KaTeX 公式、Shiki 代码高亮、自动目录、阅读时间 | — |
| 全文搜索 | 构建期生成索引,前端做大小写不敏感的子串匹配,`Ctrl/Cmd + K` 唤起 | — |
| 三种聚合视图 | 按标签、按类型、按年份归档 | — |
| SEO | RSS、sitemap、robots、Open Graph、JSON-LD 结构化数据 | 建议填站点地址 |
| 分享图 / 图标 | 脚本生成 OG 图与图标,改站名后重跑即可换品牌 | — |
| 工坊 | 一个示例工具(随机数生成器),纯前端、不上传数据;按同一形状可自行添加 | — |
| 评论 | Waline,自建后端 | 需自建 |
| 友链 | 卡片列表 + 申请说明 | — |
| 小彩蛋 | 右下角竹苗随访问次数成长;切走标签页时标题变化 | — |

## 快速开始

需要 **Node ≥ 20.19**(见 `package.json` 的 `engines`)。

```bash
npm install
npm run dev          # → http://localhost:3000
```

构建静态产物到 `out/`:

```bash
npm run build
```

其它命令:

```bash
npm run build:verify # 只构建、不跑构建链上的其它步骤,本地快速验证用
npm start            # 本地预览 out/(等价于 npx serve out)
npm run lint         # ESLint
npx tsc --noEmit     # 类型检查
npm test             # 单元测试(vitest)
```

> `npm run dev` 会先经 `predev` 生成搜索索引,所以开发模式下搜索可以直接用;
> 索引本身是构建产物、不入库(见 `.gitignore`)。

## 改成你自己的

按顺序做完这几步,站点就是你的了。

### 1. 站点身份 —— 改 `site.config.mjs`

站名、作者、标语、简介、语言 locale、GitHub 用户名都在这一个文件里。
页面标题、SEO meta、RSS、sitemap、页头页脚、首页标题、友链页的「本站信息」
全部从它取值,改一处即可全站生效。

```js
export const siteConfig = {
  name: "示例博客",           // → 页面标题、页头页脚、首页大标题
  tagline: "记录技术、思考与生活",  // → 首页副标题、分享图标题行
  description: "一个记录技术、思考与生活的个人博客。",  // → meta description、友链页「本站信息」
  author: "示例博主",         // → meta 的 author/creator、文章页 JSON-LD
  github: "",                // → 留空则页脚与 about 页的 GitHub 入口自动隐藏
  // …
};
```

> 首页的大标题是**逐字动画**,字数不限 —— 它按 `Array.from(site.name)` 驱动,不必是四个字。
>
> 注意 `author` 只影响 meta 与结构化数据,**页面上没有可见的作者署名**。

### 2. 站点地址 —— 复制 `.env.example` 为 `.env.local`

```bash
cp .env.example .env.local
```

至少要填 `NEXT_PUBLIC_SITE_URL`。不填也能构建,但 canonical / sitemap / RSS
会指向 `https://example.com`(构建期会打印一条警告提醒你)。

### 3. 品牌图 —— 重跑生成脚本

```bash
npm run og     # → public/og-default.png(改站名后必须重跑)
npm run icons  # → public/favicon.svg + apple-touch-icon.png(图标不含文字,通常不用重跑)
```

**站名是烧进 PNG 像素的** —— 改了 `site.config.mjs` 之后不重跑 `npm run og`,
分享图上的还是旧站名。这是最容易漏的一步:其它地方的站名会自动更新,只有图片不会。

脚本与 `next build` 一样会读 `.env.local`(经 `scripts/load-env.mjs`),所以配好之后
直接 `npm run og` 即可。CI 等场景下传入的真实环境变量优先级更高,不会被仓库里的文件覆盖。

### 4. 内容

- 删掉 `content/blog/hello-world/`,或者把它改成你的第一篇。
- 保留 `content/blog/syntax-test/`:它覆盖了全部 Markdown/MDX 渲染路径,
  升级依赖后能一眼看出哪条路径坏了。详见 `content/AGENTS.md`。
- 文章配图放 `public/blog/<slug>/`,正文用绝对路径引用。

### 5. 其余可选项

| 要改什么 | 改哪里 |
|----------|--------|
| 友链 | `data/friends.json`(3 条占位数据待替换) |
| 工坊里的工具 | `lib/tools.ts` |
| 「关于」页 | `app/about/page.tsx`(文案刻意写成通用描述,不改也能看) |
| 导航菜单 | `components/layout/nav-data.ts` |
| 站点图标 | `scripts/generate-icons.mjs` 里的墨竹几何 |
| 许可协议里的署名 | `LICENSE` 第 3 行(模板署名为 wanrenhuifu,换成你自己的名字或 ID) |

## 环境变量

全部都是**可选的** —— 一个都不配也能 `npm run build` 成功。
完整说明见 [`.env.example`](./.env.example)。

| 变量 | 作用 | 缺省行为 |
|------|------|----------|
| `NEXT_PUBLIC_SITE_URL` | 站点根地址,用于 canonical / sitemap / RSS / JSON-LD | 回退到 `https://example.com` 并打印构建警告 |
| `NEXT_PUBLIC_BASE_PATH` | 子路径前缀,仅项目页部署需要 | 视为部署在根路径 |
| `NEXT_PUBLIC_WALINE_SERVER_URL` | Waline 评论后端地址 | 评论区显示「评论系统未配置」 |

## 部署到 GitHub Pages

仓库自带 `.github/workflows/deploy.yml`,推送到 `main` 即自动构建并发布。

**首次部署前要做两件事**:

1. fork 出来的仓库默认**不启用 Actions** —— 到 Actions 标签页点一下启用
   (不启用时推送后不会产生任何 workflow 运行,也没有报错提示)
2. 到 **Settings → Pages**,把 **Source 设为 "GitHub Actions"**

第 2 步没做也不会出红叉:工作流会检测到 Pages 未启用,**跳过部署并打印一条提示**
告诉你差这一步(构建与检查照常跑完)。

站点地址与 basePath 会**自动推导**,两种情况都无需配置:

- **用户站点**(仓库名为 `<你的用户名>.github.io`)→ 地址在根,无 basePath
- **项目页**(仓库名是别的,比如 fork 出来的这个模板)→ 自动用
  `https://<用户名>.github.io/<仓库名>` 并设好 basePath

> ### ⚠️ 项目页部署的坑
>
> 如果你的站点在**子路径**下(项目页),必须让这两个变量同时正确:
>
> ```
> NEXT_PUBLIC_SITE_URL=https://<用户名>.github.io/<仓库名>
> NEXT_PUBLIC_BASE_PATH=/<仓库名>
> ```
>
> 漏了 `BASE_PATH` 会**整站白屏**(CSS/JS 去根路径找)。两个值不一致则会让
> canonical / sitemap 里的链接指向错误位置。
>
> 另外,Next.js **不会**自动改写裸字符串写法的资源引用 —— `<link href="/favicon.svg">`、
> `fetch("/search-index.json")`、正文里手写的 `<img src="/...">` 都属于这一类。
> 本项目已经把这类引用统一交给 `lib/site.ts` 的 `publicUrl()` 处理;
> **新增代码时若引用 `public/` 下的资源,请同样用它包一层**,否则子路径部署下会静默 404。
>

用自定义域名时,在仓库的 **Settings → Secrets and variables → Actions → Variables**
里设置(注意是 Variables 不是 Secrets):

- `SITE_URL`,如 `https://blog.example.com`
- `BASE_PATH`,自定义域名下通常留空

> 只有同时设置了 `SITE_URL` 时 `BASE_PATH` 才会被读取;只设 `BASE_PATH` 会被静默忽略。

### 其它静态托管

构建产物是 `out/` 目录,纯静态,可直接部署到 Cloudflare Pages、Netlify、Vercel、
对象存储等。注意 `trailingSlash: true`,托管方需正确处理目录级 URL。

## 无障碍

- 日间/夜间两套配色均满足 WCAG AA 对比度
- 全站键盘可达:跳转主内容链接、可见焦点环、44px 触摸目标
- 表单控件都有可访问名称;工具页出错时错误行带 `role="alert"`,`aria-invalid` 只标在真正出错的那个控件上
- 浮层(搜索弹窗、移动端抽屉)有 `role="dialog"` + `aria-modal`,焦点被限制在内部,关闭后归还给打开它的按钮
- `prefers-reduced-motion` 下关闭所有循环动画与入场编排,内容直出
- 脚本被禁用时:入场动画的初态由 `<noscript>` 样式接管,首屏文字与列表照常可见

## 可选功能与依赖

| 功能 | 依赖 | 不配置时 |
|------|------|----------|
| 评论 | 自建 [Waline](https://waline.js.org/) 后端(可部署在 Vercel + Supabase 免费层) | 评论区显示未配置提示 |
| 友链头像 | 无 —— `npm run avatars` 从 GitHub 下载 | 头像位回退为名称首字母 |

`scripts/keepalive-waline.mjs` 会在构建时 ping 一次 Waline 后端,避免免费层数据库
因约 7 天无活动被暂停。它是**永不阻断构建**的:任何失败只打印警告。

> 部署到 GitHub Pages 时,让评论生效需要在仓库 Secrets 里创建名为
> **`WALINE_SERVER_URL`** 的 secret(`deploy.yml` 按这个名字读取,再赋给环境变量
> `NEXT_PUBLIC_WALINE_SERVER_URL`)。

## 删掉不需要的页面

路由是文件式的,删除即下线。删完记得同步三处:

1. `app/sitemap.ts` 里的静态路由清单(否则 sitemap 会指向 404)
2. `components/layout/nav-data.ts` 的导航项
3. `app/about/page.tsx` 的模块导览,以及 `app/page.tsx` 底部的 `ENTRIES`

常被删掉的:`app/friends/`、`app/guestbook/`(需要 Waline 后端)。

## 已知差异:Windows 本地构建

**在 Windows 上 `npm run build` 后本地预览时,控制台会出现一批 404**
(形如 `/blog/__next.blog.__PAGE__.txt`)。已在 Next 16.2.6 上核实:

| 构建环境 | 产出的 RSC 载荷文件名 |
|----------|----------------------|
| Linux(含 GitHub Actions) | `__next.blog.__PAGE__.txt`(扁平文件)—— 客户端预取请求的正是这个 |
| Windows | `__next.blog/__PAGE__.txt`(目录形式) |

这些文件用于**客户端预取**。缺失的后果仅限于预取落空、点击链接时退化为整页跳转 ——
导航功能本身正常(已实测:各入口的客户端跳转均正常,只是多一次整页加载)。

**不需要处理**:仓库的部署走 GitHub Actions(`ubuntu-latest`),CI 构建产出的是扁平文件,
与预期一致。若你希望在 Windows 本地预览时也消除这批 404,用 `npm run dev` 即可。

> 这条记录于模板化时的实测。上游修好后可以删掉本节。

## 项目结构

### 代码

```
app/                    # 路由页面(App Router)
├── layout.tsx          # 根布局(元数据、主题种子脚本、Header/GlobalUI)
├── page.tsx            # 首页(Hero 3D 场景 + 纯文字文章目录)
├── blog/[slug]/        # 文章详情(SSG)
├── tags/ types/ archive/   # 三种聚合视图
├── tools/              # 工坊
├── friends/            # 友链
├── guestbook/          # 留言
├── about/              # 关于本站
└── sitemap.ts / robots.ts / rss.xml/route.ts

components/             # React 组件(按功能域分组)
├── layout/             # Header / DesktopNav / MobileDrawer / Footer / PageShell
│                       #   SearchModal / ThemeToggle / TimeThemeController
│                       #   GlobalUI / ErrorFallback / FarewellTitle / JsonLd / nav-data
├── blog/               # PostCard / PostCardSkeleton / MdxContent
│                       #   TableOfContents / WalineComments
├── home/               # HeroSection(构图与时序)/ HeroScenery(场景绘制)
├── tools/              # RandomNumber(模板自带的示例工具)
└── ui/                 # FadeUp / GlowCard / BambooSprout / CopyCodeButton
                        #   BackToTop / ScrollProgress

lib/                    # 核心业务逻辑(无 JSX、无浏览器 API)
├── content.ts          # 内容读取与处理(含正文图片尺寸读取与校验)
├── data.ts             # 统一数据层(JSON 读取 + Zod 校验 + 降级兜底)
├── site.ts             # 站点身份的出口(读 site.config.mjs,派生逐字数组等)
├── schemas.ts          # Zod 校验模式
├── types.ts            # 全局类型
├── constants.ts        # 文章分类等常量
├── mdx.ts              # MDX 编译配置(插件链)
├── readingTime.ts      # 阅读时间计算
├── timeTheme.ts        # 按本地时间切换日/夜主题
├── bamboo.ts           # 竹苗彩蛋的阶段计算
├── random.ts           # 随机数算法
├── tools.ts            # 工坊的工具配置数据
└── a11y.ts             # 可访问性工具

site.config.mjs         # ★ 站点身份的唯一来源(Node 脚本与应用共用)
```

### 内容与数据

```
content/blog/<slug>/    # MDX 文章源文件(纯文本,不含图片)
data/
└── friends.json        # 友链(唯一的数据文件,人工维护)
public/                 # 静态资源(静态导出下唯一会被服务的位置)
├── blog/<slug>/        #   文章配图 —— 约定见 public/AGENTS.md
├── cursors/            #   自定义光标(日间竹叶 / 夜间星星)
└── friends/avatars/    #   友链头像(npm run avatars 生成,不入库)
```

### 样式与脚本

```
styles/                 # 全局样式(由 app/globals.css 统一导入)
├── theme.css           #   设计令牌与双主题变量(单一来源)
├── hero-scene.css      #   Hero 场景:SVG 绘制 + CSS 3D 纵深
└── components.css / animations.css / print.css
                        #   waline.css 单独由 WalineComments 导入

scripts/                # 构建链与手动资源生成器
├── keepalive-waline.mjs / generate-search-index.mjs    # 构建链上(不阻断构建)
├── generate-og.mjs / generate-icons.mjs / fetch-avatars.mjs   # 手动按需
└── audit/              # 开发期校验工具(截图 / 性能),只手动跑
```

### 文档

除了本文件,仓库还带了几份说明,这是它相对一般模板的主要差别:

| 文件 | 内容 |
|------|------|
| `DESIGN.md` | 设计令牌与视觉规范的单一来源 |
| `CLAUDE.md` | 架构约定、编码规范、代码与文档的同步映射 |
| `app/` `components/` `lib/` `content/` `data/` `scripts/` `styles/` `public/` 下的 `AGENTS.md` | 各目录的细粒度规则与踩坑记录 |
| `test/fixtures/blog/README.md` | 测试夹具说明 |

改动代码后请同步对应文档 —— 具体映射见 `CLAUDE.md` 的「代码与文档同步」一节。

## 写作

一篇文章 = 一个目录 + 一个 `index.mdx`:

```
content/blog/my-first-post/index.mdx
```

```mdx
---
title: "文章标题"
pubDate: 2026-01-01
description: "文章摘要"
tags: ["标签1", "标签2"]
category: 随笔
tocDepth: 2
---

正文……
```

全部 frontmatter 字段、配图约定与排版规范见 [`content/AGENTS.md`](./content/AGENTS.md)。

## 技术栈

| 层级 | 技术 |
|------|------|
| 框架 | Next.js 16.2.6(App Router,静态导出) |
| 运行时 | React 19.2.4 |
| 样式 | Tailwind CSS v4(CSS 优先,无 `tailwind.config.js`)+ `@tailwindcss/typography` |
| 字体 | 全部走系统字体栈,不加载网络字体(中文 webfont 体积代价过高,实测移除后 LCP 从 5.5s 降到 1.7s) |
| 主题 | `next-themes`,`attribute="data-theme"` |
| MDX | `next-mdx-remote` + remark-gfm + remark-math + rehype-slug + rehype-pretty-code(Shiki)+ rehype-katex |
| 动画 | Framer Motion |
| 图标 | Lucide React |
| 校验 | Zod |
| 测试 | Vitest |
| 评论 | Waline(可选) |

## 许可

[MIT](./LICENSE)。拿去用、改、商用都可以,保留版权声明即可。
反馈内容错误

看看同类模板

对比同技术栈与用途的模板,找到更适合的视觉与内容结构。