Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 13

Hugo Template Variables: Displaying Front Matter Content

Recommended resources

Hello! Welcome back to our course on building complex websites with AI assistance.

In our last lesson, you learned the crucial skill of writing structured prompts to guide an AI in generating Hugo templates. We instructed the AI to use placeholders like .Title, .Content, and .Params to create a layout. This lesson will demystify those placeholders.

Our learning outcome today is to use common Hugo template variables (e.g., .Title, .Content, .Params) to display content from front matter. By the end of this lesson, you'll understand exactly how Hugo pulls data from your content files into your templates. This knowledge is fundamental for debugging, refining, and manually tweaking the code your AI assistant generates, giving you complete control over your final website.

The "Dot": Hugo's Data Hub

Before we look at specific variables, we need to understand a core concept in Hugo templating: the context, which is most often represented by a single dot (.).

Imagine the dot as a super-object that holds all the information available for the page currently being rendered. When Hugo processes a file like content/services/seo-audits.md, it gathers all its data—the title, the date, any custom fields in the front matter, and the main content—and bundles it all into the . context for the template to use.

This concept is the key to making templates dynamic. The single.html template doesn't know it's building an "SEO Audits" page specifically; it just knows how to find the title, content, and other parameters inside the . it was given.

Context And Variables In The Hugo Static Site Generator

For a clear introduction to this idea, let's look at the article "Context And Variables In The Hugo Static Site Generator" from Smashing Magazine. It explains the dot and how it serves as the starting point for accessing all page data.

Read the first two sections of the article, from the beginning down to just before the section titled 'Content And Front Matter'. Focus on understanding the definition of 'the dot' as the current context and how it provides access to page data.


Accessing Page Data with Variables

Now that you understand the . as a container for page data, let's see how to pull specific pieces of information out of it. We'll focus on the three most common variables you'll encounter.

1. The Main Content: .Content

This is the most straightforward variable. It simply represents the main body of your Markdown file—everything after the front matter. When Hugo sees {{ .Content }} in a template, it renders the Markdown into HTML and places it there.

Single Page Templates | Hugo - Static Site Generator | Tutorial 13

The following video from Giraffe Academy demonstrates this perfectly. While creating a single page template, you'll see exactly how .Content is used to inject the body of a markdown file into the final HTML page.

Watch from 03:01 to 04:58. The instructor adds the {{ .Content }} variable to a basic HTML structure and shows how it dynamically pulls in the content from different markdown files.

2. Built-in Page Variables: .Title, .Date, etc.

Hugo has a set of predefined front matter fields that it recognizes for common use cases. These include title, date, summary, tags, and more.

For these special fields, Hugo provides direct access via top-level variables. So, a title field in your front matter is accessed with {{ .Title }}, and a date field is accessed with {{ .Date }}.

Hugo Markdown Content and Rendered Output
This image illustrates the core workflow. The data defined in the front matter and body of a Markdown file (like `hello.md` on the right) is accessed by template variables and rendered into a complete HTML page.

Let's watch a quick video that demonstrates how to use these built-in variables.

Variables | Hugo - Static Site Generator | Tutorial 17

This clip clearly shows how to access these common, predefined variables within a template.

Watch from 01:30 to 02:52. Notice how .Title and .Date directly correspond to the front matter fields in the content file.

3. Custom Variables: The .Params Object

This is where Hugo's flexibility truly shines, and it's essential for your goal of using Google Sheets as a CMS. Any field you define in your front matter that is not one of Hugo's predefined fields is considered a custom parameter.

All custom parameters are automatically placed inside a special object called .Params. To access them, you use the format {{ .Params.yourCustomFieldName }}.

Given your extensive experience with CMS platforms like WordPress, you can think of Hugo's front matter and the .Params object as its native version of WordPress's Advanced Custom Fields (ACF). It’s the mechanism for defining and displaying arbitrary structured data for a piece of content.

From WordPress to Hugo, a mindset transition

The article 'From WordPress to Hugo, a mindset transition' has an excellent section that draws this exact parallel. It will help solidify your understanding of how custom data is handled in Hugo.

Read the subsection titled 'Custom Fields'. Focus on the comparison between ACF and Hugo's Front Matter, and note the syntax for accessing a custom field: {{ .Params.subtitle }}.

To see this in action, the next segment of the Giraffe Academy video provides a simple, practical demonstration.

Variables | Hugo - Static Site Generator | Tutorial 17

This part of the video shows how to define a custom variable in front matter and then access it in the template using the .Params object.

Watch from 02:52 to 04:48. Pay close attention to the distinction the instructor makes: .Title is accessed directly, but the custom myVar field requires .Params.myVar.

You can even create nested structures in your front matter, which is powerful for organizing complex data from your Google Sheet. For example:

Front Matter (in your-page.md):

---
title: "Our Company"
author:
  name: "John Doe"
  email: "john.doe@example.com"
---

Template Code:

<p>Authored by: {{ .Params.author.name }}</p>
<p>Contact: {{ .Params.author.email }}</p>

Putting It All Together

Let's revisit the services page example from our previous lesson. Imagine your Google Sheet sync created the following file at content/services/seo-audits.md:

---
title: "Advanced SEO Audits"
date: 2023-11-15T09:00:00-05:00
summary: "A deep-dive analysis to uncover critical issues and opportunities."
icon_path: "/images/icons/seo.svg"
service_lead: "Jane Doe"
---

Our audit covers over 200 technical and on-page checkpoints to ensure your site is optimized for search engine visibility and user experience. We analyze site architecture, crawlability, indexing, and more...

The AI-generated template at layouts/services/single.html would use the variables we've learned to display this data:

<!DOCTYPE html>
<html>
<head>
    <title>{{ .Title }}</title>
</head>
<body>
    <article>
        <h1>{{ .Title }}</h1>
        <p><em>{{ .Params.summary }}</em></p>
        <img src="{{ .Params.icon_path }}" alt="Service Icon">
        
        <div>
            {{ .Content }}
        </div>

        <p>Service Lead: {{ .Params.service_lead }}</p>
        <p>Published on: {{ .Date.Format "January 2, 2006" }}</p>
    </article>
</body>
</html>

How it works:

  • {{ .Title }} pulls "Advanced SEO Audits".
  • {{ .Params.summary }} pulls the summary sentence.
  • {{ .Params.icon_path }} pulls the image URL.
  • {{ .Content }} renders the main paragraph into HTML.
  • {{ .Params.service_lead }} pulls the custom "Jane Doe" field.
  • {{ .Date.Format "..." }} accesses the built-in date and formats it for display.
Test your understanding!

You are building a "Case Studies" section. A file at content/case-studies/client-x-success.md has the following front matter and content:

---
title: "Boosting Organic Traffic by 150% for Client X"
date: 2023-10-01
client_name: "Client X Corp"
industry: "E-commerce"
results:
  metric: "Organic Traffic Increase"
  value: "150%"
---

We implemented a comprehensive content and technical SEO strategy that resulted in...

Below is an incomplete template. Fill in the BLANK spaces with the correct Hugo variables to display the data from the content file.

<article>
    <h1>{{ BLANK }}</h1>
    <p><strong>Client:</strong> {{ BLANK }}</p>
    <p><strong>Industry:</strong> {{ BLANK }}</p>

    <div>
        {{ BLANK }}
    </div>

    <footer>
        <h3>Key Result</h3>
        <p>{{ BLANK }}: {{ BLANK }}</p>
    </footer>
</article>
Show answer

Here is the completed template:

<article>
    <h1>{{ .Title }}</h1>
    <p><strong>Client:</strong> {{ .Params.client_name }}</p>
    <p><strong>Industry:</strong> {{ .Params.industry }}</p>

    <div>
        {{ .Content }}
    </div>

    <footer>
        <h3>Key Result</h3>
        <p>{{ .Params.results.metric }}: {{ .Params.results.value }}</p>
    </footer>
</article>

Conclusion

You've now mastered the fundamental mechanism for making Hugo websites dynamic. Understanding how to use these variables is the bridge between the data in your content files (managed by your Google Sheet) and the final rendered pages.

Key Takeaways:

  • The dot (.) is the context object that holds all data for a page.
  • {{ .Content }} renders the main body of your Markdown file.
  • Predefined front matter fields like title and date are accessed directly (e.g., {{ .Title }}).
  • All other custom fields from your Google Sheet are accessed via the {{ .Params }} object (e.g., {{ .Params.your_field }}).

Preview of the next lesson:
So far, our entire page layout is in one big single.html file. This isn't efficient, as components like the site header and footer will be repeated across many templates. In our next lesson, "Create and use partials to build reusable template components like headers and footers," we will learn how to break our templates into smaller, reusable snippets and see how the "dot" context we explored today gets passed into them.