项目 · 已发布

工作室网站重建

把一个继承了重型 SaaS 模板假设的旧站,重建成真正符合工作室需求的小型静态网站。

2026-08-26 开始 · 2026-08-29 更新

为什么做

旧工作室网站继承的是 SaaS starter 的产品假设,而不是一个小型软件工作室真正需要的能力。线上站点既保留了过时定位和模板页面,也存在 sitemap、canonical 等搜索可见性问题,同时运行时复杂度明显高于这个网站的真实需求。

之前怎么做

旧 production 来自 ShipAny / Next.js / OpenNext 技术路线。公开现场仍有模板化 Blog 与 Showcases 页面、重复 canonical、指向 your-domain.com 的错误 sitemap,以及与当前定位冲突的 creator-economy metadata。

我们当时的判断

如果架构真正跟着网站职责走,一个内容型工作室网站应该更简单:公开页面直接输出静态 HTML,Projects / Journal 用 Markdown/MDX 管理,英文默认、中文辅助;只有出现真实需求时,才单独增加动态服务。

怎么验证

先冻结旧站能观察到的 URL 和 SEO 现场,再建立没有旧兼容负担的新 repo;用 Astro 实现双语信息架构;部署到隔离的 Cloudflare Workers Static Assets staging;在完全不碰 production 的情况下验证状态码、canonical / hreflang、raw HTML、crawler access 和响应式表现。

做了什么

一个 Astro 7 静态站:包含英文与简体中文 URL、Projects / Journal 内容集合、每页唯一 canonical、reciprocal hreflang + x-default、自动 sitemap、按环境切换的 robots 策略、真实 404、trailing-slash normalization 和独立 Cloudflare staging。首页随后又加入可逆的 Opening → Focus → Release → Expanded 滚动叙事,同时保留同一份语义化 DOM,以及 no-JS、reduced-motion、tablet 和 mobile fallback。

真实使用里看到了什么

最终验收 build 的 Astro check 为 0 errors / 0 warnings / 0 hints。隔离 Cloudflare 环境真实验证:首页可逆叙事在 1440×900 下复现通过;375px mobile 与 1024px tablet 使用正常流 fallback;reduced-motion 和 raw HTML 完整可用;document scroll width 与 viewport 保持一致;缺失路由返回真实 404。随后 production cutover 把同一个 apex Custom Domain object 原子转移到独立 Static Assets Worker,并在切换窗口内暂时保留 legacy Worker 作为回滚边界。切换后的 live crawl 与 Chrome 回归再次通过双语路由、canonical/hreflang、redirect、sitemap/robots、Email + X 联系状态、真实 404 与无横向溢出验收。新 production 路径经过后续发布与回归稳定后,未再使用的 legacy Worker 与其专用 D1 database 已正式退役。

现在的结果

V1 已正式运行在 inkblocklab.com 的独立 Cloudflare Workers Static Assets Worker 上。英文与中文作为同一版本同步上线,并保持已验收的 SEO、redirect、响应式、可访问性与 Email + X 联系合同。旧 ShipAny/OpenNext production Worker 与其专用 D1 database 已退役;current production 不再依赖旧 runtime。`Inkblock Lab` 仍是 V1 临时公开身份;locale suggestion 继续延后。

学到了什么

  • starter template 只有在它的假设与产品匹配时才是加速器;否则预置功能会变成架构债。
  • 迁移应该保留真正有业务价值的 URL 和搜索权益,而不是为了迁移而保留旧 runtime。
  • 状态码、canonical、hreflang、raw HTML、crawler access 与 404 这类技术可见性问题,最好在 production 前就做成明确验收项。
  • 响应式截图只有在 viewport 真的满足测试条件时才是证据;headless browser 的最小窗口限制可能制造假溢出。

涉及的能力

Web 工程 · Cloudflare · 技术 SEO · 国际化 · 产品架构

为什么把网站本身也当成一个 Project

工作室网站不只是放作品的页面。它要解释我们做什么、沉淀真实项目、发布构建记录,也要成为未来客户项目和自有产品的统一入口。

所以这次重建本身就是一条很合适的公开证据:先看网站真正需要完成什么,再删掉不服务于这个目标的架构。

我们没有为了“迁移完整”去恢复旧系统

旧源码已经删除,而且新站本来就不需要 auth、subscription、credits、dashboard、RBAC、database 或完整 SSR runtime。

真正可能有业务价值的是另一组东西:域名历史、旧 URL、潜在搜索权益,以及旧站已经公开过的事实。

所以这次迁移刻意把两件事拆开:

  • 保留业务价值:旧 URL、可观察的搜索现场、可能需要的 redirect;
  • 不保留架构包袱:ShipAny / Next.js / OpenNext 的旧 runtime 不因为“以前用了”就继续继承。

先在隔离环境把容易出错的地方测清楚

验证阶段没有直接把新站接到 production domain。

我们先在独立的 workers.dev staging 上验证:

  • 核心页面是否真的返回 200;
  • 缺失 URL 是否是真 404;
  • canonical 与 EN/ZH hreflang 是否唯一、互相对应;
  • sitemap 是否只包含真实 URL;
  • staging 是否保持 noindex;
  • 主要正文是否直接存在于 raw HTML;
  • Googlebot、Bingbot、OAI-SearchBot 和普通浏览器是否都能访问;
  • mobile / tablet / desktop 是否存在横向溢出或结构破坏。

首页后来增加了滚动叙事和更多双语内容,但 static-first 架构仍然不需要因此升级成 SSR、数据库或更重的应用 runtime。这比最初的 framework 对比更能说明架构选择是否合适。

为什么把 release 单独验收

英文版上线前检查、中文版原生本土化、临时公开名称,以及 production build / crawl rehearsal 都已经分别完成。两种语言共享事实,但没有被做成逐句镜像。

因此上线前没有继续无限精修首页和内容层,而是把 release engineering 单独处理:先识别旧 production binding 的精确 Cloudflare 对象、在 cutover 窗口内冻结可确定回滚和 redirect,再执行 binding-only cutover 与 live crawl。最终 apex 切到新的 Static Assets Worker,旧 Worker 在切换阶段暂时保持不变;新 production 路径经过后续发布与回归稳定后,旧 Worker 与其专用 D1 database 已退役。