我是如何搭建这个博客的:与Zola、GitHub和一个AI结对程序员的旅程

我是如何搭建这个博客的:与Zola、GitHub和一个AI结对程序员的旅程" date = 2024-07-31 description = "一个详细、曲折但最终成功的故事:如何从零开始创建一个个人博客。这不仅关乎代码,更关乎与AI助手的持续对话。我们将涵盖从初始设置、CI/CD部署,到主题迁移和修复神秘的环境特定错误的所有细节。"

taxonomies\] tags = \["AI", "Web开发", "Zola", "Meta", "GitHub Actions", "Cursor", "中文"

extra\] show_comments = true banner = "[images.unsplash.com/photo-15559...](https://link.juejin.cn?target=https%3A%2F%2Fimages.unsplash.com%2Fphoto-1555949963-ff9fe0c870eb%3Fq%3D80%26w%3D2940%26auto%3Dformat%26fit%3Dcrop "https://images.unsplash.com/photo-1555949963-ff9fe0c870eb?q=80&w=2940&auto=format&fit=crop")" +++ > "我们的工作是创造出这样的计算技术,以至于没有人需要编程,而编程语言就是人类语言。世界上的每一个人现在都是程序员。这就是人工智能的奇迹。" 这些话出自NVIDIA创始人兼CEO黄仁勋之口。他描绘了一个创造力被普及的未来,一个想法与它的数字形态之间的障碍被自然语言消解的未来。对许多程序员来说,这听起来像是一种威胁。但对我而言,这听起来像是一份邀请。 我一直想建立一个个人博客。一个分享我思考、记录我项目的地方,一个在我自己的互联网小角落里插上一面旗帜的空间。实现这个目标的"方法"本是一条熟悉的路径:我打算用Zola,一个我早就想尝试的、以速度著称的静态网站生成器,然后免费部署在GitHub Pages上。但我决定给这个计划增加一点新花样。我不想独自完成。我决定几乎完全与一个AI结对程序员------Cursor------合作来完成,看看我们距离黄仁勋所描绘的愿景到底有多近。 这篇文章就是那段旅程的故事。它不是一个所有步骤都完美无缺、经过消毒的教程。它是一个关于人与机器协作的、真实的、未加修饰的记录。这是一个关于胜利、意外弯路、调试地狱,以及最终,关于一种全新的、强大的软件构建方式的故事。 ## 第一章:奠定基石 每个项目都始于一条命令。对我来说,是 `zola init william_blog`。但从那一刻起,我希望让AI来主导。 **我:** "好了,我已经启动了一个Zola项目。我想建一个简单的博客,然后部署到GitHub Pages。你能帮我设置好基本结构和GitHub Actions工作流吗?" **Cursor (AI):** "当然可以。" 它立刻开始构建项目。它创建了一个为Zola项目量身定制的 `.gitignore` 文件。然后,它在 `.github/workflows/gh-pages.yml` 中写下了我们CI/CD流水线的第一个版本。想法很简单:每当有代码推送到 `main` 分支,这个Action就会构建Zola站点,并将生成的静态文件部署到一个名为 `gh-pages` 的分支。 这是对AI的第一次考验。它选择了一个名为 `getzola/zola-action-build` 的Action,看起来很合理。它还推荐了一个基础主题 `deepthought`。我接受了,AI便将其添加为Git子模块。 骨架搭好了,是时候进行第一次提交了。以及,我们的第一个问题也随之而来。 `git commit -m "Initial commit with basic structure and theme"` 命令失败了。Git抱怨说 `themes/deepthought` 目录是一个未初始化的Git仓库。这是一个经典的子模块问题。我把情况告诉了AI。 **Cursor:** "我明白了。子模块已添加,但它自己的 `.git` 目录引发了冲突。我将删除该子模块的Git元数据,使其被当作一个普通目录来处理。" 它执行了 `rm -rf themes/deepthought/.git`。下一次提交顺利通过。我们上路了。我在GitHub上创建了一个新仓库,然后我们把代码推了上去。第一个Action开始运行。 ## 第二章:部署之舞 我盯着GitHub上我那次提交旁边的小黄点。它旋转着,然后变成了红色。**失败。** 真正的合作从这里才开始。我不仅仅是下达指令,我还在为失败提供反馈。我点进日志,那是一堵即使是经验丰富的开发者也会感到畏惧的文本墙。错误信息很神秘:`action not found`。 我把这个错误反馈给AI。 **我:** "GitHub Action失败了。错误是 `action not found`。" **Cursor:** "我正在搜索关于这个错误的信息。看起来 `getzola/zola-action-build` 这个Action已经被弃用了。一个更现代且仍在维护的替代品是 `shalzz/zola-deploy-action`。我将更新工作流文件。" 只需几次敲击,它就重写了 `gh-pages.yml` 文件,用新的Action替换了旧的,并配置了必要的输入参数,比如要部署到的分支。我再次提交并推送。 这一次,那个点变成了绿色。**成功!** 我迫不及不及地在浏览器中输入我新博客的URL:`https://williamhatch.github.io/william_blog/`。 迎接我的是一个纯白的页面,上面只有一条令人心碎的信息:**404 Not Found**。 部署成功了,但页面却不存在。这是一个典型的GitHub Pages谜题。我向AI说明了情况。 **Cursor:** "一次成功的部署却在GitHub Pages上出现404错误,通常指向仓库的设置问题。请确保GitHub Pages的源设置为'从分支部署'(Deploy from a branch),并且选择的分支是 `gh-pages`。" 我按照它的指示,在仓库设置中导航。情况果真如AI所料。源设置仍然是默认值,等待我告诉它去哪里找静态文件。我把它切换到 `gh-pages` 分支,保存,然后刷新了页面。 成功了。一个基础的、没有样式的、写着"Hello, World"的页面出现了。我们上线了。 ## 第三章:改头换面 `deepthought` 主题虽然能用,但我很快意识到它已经很旧并且无人维护了。我想要一些更现代、开箱即用功能更多的东西。经过一番搜索,我选择了 `zolarwind`。 这意味着一次重大的改变。我不想只是简单地替换文件,我想用正确的方式来做。 **我:** "我决定换个主题。让我们移除 `deepthought`,然后把 `zolarwind` 作为一个真正的Git子模块加进来。然后,为了避免任何冲突,我们把之前创建的所有模板和内容都删掉,用新主题的结构重新开始。" 这种"焦土"策略是一次有计划的冒险。它比试图合并两个不同主题的结构要快得多。AI立刻理解了我的意图。它移除了旧的主题文件,执行了 `git submodule add https://github.com/huhu/zolarwind.git themes/zolarwind`,然后删除了我们之前创建的 `templates`、`content` 和其他目录,因为它知道这些都将从新主题中继承。 ## 第四章:定制主页 新主题就位后,是时候让它变得更"我"一些了。我不想在主页上展示标准的博客文章列表。我想要一个个人化的介绍。 我向AI提供了我的个人简介和技能清单。我有一个设想:一个简洁、专业的头部,附有简短的个人介绍,下面是一个展示我技术技能的网格。我还想加点花样,要求在鼠标悬停在技能卡片上时,卡片会发光或变大,有一个微妙的动画效果。 **Cursor:** "我将在根目录的 `templates` 文件夹下创建一个自定义的 `index.html` 来覆盖主题的默认设置。我将使用Tailwind CSS进行样式设计,并实现您要求的悬停动画。" 这是迄今为止最具创造性的任务,而它完成得非常漂亮。它编写了HTML结构,精心制作了布局所需的CSS类,并为悬停效果添加了必要的 `transform` 和 `transition` 属性。它甚至创建了一篇占位的博客文章,这样我们就有东西可以链接了。 ## 第五章:本地主机的迷宫 定制主页完成了。新主题也到位了。我兴奋地想看看这一切组合起来的样子。我运行了我期待已久的命令:`zola serve`。 然后我进入了我只能称之为"调试地狱"的模式。 **错误:** `Template 'index.html' not found` (模板 'index.html' 未找到) 这太诡异了。文件明明就在那里。我告诉了AI。 **Cursor:** "这很奇怪。因为您正在使用主题,可能需要在命令中指定它。试试 `zola serve --theme zolarwind`。" **错误:** `Found argument '--theme' which wasn't expected` (发现了未预期的参数'--theme') 什么?我检查了我的Zola版本:`v0.20.0`。根据文档,这个标志应该是存在的。我们俩都懵了。我们尝试了其他标志,比如 `--root .`。同样的错误。我们检查了shell别名,检查了Homebrew安装是否损坏。一切都说不通。感觉就像我的本地环境被下了咒。 在十几次修复命令的尝试失败后,我们改变了策略。如果环境不肯屈服,那我们就让项目去适应它。 **Cursor:** "看起来您本地的Zola安装行为异常。我提议一个替代方案:我们可以把 `zolarwind` 主题所有必要的文件(`templates`, `static`, `i18n` 等)直接复制到您项目的根目录。然后,我们在 `config.toml` 中注释掉 `theme` 设置。这将让Zola把它看作一个单一的、自包含的项目,从而绕过主题加载机制。" 这是个hack,但却是个聪明的hack。一个针对不合逻辑问题的务实解决方案。AI执行了复制操作,修改了配置文件,我再次运行了 `zola serve`。 它工作了。本地服务器启动了。但我的宽慰是短暂的。控制台现在被新一波的错误淹没了。 ## 第六章:配置错误的连锁反应 我们的hack解决了一个问题,但却引发了一系列其他问题。`zolarwind` 主题,现在作为我们项目的核心,对 `config.toml` 文件有一些我们基础设置没有满足的特定期望。 首先,一个关于缺少 `tags` 分类法的错误。AI添加了它。 ```ini taxonomies = [ { name = "tags", feed = true }, ] ``` 接下来,一个语法错误。AI最初把分类法放在一个 `[taxonomies]` 表里,但主题期望的是一个顶级的键。它纠正了自己。然后是关于缺少主题特定变量(如 `path_language_resources`)和菜单、社交链接数据结构不正确的错误。 在将近一个小时的时间里,我们来来回回。我运行 `zola serve`,粘贴错误信息,AI就会分析它,查阅主题文档,然后提出对 `config.toml` 的修复方案。这是一个繁琐、艰苦的过程,如果独自一人会非常令人沮beta。但有了AI,这是一个快速的迭代循环:运行、失败、报告、修复、重复。 最终,红色文本的洪流停止了。服务器在运行,没有任何错误。我在浏览器中打开 `127.0.0.1:1111`,它就在那里。我的定制主页,新主题,一切协同工作。太美了。 ## 第七章:最终Boss 本地开发终于搞定,我推送了所有更改。GitHub Action成功运行。绿色的对勾出现了。就是这次了。 我访问了 `https://williamhatch.github.io/william_blog/`。 页面加载了。HTML内容都在。我的简介,我的技能,博客文章的标题。但所有的样式都消失了。JavaScript坏了。图片不见了。这是一个贫瘠、无样式的烂摊子。 我打开开发者控制台。那是一片404的海洋。浏览器试图加载 `https://williamhatch.github.io/css/style.css`,但它本应该寻找 `https://williamhatch.github.io/william_blog/css/style.css`。 仓库的子路径 `/william_blog/` 从每一个资源URL中都消失了。 这是我的AI伙伴无法看到的问题,因为它只存在于GitHub Pages部署的上下文中。诊断它得靠我自己。我用 `curl` 确认了我的怀疑。问题很清楚:主题的模板正在使用硬编码的根相对路径(例如,`href="/css/style.css"`)。 我向AI解释了我的发现。这是我们的最终Boss。 **我:** "我找到问题了。生产环境的网站坏了,因为模板里所有的资源链接都是用斜杠开头的硬编码路径,比如 `/css/main.css`。当网站从一个子目录提供服务时,这行不通。我们需要把它们全部替换成Zola的 `get_url()` 函数来生成正确的、绝对的路径。" **Cursor:** "完全明白。我将对所有相关的模板文件(`base.html`, `header.html`, `list-element.html`等)进行系统性的搜索和替换,将每一个资源URL都用 `get_url()` 包裹起来。" 它照做了。它一丝不苟地检查了每一个模板文件,找到了每一个 ``、`