After ten parts about rebuilding the homelab, there is one more thing I want to write about: how I wrote this series.

I kept my conversation with Amp beside a live preview of the blog. I could read a post, point at a sentence and ask for a change without explaining where to find it. That changed editing from describing a page to pointing at it. A small difference, but a very useful one!

Illustration of a blog preview beside an agent conversation, with a highlighted paragraph and comment bubble; separate blog and email cards sit on the desk

Read the page, point at a sentence, review the change. Publishing comes later.

Comment on the page, not around it

The blog uses Hugo, and the repository tells Amp how to start its preview server inside an Orb. I open Blog Preview in the thread’s Portal and read the actual page, including drafts and future-dated posts. The typography, images and captions are all there. I do not have to imagine what the Markdown will look like.

The Portal review widget lets me select something on the page and attach a comment. Amp receives the selected text and its location along with my feedback. It edits the Markdown, Hugo reloads the page, and I read the result in place.

In Part II, I mentioned one of those comments: “Assume one? It doesn’t feel direct and clear.” That was enough to ask for the wording change. I did not need to copy the surrounding paragraph into the conversation first.

Amp’s writing still needed editing. I decided what the posts should say, challenged claims that sounded stronger than the evidence and rejected wording that did not sound like me. It helped trace technical claims back to the repository and the checks we had run. However, a sentence can be technically correct and still not be something I would write.

The Portal is where I review the writing. The Markdown in Git is still the source of truth.

There is also a rule in AGENTS.md: commenting on a draft does not give Amp permission to publish it. It must ask me to confirm the exact post title before starting publication. Asking for a better caption should not accidentally become a release!

One source, two publications

I also wanted these Amp posts to reach Substack readers. What I did not want was to prepare each post twice, copying paragraphs and uploading the same images again.

So the blog stays the original. My publication workflow requires the post to pass beta and production checks, followed by clearing the changed pages from the cache, before Substack distribution begins.

A small command built around a pinned version of python-substack prepares the Substack copy from the local Markdown. It handles the blog’s formatting and images and adds a link back to the original article. The library’s publishing flow needs a draft record, so the command creates one and then publishes it with email delivery enabled. There is no separate Substack editing stage, and later blog edits do not automatically sync across.

The command does not fetch the live blog or prove that its release checks passed. Amp must complete those checks first and use the reviewed source for that release. The repository also provides an Amp-post feed, but that is a separate output, not the input to this command or an automatic publishing connection to Substack.

Before sending anything, Amp must ask me a second question: whether to publish and email that exact title to Substack subscribers. Permission to update my blog is not permission to send an email.

The command keeps a local record of its progress. If a create or publish attempt has an uncertain result, it stops rather than blindly trying again. I would rather inspect Substack than send everyone the same post twice. The integration uses undocumented endpoints, so I do not want to assume they will always behave as expected.

Back to the blog

I started with a homelab that needed years of catching up. I am ending with a better way to look after it, try new ideas and write about what I learn. There is still work to do, but it feels much easier to begin.

Thank you for following along. I hope you found something useful for your own projects, or simply enjoyed seeing this one come together. The series ends here. The tinkering, of course, does not!

Revisit the series

If you want to dive back into any part of the rebuild, all ten posts are below.

  1. Why I modernized my homelab instead of upgrading it
  2. Making a homelab repository agent-friendly
  3. Building the new K3s foundation
  4. Proving the entire platform with one blog
  5. Handing PostgreSQL over to Amp
  6. Modernizing an application, not merely moving it
  7. Replacing a surveillance media chain, not just a recorder
  8. Proving Frigate before the cutover
  9. Upgrading observability beyond the old cluster
  10. Building a platform agents can keep improving