Running a Blog with Hugo, Emacs, and Netlify

Running a Blog with Hugo, Emacs, and Netlify

I’ve been keen to get a blog up and running and thought it would also be a good opportunity to play with static sites a little more. Static sites are finally starting to expand beyond just documentation and personal sites with the likes of Next JS Commerce and their Ecommerce partners.

The biggest challenge I find in writing and maintaining a blog is the technical maintenance and ease of use. Static sites solve a lot of the challenges here, but can still be cumbersome if you don’t live in their flavor of markdown or take notes/document your build steps.

Hugo is the framework I chose to use here. It’s built on top of Go, is super simple to setup and use, and allows for a lot of customization without having a lot of difficulty associated with that. For light customizations, I haven’t encountered anything a beginner/intermediate web developer couldn’t handle easily.

I’ll walk you through how I setup, run and deploy this blog, 100% from a single text file running entirely on a ChromeOS Lenovo Duet tablet. Lots of the services and tools used are interchangeable with similar alternatives. In addition to everything below, I’ll assume you are familiar with basic linux tools and commands, including git. I can’t imagine you’re reading an Emacs blog post and are not, but you never know.

If you’re using ChromeOS, you’ll also need to setup the built in linux environment.

This post will cover the initial setup and getting the blog up and running. A subsequent post will cover registering a free domain with Freenom, setting up Netlify and Github deployment and automation. By the end, we will have a single org file you write to, which deploys with a simple bash script that publishes the site live.

Tools Used

Setting up Hugo

Hugo is pretty easy to setup. You’ll need to decide which theme you’re going to start with at this point. If you’re not using Beautiful Hugo as a starting point, the theme this site uses, be aware you may run into certain gotchas with Ox-Hugo. I will cover the nuances I’ve seen and overcome with Beautiful Hugo, but things like complex custom themes, as we’ll see with Beautiful Hugo’s bigimg tag, can be tough to put in place and quickly starts to steal the benefit of using an ‘easy to maintain’ system.

Follow the guide here to get started, making sure you have git installed beforehand. The Hugo documentation examples use homebrew and macports which are not available on ChromeOS. You can easily install Hugo on Chrome OS with apt.

sudo apt-get install hugo

Once you’ve confirmed the server starts up and is accessible at localhost:1313, remove the example MD post file. You should also probably name the site something besides testsite.

ChromeOS/Crostini localhost issues

If you’re using ChromeOS, you may not be able to reach the Hugo site at localhost:1313 outside of Linux. From my reading, Crostini tries to make localhost accessible across containers, but fails with Hugo for a couple of reasons.

Your options are to install a browser in the linux container(chromium, firefox), or run Hugo locally with some additional options. We need to change the baseURL of resources and the interface the server will bind to. Run the command below and access Hugo at penguin.linux.test:1313 inside ChromeOS.

hugo server --bind `hostname -I` --baseURL `hostname -I`

Consider setting this up as an alias in your .bashrc/.zshrc for easy use.

Configuring the Site

You’ll need to modify the config.toml file found in the root of your site to put some basic settings in place.

Here are the basics you’ll need. You can find a more complete example in themes/beautifulhugo/exampleSite/config.toml.

baseURL = "[your site's URL with protocol]"
languageCode = "en-us"
title = "[your site's title]"
theme = "beautifulhugo"
enableRobotsTXT = "true"
  logo = "img/logo.png"

Setting up Ox-Hugo and Emacs

Now that you have a functioning Hugo site running locally, let’s figure out our content workflow using Emacs and Ox-Hugo.

I am using Doom Emacs, but Ox-Hugo will work with any version >24.4 of Emacs and version >9.0 of Org. The package is available on Melpa.

If installing in Doom, simple add the following line to your .doom.d/packages.el file:

(package! ox-hugo)

then run M-x doom/reload and wait for the package to install. You should now have an Ox-Hugo option in your org-export menu (C-c C-e)

Setting up the File

Here we will setup the single file that controls all content across the Hugo site. If you wish to use another structure, for example a single org file per post, see this page. Create a new directory in your site’s root called content-org and create a new org file in it called

mkdir content-org
touch content-org/

You’ll want to setup some things specific to Ox-Hugo at the top of your org file.

​#+hugo_section: ./
​#+hugo_base_dir: ../
​#+hugo_custom_front_matter: :author "yourname"

If you’re using beautifulhugo, make sure to add the author tag as the pages will fail to compile without it.

Now you can create a top level heading, Posts, and write your pages/articles as subheadings. You can also create additional top level headings to create categories of pages.

Create a first post with the following property values.

​* Posts
​** My First Post
:EXPORT_FILE_NAME: my-post-title
:EXPORT_DATE: 2020-11-29
this is the text of the post.

If you want to use bigimg, as seen in this post and most others on the site, you can use the following within the post. I place mine just under the Properties drawer, but it can go anywhere except in the Properties drawer. There may be a better way to do this, but I have not found it.

​#+begin_src toml :front_matter_extra t
bigimg= [{src="/img/hugoemacs.png"}]

Save the file and initiate org-export by pressing C-c C-e and export the entire file using Ox-Hugo using H A. You can use H H if your cursor is at a heading to only export that page or set of pages.

Now you should be able to spin up the development server and see your post.

hugo server --bind `hostname -I` --baseURL `hostname -I`

Next Time

Next time we’ll cover the rest of the deployment setup as well as setting up things like GA, comments and a simple subscription button. Thanks for reading and please leave a comment if this helped you out.

See also



Excellent post! I was wondering your thoughts regarding Hugo vs Jekyll. Also, is disqus and similar comment tools possible?


I’ve setup Jekyll in the past but didn’t get much further than getting everything stood up. My experience with Hugo was much better, though I haven’t tried Jekyll in several years.

Disqus is very easy to setup in Hugo. I have staticman running here, which I’ll cover setting up in the next post.