Customizing Hugo's slug inference with datafiles?

I have approximately 2,000 posts for a medium-traffic site that I’m considering migrating to Hugo. I name my posts according to the scheme: <id>-<slug>.<format>, e.g. 00391-example-post.markdown. This is so that:

  • My content is lexicographically sorted on the filesystem, so it’s easier to find a specific post.
  • The posts are ordered in the order they were written on the filesystem.
  • The slug is determined from the file name, so nothing needs to be updated in front-matter.

Hugo wants to pull the slug from the entire file name, whereas I want to supply my own slug-generation function to just pull it out directly. I’m assuming I can’t tell Hugo to use some external generator – I couldn’t find anything in the docs that seemed to indicate the availability of extensibility for this.

Is there a way to make this happen? Could I use data files, generate the slugs externally into a data file, and tell Hugo to look at the data files to infer the slug for a given post as if it were in the post’s frontmatter?

You currently would have to put this into front matter.

What would it take to get Hugo to associate content in a data file to (a) identify a piece of content in a datafile and (b) trump that content’s frontmatter? (I’d be willing to pay a feature bounty for this improvement if the maintainers think this feature is useful.)

I have no idea what your last post was about, but what I gather from you is:

You have files on the format

<id>-<slug>.<format>, e.g. 00391-example-post.markdown.

You want URLs on the format:

/<id>

Or any variations of the above.

So 00391-example-post.markdown => 00391

Which is doable, I guess, but a fairly narrow use case – with some questions as to what to do with the files that doesn’ match that pattern etc.?

I read your post about the “data files again” … if you are able to make a script that writes to data files, wouldn’t that script be able to write to front matter as well?

I want URLs of the form /<plural>/<slug>, where <slug> is extracted as I described in the original post.

wouldn’t that script be able to write to front matter as well

Sort of. That’s not desirable for two reasons:

  • Correctly parsing an individual YAML+markdown file and writing back to it is much more involved than writing to a new YAML file.

  • Touching 2,000 files is not ideal from a source-control perspective, when compared against generating one file which doesn’t need to live in source control.

I’m sorry if anything was unclear. Let me know how I can clarify.

And the plural value comes from where?

A datafile to filename overrie mechanism would be easy to implement, but it sounds like a very special use case, so probably not worth it.

And touching 2000 files … I would just do it.

It comes from the same place Hugo gets it now - the name of the content directory, unless I’m missing something.

There’s another reason to consider it: it means you can save metadata that’s different for different environments.

For example, you might generate one set of data for the staging version of your static site but another for production. Without this ability, everything has to go into your post front matter, which is awful from a version-control and clean-source-history perspective. You shouldn’t have to make a commit every time you want to switch environments.

This is a valuable addition for using Hugo on documentation sites for enterprises, which is one of the use cases I’m evaluating (though not for this site).

Unrelated question: is there a way to set the slug programmatically from inside a template? That would also do the trick, I think, because I could just define it in my data file and pull it in.

The “slugs” relates to how files are organized in folders, layouts what to put in them.

Right – I was asking asking whether something like setting the slug in a template or layout is possible (in the same way that one can set it in frontmatter).

it would be good to have external utility (script) that could mass convert slug=>filename and filename=>slug.

The answer is no.

Understood. Thanks for your help and prompt responses, @bep.