🔗 Related cheat sheets:

  • 🚀 Core: hugo.md
  • 🎨 Themes and addons: hugo_themes-and-addons.md

Goal: master how Hugo renders Markdown, front matter, and code blocks.

🧩 Front matter essentials

Supported formats per file:

  • TOML front matter: +++ at top and bottom.
  • YAML front matter: --- at top and bottom.
  • JSON front matter: { } at top of file.

Example TOML front matter for a post:

+++
title = "My first post"
date = 2025-01-01T10:00:00Z
draft = true
summary = "Short teaser used in lists"
description = "Fuller meta description"
slug = "my-first-post"
tags = ["hugo", "intro"]
categories = ["blog"]
weight = 10
aliases = ["/blog/first/"]
+++

Useful fields:

  • title: page title.
  • date, lastmod: timestamps.
  • draft: true hides content unless -D is used.
  • summary: overrides automatic summary.
  • description: meta description.
  • slug: custom last URL segment.
  • weight: ordering within lists (lower first).
  • aliases: extra URLs that redirect to this page.
  • markup: force a renderer, for example “html” or “md”.

✍️ Content formats and markup engines

  • Default for .md is Goldmark (CommonMark-compatible).
  • Other formats (Org, AsciiDoc, Pandoc, reStructuredText) are supported via external tools.

Basic markup configuration in hugo.toml:

[markup]
  defaultMarkdownHandler = "goldmark"
 
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true      # allow raw HTML in Markdown
  • unsafe = true is common for docs and blogs that embed raw HTML.
  • Fine-tune Goldmark with parser and extension settings (see Hugo docs for details).

⚙️ Sane defaults for markup and highlighting

Example opinionated but practical defaults:

[markup]
  defaultMarkdownHandler = "goldmark"
 
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true
 
    [markup.goldmark.parser]
      attribute = true
      autoHeadingID = true
 
  [markup.highlight]
    style = "dracula"
    lineNos = true
    lineNumbersInTable = true
    noClasses = false
  • Enables raw HTML, attribute lists, and automatic heading IDs.
  • Uses a popular syntax highlight style with line numbers and CSS classes.

💻 Fenced code blocks and syntax highlighting

Simplest fenced code block:

```go
fmt.Println("Hello from Hugo")
```

You can pass options using attribute syntax understood by Hugo's highlighter:

```markdown
```js {linenos=table,hl_lines=[2],linenostart=10}
console.log("line 10")
console.log("line 11")

Configure syntax highlighting in hugo.toml:

```toml
[markup]
  [markup.highlight]
    style = "dracula"      # run hugo gen chromastyles --highlight-style=dracula for CSS
    lineNos = true
    lineNumbersInTable = true
    noClasses = false       # when false, use CSS classes from chroma stylesheet

Shortcode-based highlighting (works for any content format):

{{< highlight go "linenos=table" >}}
fmt.Println("Hi")
{{< /highlight >}}

🪄 Shortcodes

Shortcodes let you embed rich elements from templates.

  • Built-in examples (vary by version and theme):
    • youtube, vimeo, figure, gist, tweet, and more.
  • Custom shortcodes live in layouts/shortcodes/name.html.

Basic usage:

{{< youtube dQw4w9WgXcQ >}}
 
{{< figure src="/images/pic.jpg" caption="Sample figure" >}}

Content vs raw mode:

  • {{< name >}} … {{< /name >}}
    • Inner content is parsed as Markdown.
  • {{% name %}} … {{% /name %}}
    • Inner content is left as-is for the shortcode to handle.

Inline shortcodes can appear inside text as well, for example to pull params.

🖼️ Images, figure, and attributes

Basic Markdown image:

![Alt text](/images/logo.png)

With Goldmark attribute lists enabled, you can add HTML-like attributes:

![Logo](/images/logo.svg){ width=120 loading=lazy }

Enable the attribute parser in config:

[markup]
  [markup.goldmark]
    [markup.goldmark.parser]
      attribute = true

The built-in figure shortcode can give you captions and classes from templates:

{{< figure src="/images/diagram.png" caption="System diagram" class="w-full" >}}

📑 Summaries and read-more markers

  • Hugo auto-generates .Summary from the first part of the content.
  • You can control where it stops with a comment marker:
Intro paragraph that appears in lists.
 
<!--more-->
 
Everything after this appears only on the single page.
  • In templates, .Summary and .Truncated tell you if the more-marker was used.

🧪 Content tips and patterns

  • Use weight in front matter to get deterministic ordering in lists.
  • Use aliases to avoid broken links when changing URLs.
  • Use markup = “html” on pages that should bypass Markdown and be rendered as raw HTML.
  • Combine Hugo shortcodes with Markdown for rich but maintainable content.
  • Keep long code examples in partials or data files and include them via shortcodes when they get large.

⚠️ Gotchas

  • If markup = “html” is set in front matter, Hugo will not treat the body as Markdown; this often explains why headings or lists are not rendered as expected.
  • Forgetting unsafe = true under [markup.goldmark.renderer] blocks raw HTML, causing embeds to disappear or render as text.
  • When attribute = true is disabled, Goldmark attribute lists like { width=120 } are ignored.
  • The marker affects .Summary; missing it means auto-truncated summaries that might break mid-sentence.
  • Mixing fenced code block options and highlight shortcode options inconsistently can make code highlighting behave differently across pages.