Potentially Useful

Writing boring posts is okay

Using RStudio and RMarkdown with Hugo

in: Meta Programming Data Science tagged: R

I converted my site to Hugo recently, and I finally figured out a workflow to create blog posts using RMarkdown from inside RStudio. None of the instructions that I found online worked the way I wanted (for instance, hugodown requires a specific out-of-date version of Hugo), so I’m sharing my workflow in case it’s useful for anybody else.

Things to do once

There are a few basic setup steps that should only need to be performed once.

Setup Hugo

Hugo setup is beyond the scope of this post. I mostly followed this quickstart guide.

Set a HUGO_ROOT environment variable

Create a new environment variable HUGO_ROOT and set it to the directory in which you created your site. In my case, I’m using:

HUGO_ROOT="~/web/www.eamoncaddigan.net/"

There are (too) many ways to set an environment variable. I edited ~/.profile, but ~/.bashrc will work for many folks. Using ~/.Renviron would also be appropriate if you’re not planning to use this variable for anything outside of R and RStudio.

Create a location for RMarkdown files outside of Hugo

You could keep your .rmd files in your Hugo site, and it might even be possible to have Hugo knit them for you. But since I’m currently on my third static site generator, I wanted to use a separate git repository for blog posts, outside of the rest of my site configuration.

Things to do for every post

Here are the steps to take every time you create a new blog post.

Launch the Hugo server

Running Hugo’s built-in server lets you preview your post as you work on it. Run the following command in the shell:

hugo server -DF

When you initially run this in a terminal, it will print a URI at which you can point your web browser, e.g., http://localhost:1313/. Go ahead and open that in your browser.

Create a new RMarkdown file in RStudio

When you create a new RMarkdown file in RStudio, you can fill in a title for your post in the GUI, or you can do it later. It doesn’t matter which output format you select since we’re going to change that in the next step.

Edit the RMarkdown YAML

Here’s the YAML block for my last post:

---
title: "Labeling bar charts (and other graphics) in ggplot2"
description: "How to combine stats and geoms to simplify complex plots."
date: 2022-07-08T19:32:57-04:00
draft: False
knit: (function(input, ...) {
    rmarkdown::render(
      input,
      output_dir = file.path(Sys.getenv("HUGO_ROOT"), "content/posts")
    )
  })
output: 
  md_document:
    variant: markdown
    preserve_yaml: true
---

Change the title, description, and date as appropriate for your post, and set draft to True for now.

The function used with knit is invoked when you press the “Knit” button in RStudio. It specifies that the rendered content (a markdown file) is put in $HUGO_ROOT/content/posts.

The options passed to output tell knitr to generate Markdown output by default. Preserving YAML is important because Hugo uses that to organize posts, and the markdown variant has good code highlighting, etc.

You might want to set tags, I ought to start doing that soon.

Set chunk and knit options

Set knitr chunk and knit options in the first code chunk of the file:

knitr::opts_chunk$set(
  echo = TRUE,
  fig.path = file.path("figs", 
                       sub("\\.Rmd$", "",
                           basename(rstudioapi::getActiveDocumentContext()$path)),
                       "")
)
knitr::opts_knit$set(
  base.dir = file.path(Sys.getenv("HUGO_ROOT"), "static"),
  base.url = "/"
)

These options ensure that figures are put in the correct local directory, and that the links will work online. This specific configuration places figures in http://example.com/figs/rmarkdown-filename/chunk-name-N.png, and you can tweak this as you see fit. You can pass additional named arguments to knitr::opts_chunk$set() that you like, such as fig.width.

Write a good post

If it’s really good, please let me know about it!

Clicking the Knit button in RStudio will create a new markdown file inside your local Hugo site. The Hugo server will see the changes and generate a new site, and your browser should refresh the site to display the changes (Hugo injects special JavaScript to do this when you’re previewing with its server).

Finish up

When you finish your post, set draft to False in the YAML, kill the Hugo server, and run hugo (with no additional options) to generate your static site. Upload that site to your host and feel good about freely sharing your knowledge with the broader community.