个人网站
一个把个人基础设施当生产环境来做的双语开发者作品集 —— 自托管 Docker 栈、基于站点自身内容的 AI 助手、WCAG AAA 无障碍,以及跑着 222 个 E2E 测试和 Lighthouse 审计的 CI 流水线。

一个对待个人基础设施, 像对待生产环境一样认真的作品集。
17 个页面、17 个 API 路由,以及一个用站点自身内容回答关于我的问题的 AI 助手 —— 全部独立开发、完整双语,跑在自己的服务器上。博客、摄影画廊、隐私优先的分析和 WCAG AAA 无障碍,通过带健康检查门禁的部署流水线交付。
- 技术栈
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS
- PostgreSQL + pgvector
- Docker
- Playwright
- 分类
- Full-stack
为什么做这个
实验场与生产环境不是模板
从零搭建,最初是学习 Next.js App Router、Server Components 和 i18n 的实验场 —— 后来一路长成自带部署流水线和 AI 助手的自托管平台。同时它也是面向雇主的正式线上作品集。
故意过度工程化
检索管线可视化的 RAG 助手、自托管分析、每个页面的 E2E 测试、axe-core 无障碍审计、Lighthouse CI、带健康检查门禁的部署 —— 因为这个网站本身就是作品。
一览
数据一览- 页面
- 17
- API 路由
- 17
- 测试文件
- 63
- 语言
- 2
- WCAG 等级
- AAA
- 翻译条目
- 565
全栈维度
七个维度- FE
前端 界面与动效
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS 4
- Framer Motion 12
- next-intl · 565×2 条目
- BE
后端 API 与契约
- 17 个 API 路由
- RFC 9457 错误格式
- SSE 流式
- 限流与配额
- OpenAPI 规范
- DB
数据库 持久化
- PostgreSQL 18 · 自托管
- 11 张表
- pgvector(1024)
- _zh 双语列
- 每晚 pg_dump
- AI
Ask 站内 RAG
- LiteLLM 网关
- voyage-3.5-lite · 1024 维
- pgvector · 余弦前 5
- 强制 [n] 引用
- 实时管线面板
- UI
设计 系统与无障碍
- OKLCH 色彩系统
- WCAG AAA · 13:1+
- 3 种主题
- Cormorant · Geist · JetBrains Mono
- QA
测试 质量关卡
- Playwright E2E · 4 路分片
- Vitest 单元测试
- axe-core 无障碍
- Lighthouse CI
- OPS
DevOps 把一切发布出去的那一层
- Docker
- Dokploy
- Traefik
- GHCR 镜像
- Cloudflare R2
GitHub Actions- lint
- typecheck
- build
- test
- e2e ×4
- health-gated deploy
线上实况
桌面端 · 移动端

Ask 如何工作
RAG 管线网站基于自身内容回答关于我的问题,而所有防护 —— 按 IP 限流、输入校验、全局每日配额 —— 都跑在任何付费调用之前。
语料博客 MDX · 作品集数据库 · 个人资料
切块按标题切分 · 300–800 token
向量化Voyage 3.5-lite · 1024 维
入库pgvector —— 与网站同一个数据库
检索余弦相似度前 5 · 0.2 下限
约束编号摘录 · 强制 [n] 引用
生成自托管 LiteLLM 网关 · SSE 流式
回答过滤推理块 · 实时引用面板
功能概览
三大支柱全栈作品集:博客、摄影画廊、项目展示、基于站点自身内容的 AI 助手、隐私优先的分析和生产级基础设施 —— 全部双语。
内容
博客MDX + 语法高亮 · 基于 slug 的分类、子分类、标签 · 归档 · 带 active 状态的目录 · 分享按钮
摄影瀑布流 · EXIF 元数据 · 灯箱 · 分类筛选
项目展示结构化详情页 · 双语内容 · 分享按钮
AI 与体验
Ask —— AI 站点问答检索管线可视化的 RAG · /ask 演示间 · 首页 · ⌘K
命令面板 (Cmd+K)搜索页面、项目、文章 —— 可原地切换 Ask 模式
主题与键盘浅色 · 深色 · 跟随系统 —— OKLCH、AAA 对比度 · 方向键翻页
基础设施
隐私优先分析自托管 umami · 无 Cookie · 不记录 IP · REST API 聚合
安全CSP · 边缘源站防护 · 按 IP 限流 + 每日配额
SEO动态站点地图 · hreflang · JSON-LD · OG 图片 · robots.txt
权衡
经受住考验的决策自托管,告别 Vercel + Supabase
网站最初跑在 Vercel 和 Supabase 上,后来刻意迁移到自托管:自己的 VPS 上跑 Dokploy + Traefik、Postgres 与应用在同一个 compose 里、GHCR 镜像、每晚 pg_dump 备份并保留 14 天。运维成本更高 —— 但部署流水线、备份和缓存行为本身成了作品集展示的一部分。
向量放进应用数据库,而非独立向量库
RAG 语料只有约 70 个块。独立向量数据库纯属额外开销 —— pgvector 让检索和其他数据只隔一条 SQL,这个规模下精确余弦扫描亚毫秒完成、100% 召回。语料超过约 1 万块之前不建向量索引。
网站和模型之间隔一层 LLM 网关
应用通过一个稳定的模型别名调用自托管 LiteLLM 代理,而不直连任何供应商。换上游模型只需改网关配置、无需重新部署应用;供应商密钥只存在网关里;流式过滤器会剥离思考块,推理模型可以直接换上,UI 不用改。
检索阈值靠实测调出来,不靠理论
相似度下限定在 0.2,因为设 0.35 时一个真实答案(毕业院校问题,仅 ~0.34)被丢弃,而无关噪声反而拿到 ~0.39。向量阈值只筛明显噪声 —— 真正把关相关性的是 grounding 提示词:强制 [n] 引用、允许回答"不知道"。
WCAG AAA,而非仅 AA
所有颜色 token 都达到 AAA 标准(两种主题下 13:1+ 对比度)。OkLCh 色彩空间在明暗模式间保持感知一致性。每个页面在 E2E 中运行 axe-core 检查 —— 无障碍退化会让构建失败。
_zh 后缀列而非独立翻译表
只有 2 种语言,用外键关联的翻译表是过度设计。每张表上的 _zh 后缀列保持查询简单 —— 一次查询、一次语言判断、不需要 JOIN。
想了解完整细节?
很乐意聊聊这个项目背后的架构、决策与取舍。


