Migrating my website to Hugo + Academic + ox-hugo

Update <2021-05-30 Sun>: A template of this website is now available on GitHub.

Being stuck at home during the pandemic, as miserable as it is, actually helps me to redesign my working environment. One of the many outcomes is this new personal website powered by the Academic theme for Hugo. I hope you will agree with me that it just looks awesome!

For the rest of this blog post, I will explain the workflow to generate this website. I hope you may find it useful when designing your own website.

Table of Contents

The Hugo framework

I admire the front-end web developers who still hand write HTML and CSS, but those are simply too much for me. If you are like me who just wants a personal website that can keep track of one’s work, chances are you would like to use some static site generator. When I was young and had my first encounter with the internet, Microsoft Frontpage and Dreamweater were the most popular website generator.

Static site generators

But we are well past that time and there are many much better choices today. One great framework is the Markdown, a lightweight markup language that is used in GitHub readme pages and deeply integrated with statistical computing with the R Markdown. Many static site generators (including Jekyll and Hugo) are able to automatically generate HTML codes from Markdown. This is a giant life-saver because Markdown is so much more readable.

After some brief research I decided to use Hugo. Based on my reading, Hugo is renowned as “the world’s fastest framework for building websites” and many developers were extremely happy about it. But for me, the killer was two extensions to Hugo: the Academic theme that implements many use features for academic researchers, and the ox-hugo backend that exports .org files straight to Hugo-compatible Markdown files. As an academic who already uses Emacs for most of the day-to-day work, these features are extremely convenient for me.

Installing Hugo in Mac OS X is straightforward with homebrew. Simply run

brew install hugo

Content management in Hugo

Let’s first take a look at how Hugo works. The most useful thing to know is Hugo’s organization of content source. In particular, the most important is the content folder, which contains all the Markdown files needed to generate the website. Here is a sample structure for the content folder from Hugo’s official documentation (the base URL for this site is https://example.com/):

└── content
    └── about
    |   └── index.md  // <- https://example.com/about/
    ├── posts
    |   ├── firstpost.md   // <- https://example.com/posts/firstpost/
    |   ├── happy
    |   |   └── ness.md  // <- https://example.com/posts/happy/ness/
    |   └── secondpost.md  // <- https://example.com/posts/secondpost/
    └── quote
        ├── first.md       // <- https://example.com/quote/first/
        └── second.md      // <- https://example.com/quote/second/

As you can see, each Markdown file in a directory under content generates a webpage. Notice that _index.md has a special role in Hugo—it allows you to add front matter and content to the list pages. See here for more detail.

Front matter in Hugo

Another important concept is the front matter of a Markdown file that contains metadata and options for the content. Some popular formats are TOML and YAML, which are much more human friendly than JSON. The following block contains the first few lines of this blog post. The front matter is the lines between +++ (which means it is in TOML):

title = "Migrating website to Hugo + Academic + ox-hugo"
author = ["Qingyuan Zhao"]
date = 2020-06-13
tags = ["Workflow"]
draft = false

Being stuck at home during the pandemic, as miserable as it is, actually
helps me to redesign my working environment....

Apart from draft which is a option for the Academic theme, all other fields are standard for Hugo Markdown files.

Hugo themes

There are many cool themes for Hugo that you can immediately use. As far as I know, they are useful in two ways. First, all the page styles are already pre-defined and many of them look awesome! Second, they also provide convenient templates for the front matter. As an example, I was initially considering to use the Jane theme for this website. Similar to most other Hugo themes, it is really easy to install and get started; an example site can be found in its GitHub repository, which generates this demo page. One thing I especially like about this theme is how it allows the reader to focus on the website content. Eventually I did not choose it because it is not powerful enough for all the different functions I needed, but I would highly recommend it if you just want to write blogs.

From Markdown to HTML

After creating all the Markdown content and selecting a theme, you can preview the website by running

hugo server

from the website directory. This builds the website and creates a local web server to host it. It generates a link (the default is http://localhost:1313/) which can be pasted into a web browser. In the background, the hugo server also detects any change to the content and updates the website automatically.

To public the website, first execute hugo from the website directory. This builds all the website pages in the public/ folder within seconds. You can then upload that folder to an FTP server. For me, this amounts to

rsync -avz --delete public/ qz280@ssh.maths.cam.ac.uk:~/public_html

See here for other options to host and deploy your website.

The Academic theme

Academic is a Hugo theme designed for academic researchers. To me, it is a website builder with just the right balance of complexity and flexibility. There are many ways to install the Academic theme. I prefer the Git option by forking and cloning the Academic Kickstart GitHub repository. You can then modify the content of the startup website and customize its styles.

Content management in Academic

Academic has a convenient content management system that is inherited from Hugo. This is currently how my website directory looks like:

├── assets
│   ├── images
│   └── scss
├── config
│   └── _default
├── content
│   ├── authors
│   ├── home
│   ├── news
│   ├── post
│   ├── project
│   ├── publication
│   ├── talk
│   └── teaching
├── content-org
├── data
│   ├── fonts
│   └── themes
├── resources
│   └── _gen
├── scripts
├── static
│   ├── admin
│   ├── files
│   └── img
└── themes
    └── academic

Unsurprisingly, the content folder contains all the Markdown files for website content. Most of its sub-directories correspond to a section of the webpage; in particular, home corresponds to the homepage of your website. Another unique folder is the authors, which contains basic information about the website owner and all other authors (not needed for a personal website). The content-org contains the org-mode files that generate some or all of the Markdown files in content. I will go through this later on in the post, but it is of course not needed if you don’t use org-mode. The config folder contains all the important website settings offered by the Academic theme. See its documentation for more information.

Organizing your work

A nice feature of the Academic framework is the templates for publications, talks, projects, and many other academic-related objects. For example, I recently arXived a paper on the selection bias in COVID-19 studies. To add this new publication to my webpage, I can execute the following command

hugo new --kind publication publication/covid-19-bets

This generates a Markdown file publication/covid-19-bets/index.md with YAML front matter from the publication template. I can then add all the relevant information about this publication to the Markdown file. This is how the beginning of this file looks like right now:

# Documentation: https://sourcethemes.com/academic/docs/managing-content/

title: "BETS: The dangers of selection bias in early analyses of the coronavirus disease (COVID-19) pandemic"
authors: ["admin", "Phyllis Ju", "Sergio Bacallado", "Rajen Shah"]
date: 2020-04-16
doi: ""

# Schedule page publish date (NOT publication's date).
publishDate: 2020-06-13T21:28:45Z

# Publication type.
# Legend: 0 = Uncategorized; 1 = Conference paper; 2 = Journal article;
# 3 = Preprint / Working Paper; 4 = Report; 5 = Book; 6 = Book section;
# 7 = Thesis; 8 = Patent
publication_types: ["3"]

As you can see, the YAML fields record important metadata about the publication, which are used by Academic to automatically generate this nice webpage. This same workflow apples to talks, projects, and other content types provided by Academic.

Widget pages

An important feature of Academic is its widget pages. They are essentially custom page blocks that summarizes the information in the other pages. By default, the homepage is a widget page with many built-in widgets:

> ls content/home
about.md           demo.md            hero.md            projects.md        tags.md
accomplishments.md experience.md      index.md           skills.md          teaching.md
contact.md         featured.md        people.md          slider.md          welcome.md

Personally, I prefer a clean homepage and would use separate section pages to organize the website. So my homepage only contains two widgets. Additionally, I created a custom widget page called news to make announcements and display new content.

Customization in Academic

The are several important files to modify when building your own website:

  • config/default/config.toml General configuration for Hugo.
  • config/default/params.toml Parameters for Academic.
  • config/default/menus.toml Configuration for the menu bar.
  • content/authors/admin/_index.md Information about the website owner.

Advanced customization can be found here.

The ox-hugo exporter

Finally, I use ox-hugo, an Org mode to Hugo exporter, to generate blog posts and other text-rich content in this website. Since the beginning of my PhD, I have gradually become an heavy user of the extremely extensible text editor Emacs. Previously I was mostly just using Emacs for writing R and \(\LaTeX\) with the amazing ESS and AUCTeX modes. I saw great reviews of the Org mode before and started to appreciate it as my duties pile up after becoming an independent investigator. Org mode, as its name suggests, is a great way to keep oneself organized. Besides keeping notes and managing TODO lists, Org mode is also great for writing documents. It has powerful backends that can export .org files to LaTeX, HTML, Markdown, and other formats.

A picture is worth a thousand words. This is the .org files that generates the blog post you are currently viewing.

I followed the “one post per Org subtree” format recommended by the ox-hugo author. So my content-org/ folder has only one .org file:

> ls content-org/

Each website section corresponds to a level-1 heading (one *), and each blog post is contained under a level-2 heading in Post. Each heading has some properties (and inherit the properties of its ancestors) that are exported to TOML or YAML front matter. If the EXPORT_FILE_NAME is specified, content under that heading is then exported to the corresponding section in the content folder:

> ls content/post/
_index.md      migrating.md   mr-software.md

To export all subtrees to Hugo Markdown, simply press C-c C-e H A in Emacs. The local Hugo server then picks up the content change and updates the website. More information about ox-hugo (including many advanced features that I am still learning) can be found in its online documentation.

So that’s it for now! Feel free to leave a comment below. I will update this post if I make any major modification to this workflow in the future.

comments powered by Disqus