March 9, 2023

While Hugo is overall quite excellent, it does have a few warts, and one in particular was a problem for this site. Sometimes I write fairly long articles, and they don’t really lend themselves well to being a single huge web page.

Nor are they good candidates for being a separate section on the site; they really are just blog posts.

Unfortunately, Hugo can’t paginate normal documents out of the box, and that makes for a problem. Luckily, however, there is a workaround, that I found here and then expanded upon.

Might as well share my work!

The Problem

If you’ve spent any time with Hugo, you know that it has a very particular view of what each file means in your source directory. For example, index.html is just a document, but _index.html is for the list of documents that exist in that directory (the root of a so-called branch bundle). Coloring outside of these lines is all but impossible.

Any given document will only ever cause Hugo to generate a single web page. The only exceptions to that are the “list pages”: those _index.html files that live at the roots of branch bundles. Want to store multiple pages in one document? Sorry, you’re out of luck.

No, I didn’t manage to solve that bit, which is annoying; I like being able to move page boundaries around without having to move chunks of text between files, but alas…

In any event, while Hugo has pagination support for the list pages, it has no such facility for normal pages. And that is truly unfortunate. It would have made this solution far more trivial than it turned out to be…

The Obvious Answer

You’ve probably already hit on the first part of the solution: the aforementioned branch bundles. All a branch bundle is, is a directory of other documents and resources. It’s that simple. So what if you make each page a document in a branch bundle?

Well, you can do that, but the devil is in the details…

For example, here’s the structure of my content directory for 2023 at the time of this writing, including this post:

content
├── blog
...
│   ├── 2023
│   │   ├── 01-floating-io-2-0.md
│   │   └── 02-paged-posts-with-hugo
│   │       ├── _index.md
│   │       ├── page-1.md
│   │       ├── page-2.md
│   │       ├── page-3.md
│   │       └── page-4.md
...

Pretty straightforward, right? Each page in the post is represented as a separate Markdown file under the post’s directory. The names of the files are actually quite irrelevant (though I suppose a clever implementation could make use of them for sorting instead of the mechanism I’m using. Hmmm… Might have to look into that!).

Note that there is no actual content in the _index.html (though you could do something creative with that if you wanted). Instead, the post content is in each page file. The index page is just a bunch of front matter, which we’ll come back to in a bit.

Of course, if this is all you do, Hugo is going to use the standard list template when you browse to that location, and the content is going to look absolutely nothing like what you want.

So how do we fix it?