A comparison of the pros and cons of Hugo and Jekyll, two very popular Static Site Generators, from the perspective of a user of both platforms who writes their own templates.

Static Site Generation (SSG) has been growing in popularity in recent years. By pre-rendering your website content down to simple HTML, you get stunning performance from even lightweight hosting and as your content management is all done offline, it also removes a lot of concerns around security.

I’d previously been using Jekyll for all of my static sites (Connecting to Host, ShyGuys, this blog) but due to COVID-19 I find myself spending more time on Windows, where setting up Ruby Gems feels like considerably more work than on macOS. In my search for an easier life, I stumbled across Hugo - a SSG wrapped up in a single binary you can run without dependencies.

If you’re coming from a strong React or Vue background, there are SSGs that probably better fit your needs than Hugo or Jekyll. Solutions such as Gatsby.JS or Grindsome will build on your existing knowledge and use JavaScript as their core. However, if you’re looking to build your own HTML template and write content in MarkDown, read on!

Factually, here are the main differences between the two platforms;

Hugo Jekyll
Language Go Ruby
Installation Standalone Exe Ruby Gems
Content Formats Markdown, AsciiDoc, RST, HTML Markdown, HTML
Custom Shortcodes Using Templating Engine Using Ruby
Plugin Support No Yes (Ruby)
Debug Server Yes Yes
Github Stars 46k 41k

Showdown

If you’re considering both Hugo and Jekyll for your next static-site, here is a breakdown of how the two compare on various topics.

If you are just looking for a short-summary, head straight to the Summary and Conclusions!

Installation

Hugo is distributed as a single executable file with support for macOS, Windows and Linux. On macOS in particular, you can install Hugo using Homebrew with brew install hugo and run a test server on an existing site using hugo server -D. It’s almost as easy on Windows (just download the executable) and it’s also trivial to run Hugo as a post-commit step without using Docker.

Jekyll is built on top of Ruby and requires you to have a full Ruby development environment installed to build your site. On macOS this is fairly trivial - Ruby is already installed so you just need to install the relevant gems using gem install bundler jekyll. After that, you can start testing your site using bundle exec jekyll serve. On Windows however, it’s a bit more of a pain. I’ve had some issues installing Ruby in the past - so I imagine your best route is to look into the “Windows Subsystem for Linux” (WSL) and effectively install Linux inside your Windows partition.

Summary: It’s much easier to get up and running with Hugo without running into Ruby issues some day down the line. With that said though, the ease of installation of Hugo also means that extending Hugo with additional functionality requires rebuilding the whole product from scratch.

Content Organisation

Both Jekyll and Hugo primarily use Markdown and HTML with custom front-matter for content management. For simple content, it’s usually preferable to use Markdown and fallback on HTML if you need to insert fancy details in your page. Both platforms work well with HTML mixed into Markdown and both allow you to create your own includes/shortcodes so that you can have parameterised and reusable snippets of HTML that you can reuse throughout your site. Both platforms now also understand different collections of content - i.e. you can have “pages” which use one template, “blog posts” which use another and “projects” which looks different again.

Hugo has some asset processing out of the box, but it’s a little weird and awkward to setup. For instance, I wanted to automatically resize some images to use in my custom {{ thumbnail image=”/path/” size="320x240” }} shortcode. However, image resizing only works from your asset directory, not for your static content - so I had to configure both to the same path - which felt like a kludge. Jekyll on the other hand didn’t support resizing out of the box. While I found some plugins, I ended up building one myself. While it was great to have the plugin available, it was sometimes painful trying to install that plugin on certain systems, due to a dependency imagemagick (rmagick) that caused issues.

Jekyll makes it possible to generate pages from a datasource, such as a JSON file or CSV file. On the ShyGuys Site we generate a few hundred pages from a JSON file using a Ruby plugin that’s about 30 lines of code. These pages are built as part of the Jekyll build-phase, meaning Jekyll understands they exist even though no md files exist. While Hugo supports loading data from these sources for use in your templates, it doesn’t support generating individual pages from these data sources. If you wanted to solve this in Hugo, you would need to write a custom script to delete and rebuild your md files from your datasource in another language than Python or JavaScript.

Hugo does support some additional formats out of the box if you have the pre-requisites installed. Hugo also allows you to manage content as AsciiDoc, RST, Pandoc and “Emacs Org-Mode”. On the flip-side, Jekyll has a number of plugins that also provide additional content formats (including AsciiDoc, RST and Pandoc).

Summary: For most users, both Jekyll and Hugo offer the same here - you will likely primarily use Markdown with a bit of HTML mixed in where required. If you rely on AsciiDoc or Pandoc, you might want to lean towards Hugo as you get support for those formats out of the box, but Jekyll provides support for those (and more) through extensions. If you have more demanding needs, such as generating content from a remote end-point or json file, Jekyll makes it easier to build that in Ruby instead of hacking a solution in.

Templating

Templating in Hugo and Jekyll is a reasonably similar affair. Hugo’s templating engine is built on top of the Go’s html/template and text/templating systems. Jekyll’s templating is built on top of Liquid. Both make it very easy to do simple substitutions of variables into content, both give you some good scope for breaking your content down into reusable components and both have a bunch of strange little quirks that will catch you up along the way. It’s worth noting that Hugo does a better job of enforcing a split between the template and your custom layouts, whereas Jekyll lets you get away with being a bit more sloppy (for better or worse).

In all honesty, both templating engines are good overall. They give you access to global variables (such as the site URL) and a list of functions to make it easier to create content from data or variables. I would say that Jekyll’s templating is slightly easier to get your head around when it comes to syntax, but there are some oddities around the variable context in Jekyll which bring it back to an even-playing field. For instance, in Jekyll, if you have a variable that iterates in a template that’s used multiple times, the variable state persists across different pages - leading to some confusing moments.

Here are two examples of how the templating languages look;

Hugo

{{ if or (isset .Params "alt") (isset .Params "caption") }}
  {{ "Some Text Here" | countwords }} 
{{ end }}

Jekyll

{% if page.alt != nil or page.caption != nil %}
  {{ "Some Text Here" | number_of_words }}
{% endif %}

Hugo handles a lot of the work out of defining the required list/taxonomy/archive pages for content for you but in Jekyll I remember building those myself - but once again, that gives more control over exactly how those pages look and are constructed.

Summary: With everything said, things are pretty even in the templating region. Both languages have their quirks, but both are pretty powerful overall. I would say that Jekyll is a little bit easier to get started with in the templating department, but only by a fraction. After you spend a day with either, you should be in a good position to build what you want, and both with give you a small number of headaches along the way as you figure out the quirks.

Speed (& Development Speed)

Written in Go and built for speed, one of Hugo’s main selling points is that it’s blazingly fast. Some benchmarks show that for a 100 page site that Jekyll builds in 3-4 seconds, Hugo builds the same amount of content in much less than a second. On bigger sites with thousands of pages generated from JSON files say, you could be looking at a different between a second or two and a minute or two.

However, both come with development servers which don’t require a full-rebuild when editing content files and, when editing templates in Jekyll, you can limit the number of posts and pages generated on the command line to make it more responsive. Also worth noting here, is that Hugo also injects some JavaScript when hosting using the development server with automatically refreshes your page whenever you make an edit. This is super helpful if you develop like I do - constantly saving your work in the text editor and tabbing back to the browser to see the result.

Summary: Hugo wins hands down in this area. How much that matters to you will probably be determined by how big your site is. If you’re only working with up to a hundred pages, the difference isn’t going to be a problem but with bigger and bigger sites - you will notice the impact more.

Flexibility & Extensibility

Both platforms provide the ability to build your own shortcodes which can be used in articles to make it easier to reuse HTML content across your site. For instance, I have a thumbnail shortcode in both platforms which resizes a source image and pops an img tag into the page with the relevant alt tags setup as defined in the shortcode.

One big difference between Hugo and Jekyll is that Jekyll provides support for Ruby plugins to add any functionality you could ever need to your site generator, whereas Hugo has no support for plugins. If you find yourself really needing a new feature in Hugo in the future, it will either be a pre-build hack or you’ll need to write it in a fork of the whole Go project and maintain that branch. On the other hand, Jekyll makes it super easy to drop a ruby script in the plugins folder which can do practically anything, and there is a very healthy set of plugins available on Github.

Summary: If you need custom functionality or the ability to generate pages from another data source, Jekyll wins hands down. Hugo does come with more features out of the box, so it’s unlikely most users who are putting together a blog or static site for their business will need much more, but if you find yourself wanting to build a review site or something with lots of custom content - Jekyll will give you the extra power you need to build that big site.

Documentation

Both platforms have a good level of very readable documentation on installation and usage, as well as a list of shortcodes/filters available when building articles. Both have a readily accessible list of shortcode you can use in your articles/templates to build your site. Naturally, you’ll run into moments when you wish certain features had slightly more thorough examples while bashing your head against the wall trying to get some feature to work - but I think that’s to be expected when learning a new platform with so many components.

Summary: Its pretty even when it comes to documentation. I would say that Hugo’s documentation is a bit more thorough, but that means that it’s sometimes hard to get the beginners perspective on a topic (you get the full text-book answer, instead of one aimed at someone learning fresh), but it’s great to see every feature has a manual so you can dig and learn. On the flip side, Jekyll doesn’t have quite as thorough documentation, but it’s still very good - and when it comes to building plugins or templates, GitHub is littered with thousands of examples for you to peak at for reference.

Asset Pipeline

I don’t have much experience using Webpack or SASS outside of environments where it’s made super easy to use them (i.e. React/Vue), so I can’t really comment on how well these features work in Jekyll and Hugo. However, from reading the documentation it seems like Hugo has built-in support for SASS, Webpack, minification and bundling (as well as other features) through Hugo Pipes. Jekyll supports SASS out of the box and there are tutorials online showing ways to use Jekyll with Webpack and minify, sometimes using plugins.

Summary & Other Thoughts

As always with technology, it’s rarely a simple answer of one being better than the other. Both Jekyll and Hugo are very strong single-site-generators for people who don’t come from a strong React or Vue background, so it’s really about assessing your needs and finding the one that fits. Hopefully, the table below will help you make that choice.

Hugo Jekyll
Installation Very Easy
Standalone Exe
Average
Ruby Gems
Content Organisation Good
Markdown + HTML + Several Others
Great
Markdown + HTML + Anything via Plugins
Templating Good Good
Speed Blazingly Fast
50-70x Faster than Jekyll
Okay
Can take minutes for 1000+ pages
Flexibility Minimum
Lots of Core Features but no plugins
Great
Full plugin support with thousands available
Documentation Good
Sometimes like trying to find a cake recipe on Wikipedia
Good
A few gaps but the extension library provides more examples
Asset Pipeline ?? ??

In conclusion, Hugo is significantly faster for larger sites, is a little easier to get started with and offers more features straight out of the box. However, Hugo is ultimately limited by its lack of a plugin system and if you hit the boundaries of what the platform offers, you’ll likely be in trouble.

Jekyll is a bit more finnicky overall and doesn’t have as many features off the shelf. However, being able to build plugins using Ruby and having access to a wide set of extensions and themes that are already available, Jekyll allows you to build more complex sites that Hugo probably won’t handle - especially if you want to generate pages from json files or end-points.

At the end of the day, you really can’t go wrong with either choice as both are excellent static site generators with a big community of helpful developers.