SITE / 0 → 1

这个站点是怎么长出来的

一台 2C2G 的小机器、一个 Next.js 单体、一份写死的设计规则。从空白目录到能写作、能放作品、能看数据, 中间没有套壳模板,每一步都留下了取舍的理由。这一页记录它从 0 到 1 的过程,以及它为什么存在。

独立设计 · 开发 · 运维风起8 篇文章在跑

为 什 么 要 有 这 个 站

3 个用途

写作与沉淀

把踩过的坑、想通的设计写成可检索的长文。写下来才算真的想明白,也避免同一个问题踩第二遍。

作品集

项目不只是一句「做过」,而是能点开、能读实现细节、能看源码的完整证据链。

实验场

新想法先在这里跑通:渲染管线、缓存策略、通知降级、视觉特效,验证过再带去生产项目。

从 0 到 1 的 六 个 阶 段

6 phases
  1. 01

    先定设计语言,再写第一行代码

    开工前先把视觉规则写死:深色科技感底子、三级分层(base/panel/raised)、1px 冷蓝灰细线、单一电光青强调色。禁止渐变条、毛玻璃与霓虹,图标一律线性(lucide)+ 少量 3D 物件点缀。规则写进文档后,后面每个页面都在同一套令牌里拼装。

    设计令牌深色优先禁用清单
  2. 02

    技术选型:一个单体,一台小机器

    Next.js 15 App Router 单体 + PostgreSQL,用 Drizzle 做类型安全查询。不做微服务、不上 Docker——2C2G 的机器上,systemd 直跑 standalone 产物最省内存,也让「构建在本地、运行在服务器」这条链路足够简单。

    Next.js 15Drizzlestandalone
  3. 03

    内容模型:六块拼图

    文章、分类、标签、媒体、简历、项目。slug 唯一、索引按查询建;详情页用 SSG + ISR(10 分钟),列表页动态渲染;写入路径统一收口到一个 service 层,标签 upsert、字数与阅读时长预计算、缓存精准失效都在那里完成。

    ISR 缓存slug 路由写路径收口
  4. 04

    后台与写作体验

    管理端与前台共用一套渲染管线:编辑器的实时预览就是文章页的渲染结果,所见即所得。图片在浏览器端先压成 WebP 再上传,服务端只做魔数校验与落盘——省带宽也省 CPU。

    同管线预览浏览器端压缩魔数校验
  5. 05

    上线:从能跑到敢用

    Caddy 反代 + 媒体静态直服,Node 只处理页面与接口;systemd 单元带内存上限与沙箱约束。部署是「本地打包 → 上传 → 解压 → 健康检查」四步,失败自动回滚到上一版本;数据库每天 03:00 备份,保留 14 天。

    Caddy秒级回滚每日备份
  6. 06

    持续迭代:把不确定变成可观测

    上线后补的是「看不见但决定质量」的部分:PV/UV 统计(加盐指纹去重、不存原始 IP)、管理端操作日志、接口限流、SSH 仅密钥 + 防火墙,以及一套覆盖渲染管线的单元测试。

    访问统计操作日志安全加固

现 在 的 样 子

live metrics

已发布文章

8

项目作品

2

内容分类

3

部署形态

2C2G

浏览器

Caddy

zstd/gzip、安全响应头、/media 静态直服(一年强缓存)

应用层

Next.js

App Router + ISR,Node 仅监听 127.0.0.1:3000,堆上限 512MB

数据层

PostgreSQL

Drizzle ORM、本地连接池、每日备份 + 迁移脚本随包发布

写 在 明 面 上 的 取 舍

constraints

纯 JS 依赖

服务端依赖不引入原生模块,保证 Windows 构建产物能在 Linux 直接跑。

媒体不走 Node

图片由 Caddy 静态直服并加一年强缓存,2M 带宽下把 Node 从大文件传输里摘出来。

内存上限 512MB

systemd 注入堆上限,宁可慢一点也不能把 2G 的机器拖进 OOM。

单一实例假设

限流与缓存都用进程内实现——单机部署下够用,也不为此引入 Redis。

想看看它产出了什么?

文章是过程,项目是结果,简历是人。

已运行 —北京时间 --:--:--

© 2026 风起|永远相信美好的事情即将发生!