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:
Create a directory within
content
that will hold your Quarto article.Add an
index.qmd
document to the directory. When rendered this will create anindex.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).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
= np.arange(0, 2, 0.01)
r = 2 * np.pi * r
theta = plt.subplots(subplot_kw={'projection': 'polar'})
fig, ax
ax.plot(theta, r)0.5, 1, 1.5, 2])
ax.set_rticks([True)
ax.grid(
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:

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;