Personal website
定位与范围
这是本人的作品集与博客合一的静态站点:首页入口、自我介绍、项目列表与逐篇说明、按日期归档的博客、生活图文时间线,以及主题与字体等站点级设置。文案以中英双语组织(站点级切换语言),项目详情、博客正文等随 locale 读取对应内容或文件。
设计目标包括:内容可静态生成、结构清晰便于扩展(新增文章或项目主要加数据与文案)、交互上保留「灵动模式」¹ 这一可选实验特性,同时尊重减少动画偏好。
技术栈与运行形态
框架为 Next.js²(当前 16.x)的 App Router³:页面以 React Server Components 为主组织布局与数据读取,客户端组件用于需要浏览器状态或动画的区块(如整站设置、灵动排版、地图等)。样式使用 Tailwind CSS⁴ 与少量全局 CSS。类型系统为 TypeScript,构建由 Next 内置打包器完成。
依赖上除核心栈外,博客正文使用 react-markdown;生活页地图使用 d3-geo 与中国 GeoJSON;灵动排版依赖 @chenglou/pretext⁵ 做文本分段,再配合自研布局算法绕开鼠标与「子弹」障碍。
路由与主要页面
根路径为站点入口;`/intro` 为自我介绍(教育、奖项、联系方式、简历链接与长 bio)。`/projects` 列出 `lib/projects` 中登记的项目,每项链到 `/projects/[slug]`;有详情文案的 slug 在 `projectDetailCopy` 中提供中英结构与脚注,无则显示占位说明。`/blog` 聚合 `data/blogs/YYYY/M/D/*.md`,单篇路由为 `/blog/[year]/[month]/[day]/[slug]`,构建时通过文件系统扫描生成静态参数。`/life` 展示生活瞬间(读本地 JSON 与图片);`/life/post` 为带鉴权的发布端(调用下文 API)。`/settings` 为主题、正文字体、中英与灵动开关。
博客如何接入
`lib/blogIndex` 在构建时递归遍历 `data/blogs`,按路径解析年、月、日,从 Markdown 首行 `# 标题` 取标题,生成按日期倒序的索引。文章页在服务端读文件、客户端用 react-markdown 渲染;支持按站点设置切换展示形态(如「灵动」相关纯文本用于绕排)。
生活足迹与 API
`app/api/life/moments` 提供 POST:multipart 上传文案与图片,请求头 `Authorization: Bearer` 与环境变量 `LIFE_POST_SECRET` 比对通过后,按上海时区日期写入 `data/life_photos/moments` 下目录,并更新索引 JSON;另有受控的文件读取路由用于前端展示图片。未配置密钥时接口拒绝写入,避免开放公网误用。
全局状态与外观
`SiteProvider` 持有语言(zh/en)、灵动模式、减少动画等状态,持久化在 localStorage,供顶栏切换与全站消费。`layout` 中通过 `next/font` 注入多组字体变量(如 Geist、思源黑/宋、霞鹜文楷、本地 Zpix 点阵体等),`FontProvider` 与设置页联动切换 `data-font` 与 CSS 变量,实现「同一套页面、多套阅读气质」。主题由 `ThemeProvider` 与 `data-ui-theme` 控制,与 Claude 风等预设配色一致。
灵动模式与排版
开启灵动且未启用减少动画时,部分页面用 `TextEscapeBlock` 包裹正文:以 Pretext 将纯文本拆分为可定位片段,在覆盖层用绝对定位行模拟段落,使文字可绕开鼠标圆形障碍与点击发射的子弹圆;简介页照片使用 `FleeingPhoto` 做轻量躲避。链接、按钮、代码块等通过 `data-lively-exclude` 与选择器排除在发射与障碍逻辑之外,避免误伤可操作元素。关闭灵动或开启减少动画时回退为常规流式排版与静态图。
项目详情文案约定
各项目长文集中在 `lib/projectDetailCopy.ts`:按 slug 分中英 `ProjectDetail`,由小节与正文块组成,支持文末 `footnotes` 与正文内 Unicode 上标对应术语释义;`getProjectLivelyPlain` 将各节文本与脚注拼成纯字符串供灵动模式绕排。`ProjectDetailClient` 统一渲染章节、代码块与脚注列表。
构建与部署注意
博客与生活数据依赖仓库内文件,适合与 Git 同步的静态或半静态部署。构建时若拉取 Google Fonts 失败(网络受限环境),可能需在本地或 CI 配置代理或改用本地字体回退。环境变量仅生活发布等少数功能需要;生产环境变量在托管平台配置,见下节。
Vercel 部署
生产环境由 Vercel⁶ 托管;项目详情正文为纯文本渲染,不使用 Markdown,故勿在文案中写星号加粗等标记,术语释义用文末脚注上标对应。
以下为与本站仓库 personal_web 一致的实际配置顺序(私有仓库亦可:在 GitHub 第三方应用授权中允许 Vercel 访问该仓库)。
(1)导入与根目录:在 Vercel 使用 GitHub 登录并「Add New → Project」,选择仓库;在 Root Directory 中必须选中子目录 personal-site(与 package.json、next.config 同级)。勿选仅含博客与图片等资源的 data 目录,否则无法找到 Next 构建脚本。保存后完成首次构建,获得形如 xxx.vercel.app 的默认域名。
(2)自定义域名:进入该项目 Settings → Domains,添加 onlyslime.online;若希望主站在 www,可勾选将根域重定向到 www.onlyslime.online(根域对访问者做 307 到 www)。页面会列出需在 DNS 服务商处添加的记录类型与取值。
(3)DNS(以腾讯云 DNSPod 为例):在域名 onlyslime.online 的解析中新增:主机记录 @、类型 A、记录值为 Vercel 面板给出的 IP(若平台提示 IP 段扩容,以当前页面为准,勿沿用网上过期的示例 IP);再新增:主机记录 www、类型 CNAME、记录值为 Vercel 给出的专用主机名(通常形如一段随机字符加 vercel-dns 子域)。删除或与上述冲突的旧 A/CNAME,保存后等待全球解析传播。
(4)校验与证书:回到 Vercel Domains,先由 Invalid Configuration 变为通过 DNS 校验;随后可能出现「Generating SSL Certificate」,待 onlyslime.online 与 www.onlyslime.online 均为 Valid Configuration 后,方可用 HTTPS 访问。若长时间卡在证书阶段,可稍后点击 Refresh 重试。
(5)环境变量与再部署:在 Settings → Environment Variables 中为 Production 添加 NEXT_PUBLIC_SITE_URL,若主站为 www 则取值 https://www.onlyslime.online。保存变量后须对当前生产部署执行 Redeploy,站点内 metadataBase 与绝对链接才会与线上域名一致。若启用生活图文发布 API,另按需配置 LIFE_POST_SECRET;仅改变量时同样需要 Redeploy 才生效。
(6)日常迭代:向 GitHub 已关联的生产分支推送提交后,Vercel 会自动触发构建与部署,一般无需在控制台再手动点发布。
术语与注释
- 灵动模式:站点内可选的交互排版实验,开启后正文参与绕开指针与动画子弹,非默认以保证可读性与无障碍。
- Next.js:基于 React 的全栈框架,本站使用其 App Router、静态生成与 Route Handlers 等能力。
- App Router:Next.js 基于目录的路由,支持布局嵌套、Server/Client 组件分界与 generateStaticParams 等静态生成能力。
- Tailwind CSS:实用类优先的样式方案,与 PostCSS 集成,便于保持组件级一致间距与主题变量。
- Pretext(@chenglou/pretext):将纯文本预处理为可排版片段的库,本站用于灵动模式下的行盒拆分。
- Vercel:面向前端与全栈应用的云托管平台,连接 Git 仓库后在推送时自动构建与部署,提供边缘网络、HTTPS 证书与自定义域名解析指引。本站通过其 GitHub 集成与项目级环境变量完成生产配置。