Hugo

Overview

Hugo is a very popular open source website publishing system. Pages in Hugo websites are typically written in plain markdown, so don’t have a straightforward way to automatically and reproducibly incorporate computational output.

Using the Quarto hugo format, you can incorporate computational output (e.g. R or Python code that produces plots) into Hugo websites. This article explains how.

See the Hugo format reference for a complete list of all options available for Hugo output.

Site Config

There are a couple of changes you should make to your Hugo config.toml in preparation for using Quarto with Hugo. First, make sure that .qmd and .ipynb files are not published as part of the site:

ignoreFiles = [ "\\.qmd$", "\\.ipynb$" ]

Next, configure Hugo’s markdown renderer to allow raw HTML (as many R and Python packages will produce computational output using raw HTML rather than markdown):

[markup.goldmark.renderer]
unsafe= true

Creating a Page

Hugo articles and posts that use Quarto should live in their own directory (taking advantage of the Hugo Page Bundles feature). This allows any content generated/referenced by the page (e.g. plot output) to live right alongside the markdown source.

To add Quarto documents to a Hugo site:

  1. Create a directory within content that will hold your Quarto article.

  2. Add an index.qmd document to the directory. When rendered this will create an index.md, which in turn will ensure that Hugo treats it as a Page Bundle (automatically copying images and other referened resources to the publish directory).

  3. Add the requisite Hugo front matter, then also specify format: hugo and any other required Quarto options.

For example, let’s say we wanted to create a new article named hello-quarto within the content directory. The filesystem would look like this:

mysite/
  content/
    hello-quarto/
      index.qmd

Here’s what the source code of index.qmd might look like:

---
title: Hello, Quarto
date: "2012-04-06"
categories: 
  - Matplotlib
  - Coordinates
format: hugo
jupyter: python3
---

## Polar Axis

For a demonstration of a line plot on a polar axis, see @fig-polar.

```{python}
#| label: fig-polar
#| fig-cap: "A line plot on a polar axis"

import numpy as np
import matplotlib.pyplot as plt

r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.grid(True)
plt.show()
```

Workflow

Rendering

Generating pages for Hugo requires just a simple Quarto render:

quarto render mysite/content/hello-quarto/index.qmd

Whenever your render the index.qmd file, Quarto will execute the code in the file (writing any generated plots, etc. into the article’s directory) and then generate an index.md file that is subsequently processed by Hugo.

Note that the index.md file is only updated when you explicitly render with Quarto. Running the hugo command to build your site just renders the index.md file — if you want to regenerate this file based on updated code or data you need to explicitly quarto render it.

Live Preview

To setup a live preview workflow for a given page or post, start by running the hugo serve command for your hugo site:

hugo serve

Then, use quarto preview for the particular .qmd file you are working on:

quarto preview index.qmd

Changes to the index.qmd file will result in an updated index.md, which hugo serve will in turn pick up and use to refresh the current preview.

Shortcodes

Note that Hugo shortcodes and Quarto shortcodes share the same basic syntax (e.g. {{< var foo >}}). This is normally not a problem as shortcodes not recognized by Quarto are passed through unmodified to Hugo.

However, in some cases the use of a Hugo shortcode throws off Pandoc markdown processing, and its necessary to “protect” the Hugo shortcode from processing by Pandoc. This can typically be handled by escaping the shortcode with an extra brace. For example:

{{{< ref "foo/index.md" >}}}

It’s possible that this won’t be enough if the presence of the shortcode changes how Pandoc processes the surrounding markdown (e.g. this is currently known to occur for links). In this case you need to use a markdown raw block around the entire construct. For example:

```{=markdown}
[click here]({{< ref "foo/index.md" >}})
```

Or for inline content, use a markdown raw inline:

For more info, `[click here]({{< ref "foo/index.md" >}})`{=markdown}

WebTeX Math

The hugo format renders LaTeX equations using standard dollar-delimited inline ($...$) and display ($$...$$) syntax. However, if the web environment you are publishing into doesn’t support dollar-delimited math, you can alternatively use WebTeX to display math. This is done by setting the Pandoc html-math-method to webtex. For example:

format:
  hugo:
    html-math-method: webtex

The webtex method works for any web page that can display images, and requires no special JavaScript or CSS. Any inline or display equations contained within your document will be converted to an image URL that requests a rendered version of the equation. For example, the following markdown:

$x + 1$

Will be converted to:

![](https://latex.codecogs.com/svg.latex?x%20%2B%201)

Dark Background

SVG is used as the default rendering method because it has the best overall appearance. However, if your hugo document is being rendered on a dark background, you may want to switch to PNG with a dark background specified. You can do this as follows:

format:
   hugo:
     html-math-method: 
       method: webtex
       url: https://latex.codecogs.com/png.image?%5Cbg_black&space;