A while ago I redesigned this site with Claude. This time I asked it to do something far less glamorous: look at the repo and tell me what was messy. What followed was a textbook example of how a perfectly reasonable cleanup can quietly break things — and how having a second pair of (synthetic) eyes makes the fix painless.
The audit
The site runs on Hugo with the PaperMod theme, deployed to GitLab Pages. Claude poked around and came back with a tidy list of issues. The two that mattered:
public/was committed to git. That’s the build output — the stuff Hugo generates. CI rebuilds it on every deploy, so there’s no reason for 100-odd generated files to live in version control..gitignorehad quotes around the patterns:"public/"and".DS_Store". Git treats those quotes literally, so the patterns matched nothing. That’s exactly why the build output and a pile of.DS_Storefiles had sneaked into the repo in the first place.
So we did the obvious thing: fixed .gitignore (no quotes), ran git rm -r --cached public, untracked the stray .DS_Store files, committed, pushed. Clean repo.
The thing that broke
A bit later I noticed my avatar had vanished from the homepage. Along with, it turned out, the favicons and header images.
The culprit is a subtle Hugo distinction that’s easy to forget:
static/is source — Hugo copies it verbatim into the build.public/is output — Hugo generates it.
My avatar had only ever existed in public/img/avatar.jpg. There was no source copy anywhere. It had been dropped straight into the build output and committed, and it kept working purely because the committed public/ was being deployed as-is. The moment we untracked public/, the next build regenerated it from source — and since nothing in static/ contained the avatar, it simply wasn’t there.
In other words: the cleanup was correct, but public/ had been doing double duty as both build output and the only home for some load-bearing assets. Removing it from git removed the assets too.
To its credit, Claude owned the miss rather than hand-waving it. The fix was straightforward: the files were still sitting on disk locally (untracking doesn’t delete them), so we moved everything from public/img/ into static/img/, where it belonged all along. A quick rm -rf public && hugo confirmed the avatar now lands in the build output the proper way, generated from source. Commit, push, done.
A bonus bug
While we were in hugo.yaml, Claude spotted that two favicon entries pointed at .ico files that didn’t exist — the real files were .png. That one predated the cleanup entirely; those favicon sizes had been silently 404ing for who knows how long. Easy fix, fixed.
The takeaway
Two lessons worth keeping:
public/is build output. Never let it be the only home for a source asset. If a file matters, it lives instatic/(orassets/), full stop.- A good cleanup can still have blast radius. The value of working through it with an assistant wasn’t just the initial audit — it was having something that could trace why the avatar disappeared back to a single architectural mix-up, instead of me staring at a broken image wondering what I’d done.
The repo’s genuinely tidy now, the site builds cleanly from source, and the avatar is back where it belongs.