The Hugo Markdown Crash Course

Tags: webpage, hugo, markdown

5 in a series of 5 articles in the Build a Website series.

What is Text?

Now that you have a mostly functional site, you’ll need to get content into it. Luckily, Hugo makes that easy! Markdown is a simple but expressive syntax which makes creating formatted text simple and streamlined. GitHub uses it to format commits, Microsoft Docs makes heavy use of Markdown, and now you know that Hugo’s text-to-HTML strategy is Markdown as well.

The text-to-HTML aspect is important; in general, you write plain text markdown and Hugo takes that and converts it to the tags and decorations needed to make a fully-fledged HTML page that your server can send out to your visitors.

If you wanted to, you could make content by typing it into a plain text file. Most of it would probably render just fine, no flair or headers or lists or anything but it’d probably work. If you need more complicated text it’s not difficult. But this gets tedious if you’re making largely the same kinds of pages day-in and day-out, and people were fed up enough to make tools like markdown so maybe they have a point.

You could also go the other way around and simply post plaintext files on the internet. If your internet host allowed it, you could set up a simple repository of text files at various web addresses, your visitors would then download those files and read them. If this sounds arcane, and awkward it’s because it is. HTML and HTTP is the de-facto because of this, and we haven’t made a better system yet, though that’s not to say it couldn’t exist.

Rambling aside, if you want to make any amount of text on the internet, you’d best learn markdown.

Headers, Like This

I’ll ignore the default Hugo front matter stuff and start with the functional stuff. If you are writing an article, post, or any structured content you might want some titles for related blocks of text, or “headers.” No worries; it’s as easy as adding “#” to the front of a new line:

# This is a Header
This is plaintext below it

You’ll notice that the code block highlights the text with a bold style. If you’re using a competent text editor, most recognize .md files as “Markdown” and will happily highlight your text correctly. VSCode or Sublime do the job nicely, and I’ve even got vim to do it.


Sometimes you want your text to be spicy: italic, bold, both, or sometimes you want to strike things from the record, or make them more robotic. If you’re talking about someone, you might want what they said set up like a quote

640 k ought to be enough for anybody

Even if it’s a misquote! Side-note, don’t misquote people.

_italic_, __bold__, ___bold-italic___

> quoted material here

If you need more stylistic options then you are going to need more powerful tools and Hugo provides.

Links and cross-links

One of the most valuable features of HTML and the web is linking things together. You can link to content in your own site or to other sites, like this:

links look like this: [display text](

Hugo’s own documentation is robust, so check it out here (See, I used the links here too).

Lists (and Tables)

Sometimes, you want to run lists of items for emphasis, or to call attention to specific items. This element can be a bit disruptive to the overall flow, but it can be useful:

1. Sequential
2. Items
3. In a list

* unordered list
* or just "bullets"

I’ve never had to make lists that were too involved: no sub-lists or sub items, but if you do check out this useful cheatsheet.

For that matter, this cheatsheet is super useful if you forget stuff, like I do.

Advanced Hugo features

With these features most articles and posts can be handled. You may have noticed that I’ve placed Hugo shortcodes in the links section. That’s not markdown, that’s a special capability that Hugo provides for additional customization.

The most powerful general capability is probably the ability to directly inject HTML. With this, you can update classes for specific pieces of text, or put new elements and tags there. This is great, but it should be used with care; it’s easy to go overboard and flood the DOM with extra tags, elements, and clutter.

Modify Defaults

Whenever you use Hugo’s markdown rendering you’ll be working with the Goldmark renderer which we can configure with custom layouts. I mentioned that if you want a link in your page, you use a set of square brackets and parenthesis: when you write that markdown, Goldmark picks it up and makes the anchor tag

a link example like [this](example)

it gets translated to this:

<p>a link example like <a href="example">this</a></p>

But you may want a little more control over that. You may want the links in your articles or posts or pages to have a distinct styling. You could do this by making an SCSS selector that works in tandem with a particular layout, but now you’ve got a link between two pieces of code and it may not be clear how they interact. In my opinion, it’s usually much better to directly assign a class for something like this. You can use custom shortcodes to mangle this, but the Goldmark enables “Render Hooks,” which allows for a more elegant solution.

Unfortunately, at this time you can only modify image, link, and header hooks, so those are the only kinds of custom renderers you can make. Everything else will have to be a custom shortcode. Under layouts/_default/_markup I’ve got a file render-link.html. It looks like this:

<a href="{{ .Destination }}"{{ with .Title}} title="{{ . }}"{{ end }} class="link">{{- .PlainText | safeHTML -}}</a>

You can see that it takes the metadata and drops it in. This is probably pretty close to the default template that Goldmark uses. I also make use of the “class” attribute to make it a “link.” That’s a top-level style in my source SCSS. I also tend to be a bit paranoid about the text rendering so I pipe the “plain” version of the text into the safeHTML pipe to try to make sure I don’t muck up my site.

One final note; this custom shortcode file needs to have no newline at the end. If you miss this detail, you’ll often get strange text rendering and splitting paragraphs. This is because Goldmark seems to take the text verbatim. This may be a problem if your text editor automatically add a blank newline to the end of your code (and mine did until I told it not to).

Markdown Wizardy

If you read this article and referenced the cheat sheet and Hugo documentation you now possess the powerful knowledge to make webpages efficiently. For convenience’s sake I’ll put all that info here.

Use your power wisely…