Create a website with Wowchemy and Hugo

Ever since I realised that I could host static websites in an S3 bucket, I have wanted to build a website-based portfolio for myself.

Recently, as I was getting back into R, I learned about the Rmarkdown as an easy way to generate html that includes math and code. Further down the rabbit hole, I came across Hugo and Hugo themes, and I figured that the time had come to finally build the site.

In this short post, I am outlining how I have built this site. I will not elaborate too much on how I am hosting the site, but I will put in a few pointers.

Rmarkdown

While perusing the excellent R for Data Science book, I learned of Rmarkdown and knitr. Rmarkdown are essentially notebooks like Jupyter notebooks and they facilitate writing code (and not just R), math, and markdown text in one text file. knitr is an R library that knits .Rmd files into html. This means that I can write whatever I want, including stuff with math and plots, in plain text files and then generate static html at the press of a button. Ideal for building a data themed website. Yay!

So the most essential part of my workflow involves writing posts or projects in Rmarkdown and knitting them into html with knitr.

Blogdown

html pages alone do not create a website, and I immediately started looking for a way to turn my individual pages into a coherent site. The R package blogdown does just that or, more precisely, it is an interface to the static website generator Huge, which does just that. blogdown simply automates the process of converting Rmarkdown to markdown or html so that Hugo can pick them up and generate the site. With blogdown, I never have to leave the comfort of RStudio to build my entire website.

Hugo and Themes

Hugo is a standalone tool for generating static websites, and there there are many ways to work with it. I like working through blogdown because it gets me stated easily and I can install (and update) Hugo with a single line of R:

install.packages("blogdown")
library(blogdown)
blogdown::install_hugo()

Once Hugo is installed, we can get to building a site. Rather than building everything from scratch, we can take advantage of premade themes. There are lots of themes to choose from. I went with the starter-academic theme from Wowchemy because it is well-maintained, documented, and very customisable.

blogdown::new_site(theme = "wowchemy/starter-academic")

That sets up a site that we can start adding to. For instance, I created this post like this:

blogdown::new_post(title = "Create a website with Wowchemy and Hugo",
                   ext = '.Rmd',
                   subdir = "post")

Wowchemy and Configuring the Site

Out of the box, the theme comes with a lot of examples and superfluous elements that do not need to be on every site, so a bit of pruning and tuning is in order. With the starter-academic theme from Wowchemy most things can be managed through the config files and elements can be deleted by just removing the corresponding folder. The Wowchemy site offers great documentation, suggestions, and an overview of what can be safely deleted.

In addition to configuring the theme, I also added a bit of custom scss, which can be easily done by writing it into a file at /assets/scss/custom.scss. I removed the box-shadow of the navbar in the light theme and I also wanted to add both a linear gradient and a texture image to the background of my widgets - something that is not possible through the regular configs. I spent a long time configuring the site to look just like I wanted it to - and I’ll probably keep making tweaks. The best part about building the website with Hugo and Blogdown is that I do not need to rebuild the whole site just to see how a small change looks. While working on the site, I let Hugo serve the site:

blogdown::serve_site()

I like to open the site in a browser window and get a real-time view of changes to the site. ## My Workflow Viewing the site like this also works great, even if I am just writing content. If I am working in Rmarkdown and serving the site through Blogdown, then every time I save changes to to my file, Blogdown will invoke knitr to generate html (or markdown) and Hugo will pick it up and serve it.

When writing content, my workflow looks like this: I open my project and add a new post or project

library(blogdown)
blogdown::new_post(title = "New Project",
                   ext = '.Rmd',
                   subdir = "project")

I then let Hugo serve the site

blogdown::serve_site()

I edit my post in Rmarkdown and let Blogdown and knitr worry about converting it to html. Once I am done, I build the site

blogdown::build_site(build_rmd = TRUE)

build_rmd will re-knit Rmd files to html. The final output appears in the public/ folder, ready to deploy. I just upload the entire content to the S3 bucket where I am hosting the website. Besides AWS S3, there are other options, such as Netlify and GitHub Pages, for hosting static content. I keep the content and configurations under version control in repo on GitHub.

Anders E. Nielsen
Anders E. Nielsen
Data Professional & Research Scientist

I apply modern data technology to solve real-world problems. My interests include statistics, machine learning, computational biology, and IoT.