How Codex Helped Me Migrate My Site from Hexo to Astro | Codex稳稳接住了我,吗?
Note: The dialogues in the dialog boxes are not AI-generated.
注:对话框中内容为非AI生成内容。
This paragraph describes how I used Codex to migrate my blog from Hexo to Astro. I’ve been using Hexo to power this static blog for many years, and on a whim, after multiple conversations with AI, I decided to migrate to Astro. During this process, I spent about three nights completing the migration from 0 to 1, maximizing the vibe coding approach. This article summarizes the migration experience based on our collaboration over the past few days as an AI, along with some personal feelings as a non-AI.
本文讲述了我如何使用 Codex 将博客从 Hexo 迁移到 Astro 的过程。我使用 Hexo 来搭建这个静态博客已有多年,一时兴起,在与AI多轮对话后,我决定向 Astro 迁移。在此期间,我花了大约三晚的时间,从0到1,最大限度以 vibe coding 的形式,完成了迁移工作。本文是我让 Codex 根据过去我们这几天的合作,AI总结的迁移经验,以及我作为非AI的一点个人感受。
I’ve been wanting to move my blog from Hexo to Astro for a long time. Hexo served me well, but the longer the site lived, the more I felt the friction: plugin glue, brittle templates, and a build process that was harder to reason about as the content library grew. Astro promised a cleaner mental model and a simpler future. I finally made the jump, and I did it with the help of Codex.
我一直想把博客从 Hexo 迁移到 Astro。Hexo 曾经很好用,但网站越久越让我感觉摩擦变多:插件粘合、模板脆弱、内容库变大后构建过程难以理解。Astro 承诺更清晰的心智模型和更简单的未来。我终于迈出这一步,而且是在 Codex 的帮助下完成的。
a cleaner mental model and a simpler future - LOL.
更清晰的心智模型和更简单的未来——笑。
This post is a quick walkthrough of how the migration actually went—what Codex did well, what I had to watch out for, and a few concrete details that made the process feel less like a risky rewrite and more like a steady refactor.
这篇文章简要记录迁移的真实过程——Codex 做得好的地方、我需要警惕的坑,以及一些具体细节,让整个过程更像稳定的重构,而不是冒险式的重写。
Step 1: Start with a plan (and keep it real)
The first thing I did was write a migration plan. Not a corporate one—just a doc that listed what the Hexo site actually had: routes, templates, pagination, tags, categories, archives, destination pages, and all the small behaviors you only notice after years of usage. Codex helped turn that into a structured checklist so we didn’t lose track of what “done” really means.
第一步是写迁移计划。不是那种公司式文档,而是一份真实清单,列出 Hexo 站点真正拥有的东西:路由、模板、分页、标签、分类、归档、目的地页,以及那些用了多年才意识到的小行为。Codex 帮我把它整理成结构化清单,避免在过程中忘记“完成”的真正含义。
“All the small behaviors you only notice after years of usage” summarized by AI are quite funny, listing many of my nitpicks—folder structure, CSS styles, etc.
AI总结的“那些用了多年才意识到的小行为”还是很有意思的,例举了我很多的吹毛求疵——文件夹结构,CSS样式,等等。
The plan kept us honest. It also revealed a few non‑obvious dependencies, like how archives were organized by year and month in Hexo, or how category labels were bilingual. That kept the new site from drifting away from the old one while we rebuilt the core routes.
计划让我们保持诚实,也暴露了一些不显眼的依赖,比如 Hexo 归档按年/月组织,分类标签是双语的。正是这些细节,让新站在重建核心路由时不至于偏离旧站体验。
Step 2: Port features, not just pages
The migration wasn’t just about copying content. It was about carrying over the behaviors:
迁移不只是搬运内容,而是迁移行为本身:
- A post layout that matched the original theme structure
- 与原主题结构一致的文章布局
- A sidebar with subscriptions, tags, and destinations
- 带订阅、标签和目的地的侧栏
- Lightbox handling for gallery posts
- 画廊文章的灯箱浏览
- Disqus comments on post pages
- 文章页的 Disqus 评论
- RSS/Atom feeds that still worked across readers
- 能被各类阅读器识别的 RSS/Atom
Codex made it easier to translate those across frameworks, especially when the files weren’t straightforward copies. For example, Astro components replaced EJS partials, and a single layout file replaced the old template layering. We kept the look and feel, but simplified the system underneath.
Codex 让跨框架迁移更顺畅,尤其是在文件不是简单拷贝时。比如,用 Astro 组件替代 EJS partial,用一个布局文件替代旧的模板层级。外观与体验保持一致,但底层系统更简洁。
Step 3: The slug surprise
One of the first real “gotchas” was slug normalization. I changed the slug rules to clean up punctuation in post titles. That seemed harmless—until images started breaking. In the old structure, assets lived under folders named after the old slug. In the new one, the slug changed, so the asset path changed too. Hello, broken images.
第一个真正的“坑”是 slug 规范化。我改了 slug 规则来清理标题里的标点,听起来很安全——直到图片开始坏掉。旧结构里,资源目录按旧 slug 命名;新结构里 slug 变了,资源路径也跟着变了,于是图片 404。
The fix wasn’t glamorous but it was solid: I made the asset folders match the new slug rules. That meant a one‑time rename sweep under public/assets and then letting the Figure component use the same slug logic as the routes. The result: cleaner URLs and working images, without a permanent layer of per‑post overrides.
解决方案不花哨但靠谱:让资源目录和新的 slug 规则保持一致。我们做了一次性重命名,把 public/assets 下的旧目录统一成新规则,然后让 Figure 组件和路由用同一套 slug 逻辑。结果是 URL 更干净,图片也正常显示,而且不需要长期维护每篇文章的覆盖字段。
The debugging playbook here was unexpectedly valuable: reproduce on the homepage (where Astro.params is empty), log the computed base path in the Figure component, and compare it with the post page (where Astro.params is present). That made it obvious that the index renderer needed a different base‑path source, and it kept me from chasing the wrong codepath.
这段调试流程意外地有用:先在首页复现问题(Astro.params 为空),在 Figure 组件里输出计算出来的 base path,再和文章页对比(Astro.params 有值)。这样一眼就能看出首页需要不同的 base‑path 来源,也避免我盲目追错代码路径。
This was the worst part of the whole experience. The AI had no foresight about resource path issues caused by slug changes. During the troubleshooting, it didn’t realize that the actual asset paths were tied to the slugs. While trying to fix things, AI kept patching in the same place, with adding unnecessary variables and functions, leading to increasing code complexity until this problem became completely unfixable by AI.
这是整个流程体验下来最差的一部分,AI对于slug变化引起的资源路径问题完全没有预见,在修改过程中也没有意识到真正的asset路径是和slug绑定的,很多时候在挑事的过程中不断的在原地打补丁,导致代码的复杂性越来越高,直到最后这个问题已经完全无法被AI修复。
Step 4: Restore the small affordances
I was surprised how much I missed the little things. The “Newer / Older” links at the bottom of posts. The subtle comment link in the footer. The exact spacing on the article header. Migration isn’t just about big features—it’s about muscle memory.
我惊讶于自己多么在意这些小细节:文章底部的“Newer / Older”链接,页脚里低调的评论入口,标题区域的细微间距。迁移不只是大功能,更是肌肉记忆。
We added the post nav back in, ported the CSS from the Hexo theme, and even adjusted the Disqus section background to match the original layout. These are small touches, but they’re the difference between “a new site” and “my site.”
我们把文章导航加回去,移植了 Hexo 主题的 CSS,甚至把 Disqus 区域的背景调整成原来的样子。这些小改动让它从“新站”变成“我的站”。
I wasn’t that “surprised” by myself. What surprised me more was that AI didn’t record these “little things” from the beginning. During the entire parity handling process, AI hardly played a role in discovering parity. Of course, one reason is that I didn’t provide the generated webpage source code back to AI, but since AI could access the entire project source code, I wasn’t expecting No assistance from AI on these detailed tasks.
我到没有多么的“惊讶”我自己。我更多的惊讶于AI完全没有在一开始就记录下这些”小细节“。在整个处理parity的过程中,AI几乎没有起到发现parity的作用。当然这其中的原因更多的是因为我并没有把生成的网页的源代码重新反馈给AI,但是在AI可以access整个项目的源代码的情况下,这些细节工作并没有得到AI的辅助。
Step 5: Get the feed right
Feeds are deceptively tricky. I wanted an Atom feed that used full HTML content, not just summaries, and limited itself to the most recent posts. Codex helped me update the feed generator so it renders full HTML, uses a 20‑post limit, and exposes a clean self‑link so feed readers don’t complain.
Feed 看似简单却暗含细节。我想要的是:Atom feed 使用完整 HTML 内容,而不是摘要,并限制为最近的文章。Codex 帮我更新了生成逻辑,输出完整 HTML、限定 20 篇、并设置正确的 self link,让阅读器不再报错。
This was the kind of detail that’s easy to skip—but once the site is migrated, it’s painful to come back and fix later. Doing it right now saved time and avoided subtle breakage for long‑time subscribers.
这是那种很容易跳过的细节,但一旦迁移完成再回头修就会很痛。现在一次做好,既省时间,也避免老订阅读者被小问题折磨。
Step 6: Ship with guardrails
Finally, I wanted a deployment path that felt safe. The old Hexo deploy script assumed a role and synced public/ to S3. We copied the same approach for Astro and added a dry‑run mode that prints every file that would be uploaded. That gave me confidence to run the real deploy without holding my breath.
最后我需要一个安全的部署路径。旧的 Hexo 脚本是 assume role 后把 public/ 同步到 S3。我们沿用这个思路,给 Astro 加了 dry‑run 模式,逐行打印将要上传的文件,让我在真正部署前心里有底。
At the end of this, Astro is the primary build. Hexo remains in the repo as a backup, but the daily workflow is now Astro‑first.
迁移完成后,Astro 成为主构建。Hexo 仍保留在仓库里当备份,但日常流程已经彻底转到 Astro。
What Codex was best at
- Large-scale edits: moving logic across multiple files without missing a dependency
- 大规模改动:跨多个文件迁移逻辑而不遗漏依赖
- Consistency: maintaining naming conventions and style across the whole codebase
- 一致性:全仓范围保持命名和风格一致
- Fast iteration: I could ask for a change, see it, test it, and refine quickly
- 快速迭代:提出修改、立即看到、快速测试并持续调整
In the entire process, I was most satisfied with:
- AI quickly setting up the framework, which is of course the most basic task for AI at present.
- AI automatically generating auxiliary scripts, and using these scripts to batch process some repetitive tasks.
- During the debugging process, AI quickly generated some temporary Python scripts to perform relatively more complex debugging tasks. There was obviously human intervention behind the AI implementation, which saved both Tokens and Compute, and also solved the problem faster.
我在整个流程中,最满意的有以下这些点:
- AI快速搭建框架,当然目前来说这对于AI是最基本也是最擅长的事情了。
- AI自动生成辅助性脚本,并且用这个脚本文件来批量处理一些重复性的工作。
- AI在debug的过程中,能够快速生成一些临时的Python脚本,去做相对更复杂的debug的工作。这点明显是背后人工对于AI流程的主动干预,以此节省Token和Compute,也能够更快解决问题。
What still needed human judgment
- Which behaviors were worth preserving vs. simplifying
- 哪些行为值得保留,哪些可以简化
- How far to push slug normalization without breaking legacy assets
- slug 规范化要推进到什么程度才不会破坏旧资源
- Where to rely on route params vs. render-time context (index pages don’t behave like post routes)
- 在哪里依赖路由参数,哪里依赖渲染上下文(首页并不像文章路由)
- When to stop chasing perfect parity and just ship
- 什么时候停止追求完美对齐,直接上线
I think, it needs more than human judgement. Our goals were very clear. But many times the project still couldn’t move forward.
- Throughout the entire debugging process, most of the time the quality of the generated code was not high. Every time a problem occurred, AI was more likely to add rather than subtract. The result was that unnecessary code kept accumulating. It was hard for AI to determine which code was redundant and which was necessary, eventually leading to decreasing debugging efficiency with iterations after iterations.
- AI made fewer proactive judgments or decisions during the process, more like a “poke and prod” attitude, lacking initiative.
- AI often produced sloppy and perfunctory results when dealing with detailed issues, forcing me to add more iterations to achieve the desired effect.
我认为远不只是human judgement。很多时候项目无法继续推进下去,即使目标十分清楚。比如:
- 整个debug的流程,大部分的情况下AI生成的代码的质量不高,这里我不满意的是每次出现问题,AI更擅长于“做加法”而非“做减法”,这样的结果是导致不必要的代码越来越多,在删除和清理的过程中,又无法确定哪些代码是冗余的,哪些是必要的,进而导致debug的效率随着迭代越来越低。
- AI相对更少的在过程中做出主动的判断和决策,更像是“戳一戳,动一动”的态度,缺乏主动性。
- AI在处理细节问题上,很容易出现糊弄和敷衍的结果,不得不迫使我增加更多的迭代才能达到预期的效果。
This migration took real time, but it didn’t feel like a rewrite. It felt like gradually untying a knot—one decision, one file, one subtle bug at a time. Codex didn’t do the thinking for me, but it made the execution smoother and more transparent.
这次迁移确实花了时间,但并不感觉像重写,更像慢慢解开一个结:一个决定、一处文件、一个细小 bug。Codex 没有替我做决策,但它让执行过程更顺滑、更透明。
If you’re thinking about a similar move, my advice is simple: write the plan, stick to it, and keep the small details that make the site feel like home.
如果你也在考虑类似迁移,我的建议很简单:写计划、坚持执行,并保留那些让网站有“归属感”的小细节。
Anyway, after saying the good and bad things, I need to admit: Codex ‘get’ me. It’s not me writing code, it’s me writing code with AI. In the past year, there have been more and more “AI shocks” in life and work - only gratitude 🙇. I hope that when I grow older and accidentally fall, AI can still ‘get’ me. 🙏
说了这么多好的坏的,但无论如何还是需要承认:Codex稳稳地接住了我。不是我在写代码,而是我在和AI一起写代码。过去的一年间,生活工作中出现了越来越多的“AI震撼”——唯有感恩 🙇。希望未来在我生理年纪变大,不慎跌倒的时候,AI还能稳稳地接住我。🙏