I started using Hugo just tonight. I’ve got a heavy background in software development, systems administration for both RHEL and Windows, I run my own homelab via three Dell servers running Proxmox. I had written commercial software a few decades ago on my own, and I supported it, and I’ve seen strange things with that old software, so I’m not a stranger to weird oddities. I tend to find them rather quickly unintentionally even today, both with my own code, and with others.
That said, I can’t quite put my finger on the behaviour I’m seeing with Hugo and running the server in memory mode.
I’m running the server out of a shell script under WSL with Debian as the OS:
#!/bin/bash
hugo server --forceSyncStatic -M --gc --disableFastRender --noHTTPCache
The gc probably is a noop here, sure, fine, ok. I was swapping between disk and ram modes and that just stuck.
Here’s the version reported when I run:
$ hugo version
hugo v0.151.0-c70ab27ceb841fc9404eab5d2c985ff7595034b7+extended linux/amd64 BuildDate=2025-10-02T13:30:36Z VendorInfo=gohugoio
So here’s my problem.
The short of it is that Hugo is seeing work being done against a file, writing the generated code to a cache, but forgetting it after a reload. I’d expect that the entire code base for all files would be done on engine start up, but there seems to be something missing in the process. I’d also expect that Hugo would look at EVERY page, parent or child, list or page, leaf or branch.
I’m attempting to figure out how to write my own breadcrumb for certain pages. The intent is to list off ALL the pages for the particular laser focused subject I’m writing about. I’m manually maintaining them in a shortcodes file.
$ find . -type f | grep bread
./layouts/shortcodes/breadcrumbs.html
In each index file I have a {{<breadcrumbs>}} entry right after the front matter for consistency. This renders to the pages I’ve listed this on (I’ll rename later to something more specific when/if I get more accustomed to Hugo).
This is the file structure I’m running with:
$ find . -type f | grep homelab | sort
./content/homelab/dhcpdns/01-tooling/index.md
./content/homelab/dhcpdns/02-phpipam/index.md
./content/homelab/dhcpdns/03-walkthrough/index.md
./content/homelab/dhcpdns/index.md
./content/homelab/_index.md
./content/homelab/proxmox/index.md
This is what the list shows
$ hugo list all | grep homelab
WARN module with path "terminal" is imported for the same version "" more than once
content/homelab/_index.md,,,2025-10-05T23:00:00Z,0001-01-01T00:00:00Z,2025-10-05T23:00:00Z,false,/homelab/,section,homelab
content/homelab/dhcpdns/index.md,,phpIPAM - My IP Management System,2025-10-05T23:00:00Z,0001-01-01T00:00:00Z,2025-10-05T23:00:00Z,false,/homelab/dhcpdns/,page,homelab
content/homelab/proxmox/index.md,,Proxmox Hardware Config,2023-10-05T00:00:00Z,0001-01-01T00:00:00Z,2023-10-05T00:00:00Z,false,/homelab/proxmox/,page,homelab
I understand that index.md and _index.md do different things in Hugo world. I understand the behaviour I’m seeing (when its working), I don’t understand the terminology being used.
When I start the server with the file and directory structure you see above, when I go to http://localhost:1313/homelab/ I see both my Proxmox Hardware Config and the phpIPAM directory. I can go into phpIPAM, and I see the content I’ve written. However, when I click on the breadcrumb links, I run into 404s.
This is probably because of a mix up with the index versus _index files. That’s fine, that’s not what I’m here to report on. I’ll figure that jazz out later with more dents in the desk, I’m sure.
What I am here to report on is how the server is caching its content internally and not cleaning up after itself. It’s doing something very wrong and what it’s showing me is NOT representative of what my markdown is being written out as.
While the server is still running, I go into the deepest subdirectories (The 01, 02, and 03) and rename the index.md to _index.md. With every rename, I see the server say it’s rebuilding the file. Cool.
Serving pages from memory
Web Server is available at //localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
Change detected, rebuilding site (#1).
2025-10-05 23:49:17.908 -0400
Source changed /homelab/dhcpdns/01-tooling/index.md
Source changed /homelab/dhcpdns/01-tooling/_index.md
Web Server is available at //localhost:1313/ (bind address 127.0.0.1)
Total in 11 ms
Change detected, rebuilding site (#2).
2025-10-05 23:49:26.408 -0400
Source changed /homelab/dhcpdns/02-phpipam/index.md
Source changed /homelab/dhcpdns/02-phpipam/_index.md
Web Server is available at //localhost:1313/ (bind address 127.0.0.1)
Total in 7 ms
Change detected, rebuilding site (#3).
2025-10-05 23:49:32.408 -0400
Source changed /homelab/dhcpdns/03-walkthrough/index.md
Source changed /homelab/dhcpdns/03-walkthrough/_index.md
Web Server is available at //localhost:1313/ (bind address 127.0.0.1)
Total in 6 ms
With the renames in place, I have this file structure now:
$ find . -type f | grep homelab | sort
./content/homelab/dhcpdns/01-tooling/_index.md
./content/homelab/dhcpdns/02-phpipam/_index.md
./content/homelab/dhcpdns/03-walkthrough/_index.md
./content/homelab/dhcpdns/index.md
./content/homelab/_index.md
./content/homelab/proxmox/index.md
When I go to the web page, go back to the homelab landing page, then go into the phpIPAM page, my breadcrumbs work. Which that in itself is fantastic.
However, things start to go off the rails right about now.
$ hugo list all | grep homelab
WARN module with path "terminal" is imported for the same version "" more than once
content/homelab/_index.md,,,2025-10-05T23:00:00Z,0001-01-01T00:00:00Z,2025-10-05T23:00:00Z,false,/homelab/,section,homelab
content/homelab/dhcpdns/index.md,,phpIPAM - My IP Management System,2025-10-05T23:00:00Z,0001-01-01T00:00:00Z,2025-10-05T23:00:00Z,false,/homelab/dhcpdns/,page,homelab
content/homelab/proxmox/index.md,,Proxmox Hardware Config,2023-10-05T00:00:00Z,0001-01-01T00:00:00Z,2023-10-05T00:00:00Z,false,/homelab/proxmox/,page,homelab
I don’t see a difference in line counts here between this and the previous post of showing the list. Strange that. But where things are ACTUALLY broken, is if I stop the server, then immediately restart it, and I refresh on the 03-Walthrough page, I immediately get a 404.
So from just watching what’s happening, Hugo server is seeing that I’m “doing work” on a file, and it’s going and doing its work to render the page, update it’s stuff, and whatever else it needs to do. But between restarts, it loses the changes to what the index and _index file renames did, which isn’t valid work. It probably keeps those files around when writing to disk, but that just means that the public folder doesn’t have the exact content my markdowns are supposed to be rendered out as.
My concern is for when I go OUT of memory storage mode and switch back to disk mode, if I nuke the public folder, and let Hugo rebuild, I’m not going to get the correct answer post build. (Even if my filename convention is wrong regarding index – I get it – I’ll work through that and restructure if needed)
So what’s the fix here? What am I doing wrong, if anything? Bug? Crazy me? Something that’s been discussed previously but decided to not work on?
I appreciate the work, as it saves me from coding something like this myself ground up (And I can do that, it’s just I’d rather work on my homelab stuff than things like this right now).