58 comments

[ 5.2 ms ] story [ 113 ms ] thread
I made the jump to Hugo too (from a managed service: svbtle) a long time ago, but I'll be really honest...

I regret it.

I decided to use an off-the-shelf theme, but it didn't quite meet the needs and I forked it; as it so happens Hugo breaks userland relatively often and a complex theme like the one I have requires a lot of maintenance. Like.. a lot.

Now I can't really justify the time investment of fixing it so I just don't post anymore, the site won't even compile. In theory I could use an old version of Hugo, but I have no idea when it broke, so how far do I go back?

So, advice: submit the binary you used to generate the site to source control. I know git isn't the best at binary files, but I promise you'll thank me at some point.

I'm on your side.

Nobody can point to a reason why it's a good idea for a site with any interactivity now.

All the supporters here are all the same: "I had to do a whole bunch of mental gymnastics and compromises to get <basic server side site feature> but it's worth it!" But they don't say why it was worth it, beyond "it's easy now <after lots of work costs sunk>".

When you try get to why they did it in the first place, it's universally some variation on "I got fed up with <some large server side package> so took the nuclear SSG route <and then had to eventually rewrite or get someone else's servers involved again>"

Part of this is a me problem: a personal website should be owned by the person, IMO. A lot of people are fine to let other people own parts of their personal websites, and SSGs encourage that. What even is a personal website if it's a theme that looks like someone else's, hosted and owned on someone else's server - why not just use Facebook at that point?!

> So, advice: submit the binary you used to generate the site to source control. I know git isn't the best at binary files, but I promise you'll thank me at some point.

No need for the entire binary.

Just put `go run github.com/gohugoio/hugo@vX.Y.Z "$@"` into a `hugo.sh` script or similar that's in source control, and then run that script instead of the Hugo binary.

You'll need Go installed, but it's incredibly backwards compatible, so updating to newer Go versions is very unlikely to break running the old Hugo version.

I had the same issue and I'm currently thinking whether it's easier to just Vibe Engineer my own static site generator with the exact features I need vs fighting with the hugo theme system.

My needs for a site are pretty simple, so I might just go with the custom-built one to be honest.

If it breaks, I can just go look in the mirror for the culprit =)

EDIT: Just made my own. Claude + Opus and about 3-4 prompts.

Looking at the comments here a common pain (that I share) is config and code drift, or just losing your config file and being unable to publish a new version without re-doing everything.

I made a version where everything, including the HTML templates and CSS, is built in to a single static Go executable, no configuration files, everything is hard-coded.

This way as long as I have the specific executable version and the source markdown files, I can deterministically replicate my blog output structure.

The source is a directory in my Obsidian vault and the setup supports Obsidian-style front-matter

> advice: submit the binary you used to generate the site to source control.

Or use HVM and submit the .hvm file (which is just a text file with the Hugo version that you use)

> In theory I could use an old version of Hugo, but I have no idea when it broke, so how far do I go back?

Pretty sure the version of Hugo used to generate a site is included in metadata in the generated output.

If you have a copy of the site from when it last worked, then assuming my above memory is correct you should be able to get the exact version number from that. :)

I have the same problem with Jekyll. I fixed my website for the Jekyll version I installed when I got this machine (in 2021). I dread the moment when I get a new computer and have to either try to install this particular version of Jekyll or to fix my website again.

I just assumed static website generators would be stable but well, there's always something that breaks. Terrible user experience for someone who just wants to use the generator to generate a website vs. to tinker with it as a hobby.

I'm in the process of porting my website to PHP ... but that project hasn't gone anywhere because currently everything works ;)

I "solved" this issue by using a custom Docker image, both for writing/serving content locally, and for the CI.

So I have a fixed Hugo version that I know works.

And when I mean "solved", I actually never had the issue because, since I have no reason to upgrade Hugo, I never had to change my Docker image and never had the opportunity to risk breaking my theme.

Out of interest: does anyone know what those three Safari extensions are on Jeff's screenshots?

Edit: thx for answers below!

Interesting. I'm currently looking to migrate from Hugo to Zola. Personally I feel like I grok the configuration and templating options for Zola better than I do for Hugo.
Instead of committing the binary, I highly recommend using a .tool-versions file (if you use asdf or mise) or a Dockerfile with a pinned version.
I like Hugo, but I’ve not found a nice workflow to automatically put the images on a CDN.

I was thinking of making a GitHub action that uploaded the image from a given branch, deleted it, set the URL, and finally merged only the md files to main.

Why not put the whole site behind CDN?
I had a similar push years ago, but I did take this approach once step further. For a similar reason Jeff mentions -- lower maintenance over time.

I was frustrated that (because my posts are less frequent) changes in Hugo and my local machine could lead to changes in what is generated.

So I attached a web hook from my websites GitHub repo to trigger an AWS Lambda which, on merge to main, automatically pulled in the repo + version locked Hugo + themes. It then did the static site build in-lambda and uploaded the result to the S3 bucket that backs my website.

This created a setup that now I can publish to my website from any machine with the ability to edit my git repo. I found it a wonderful mix of WordPress-like ability to edit my site anywhere along with assurance that there's nothing that can technically fail* (well, the failure would likely, ultimately block the deploy, but I made copies of my dependencies where I could, so very unlikely).

But really the main thing I love is not maintaining really anything here... I go months without any concern that the website functions... Unlike every WordPress or similar site I help my friends run.

> Beyond that, I've grown fond of 'sticking to the defaults' over the years.

This resonates with me! Both in terms of things I use and things I make - I want them to "just work"

For long term stuff like a blog, nothing seems to beat static sites generated before deployment, instead of automated tools like Hugo. I tried Hugo years ago and some tiny config or update would suddenly expose all site variables to visitors, which was an incredible security risk. Wordpress and Drupal are a war zone of attacks - judging by the server logs of any of web site. These days you can custom write or design any page, click to build all menus, site maps, rss with something as simple as gulp, and move the files out via SFTP. Fast, performant, and secure.
A few years ago, I decided to migrate my personal website to a Common Lisp (CL) based static site generator that I wrote myself. In hindsight, it is one of the best decisions I have made for my website. It started out at around 850 lines of code and has gradually grown to roughly 1500 lines. It handles statically rendering blog posts, arbitrary pages, a guestbook, comment pages, tag listings, per tag RSS feeds, a consolidated RSS feed, directory listing pages and so on.

I have found it an absolute joy to maintain this piece of little 'machinery' for my website. The best part is that I understand every line of code in it. Every line of code, including all the HTML and CSS, is handcrafted. This gives me two benefits. It helps me maintain my sense of aesthetics in every byte that makes up the website. Further, adding a new feature or section to the site is usually quite quick.

I built the generator as a set of layered, reusable functions, so most new features amount to writing a tiny higher level function that calls the existing ones. For example, last month I wanted to add a 'backlinks' page listing other pages on the web that link to my posts and it took me only about 40 lines of new CL code and less than 15 minutes from wishing for it to publishing it.

Over the years this little hobby project has become quite stable and no longer needs much tinkering. It mostly stays out of the way and lets me focus on writing, which I think is what really matters.

Ha. Well, https://taoofmac.com was ported to Hy (https://github.com/rcarmo/sushy) in a week, then I eventually rewrote that in plain Python to do the current static site generator —- so I completely get it.

I am now slowly rebuilding it in TypeScript/Bun and still finding a lot of LISP-isms, so it’s been a fun exercise and a reminder that we still don’t have a nice, fast, batteries-included LISP able to do HTML/XML transforms neatly (I tried Fennel, Julia, etc., and even added Markdown support to Joker over the years, but none of them felt quite right, and Babashka carries too much baggage).

If anyone knows about a good lightweight LISP/Scheme dialect that has baked in SQLite and HTML parsing support, can compile to native code and isn’t on https://taoofmac.com/space/dev/lisp, I’d love to know.

Babashka now has a built-in markdown library. Babashka now also has a built-in HTML parsing library: Jsoup.

Why does bb carry too much baggage? Because it has useful libraries like the above?

No, because of Graal.
I really like Hugo as well. I've found it significantly faster than Jekyll which makes iterating much more pleasant and it's a single binary to download/run vs having to deal with Ruby and its package manager.

I'm amazed there still isn't a decent free simple to host CMS solution with live page previews, a basic page builder, and simple hosting yet though. Is there one?

There's https://demo.decapcms.org/ (previously Netlify CMS) that you install and run via adding a short JavaScript snippet to a page. It connects to GitHub directly to edit content. You can running it locally or online, but you need some hosting glue to connect to GitHub. Netlify provides this but more options would be nice and I think they limit how many total users can connect on free plans. You can get something like a page builder set up via custom content blocks, but I don't think there's going to be a simple way to render live previews via Hugo (written in Go) in a browser. A JavaScript based SSG would help here, but now you have to deal with the JavaScript ecosystem.

@geerlingguy Not a huge deal but noticed (scanning with https://www.checkbot.io/) if you click a tag in a post, it has an unnecessary redirect causing a speed bump that's easy to fix e.g. the post has a link to https://www.jeffgeerling.com/tags/drupal which then redirects to https://www.jeffgeerling.com/tags/drupal/.

I did a migration to markdown, too, but I decided to backport my previous nodejs code to Go, as I wanted the editor part to be still available as a standalone binary.

This Christmas, I redesigned my website [1] into modular "middlewares" with the idea that each middleware has its own assets and embed.FS included, so that I can e.g. use the editor to write markdown files with a dynamic backend for publishing and rendering, and then I just generate a static version of my website for the CDN of choice. All parts of my website (website, weblog, wiki, editor, etc) are modular this way and just dispatch routes on a shared servemux.

The markdown editor turned out to be a nice standalone project [2] and I customized the commonmark format a bit with a header for meta data like title, description, tags and a teaser image that is integrated with the HTML templates.

Considering that most of my content was just markdown files already, the migration was pretty quick, and it's database free so I can just copy the files somewhere to have a backup of everything, which is also very nice.

[1] https://cookie.engineer

[2] https://github.com/cookiengineer/golocron

(comment deleted)
I think this is silly, and it's a hill I'm willing to die on. I wrote this in a comment yesterday, and Jeff has fully confirmed/vindicated this in his post:

SSGs are good for static sites with no interactivity or feedback. If you want interactivity or feedback, someone (you or a 3rd party service provider) is going to have to run a server.

If you're running a server anyway, it seems trivial to serve content dynamically generated from markdown - all an SSG pipeline adds is more dependencies and stuff to break.

I know there's a fair few big nerd blogs powered by static sites, but when you really consider the full stack and frequency of work that's being done or the number of 3rd party external services they're having to depend on, they'd have been better by many metrics if the nerds had just written themselves a custom backend from the start.

Jeff: I think you'll regret this. I think you'll waste 5 - 10 years trying to shoehorn in basic interactivity like comments, and land on a compromised solution.

I also used and managed Drupal and Joomla before I went to SSGs, and then finally realised there's a sensible midpoint for the pain you're feeling: you write/run a simple server that dynamically compiles your markdown - good ol' SSR. It's significantly lighter, cheaper and easier than drupal, and lets you keep all the flexibility and features you need a server for. Don't take cave to the "self hosted tech was too hard so I took the easy route that forces me to also use 3rd party services instead" option.

SSGing your personal site is the first step to handing it over to 3rd party services entirely IMO.

I run an e-commerce website on Hugo. The only non-static part is a short Python function I run in a cloud to forward the orders to Stripe.
I have a vague memory that one of the largest commenting sites on the internet, 4chan, was basically statically generated.

Every time a comment was added, it just generated a full-ass static web page.

I know this isn’t quite the spirit of self hosting, but for people that aren’t ready to self they host can use https://prose.sh which interops with Hugo. It’s a safe stepping stone into self hosting a blog for anyone who wants to get started slowly.

prose is fully open source as well: https://github.com/picosh/pico

It even has a Hugo migration repo for when users want to make the jump

https://github.com/picosh/prose-hugo

Alternatively you can use https://pgs.sh to deploy your Hugo blog using just rsync. The entire workflow starts and finishes in the terminal.

I ran Hugo when I launched my blog last year. I made 18 total posts. Probably 3/4 of those had issues when trying to publish due to issues with Hugo. Found it so frustrating.
What's the temperature on Pelican [https://getpelican.com] these days?

Best Python SSG is mostly down to Hugo and Pelican as far as I can tell.

I've always loved SSGs, but ActivityPub integration is also looking very attractive absent wider adoption of RSS.

I use pelican, with a bunch of self-made plugins, and it works very well. There's a few commits every month, so it's not a dead project.
Welcome to the dark side, Jeff! I migrated to Hugo from WordPress in 2019: https://blog.carlosnunez.me/post/neurons-are-firing-again/

I built some automation that helps me test and deploy changes to S3 as well: https://github.com/carlosonunez/https-hugo-bloggen. It's clunky but works for me! Feel free to fork/PR if you're interested, of course.

It was a great move; I couldn't be happier. Running my blog is basically free (because nobody reads it, lol, but also because it's served by S3 and CloudFront and the # of monthly requests is still within Free Tier).

At the time, some folks were questioning why I built this instead of moving to Netlify. I wanted control over how my sites were deployed and didn't want to pay some provider for convenience I knew I could build myself. Netlify got AI-pilled some time ago, which makes me feel vindicated in my position.

Just curious what you do with all the plug-ins. That’s the issue with the WordPress is replacing the plug-ins otherwise static sites are awesome
I've been considering moving from WordPress to Hugo, mostly because I'm tired of updating it all the time, and the whole wpengine stuff.

Was formatting old articles any difficult when moving to a new way of publishing?

If you already write your posts in Markdown, it makes sense for sure.

About a year ago I converted my 500+ post Jekyll blog to Hugo, overall it's been a net win but boy do I find myself looking up syntax in the docs a lot. Thankfully not so much nowadays but figuring out the templating syntax was rough at the time.

Jeff, you don't have to set draft to false. You can separate your drafts into a different directory and use Hugo's cascade feature to handle it. Also you don't have to update the date in your frontmatter if you prefix the file with YYYY-MM-DD and configure Hugo to use that.

Just a heads up, you didn't mention this in your post but Hugo adds a trailing slash for pretty URLs. I don't know if you had them before but it's potentially new behavior and canonical URL differences unless you adjust for that.

When I did the switch from Jekyll to Hugo, I wrote a 10,000 word post with the gory details and how I used Python and shell scripts to automate converting the posts, plus covered all of the gotchas I encountered. There are sections focused on the above things I mentioned too: https://nickjanetakis.com/blog/converting-my-500-page-blog-f...

I've been using Hugo for the past 3 years. Biggest lesson I learned is to just fork the theme you're using and don't use submodules. There's no rush in keeping your theme up to date. Also you have complete control over the theme when its forked. I've only had stuff break on occasion when updating to a newer version of Hugo, had to change a couple things with the theme which did not take too long to fix. Curious to see how comments will be implemented though. Does not sound straightforward to add to a SSG.
Tried to migrate to Hugo from Jekyll multiple times and have bounced off every time. Don't really know Go very well, but better than Ruby, and used this as justification -- since dealing with Jekyll updates was sometimes a headache (I use GitHub Pages for free hosting and let them build things for me when I push updates).

Instead I eventually just created an environment in nix that had compatible dependency versions to what GitHub uses and have been pleased since.