Skip to main content

Welcome to a Grasp lesson

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

Lesson 23

Creating Reusable Partials for Static Content

Recommended resources

Hello again! It's great to see you back.

In our last session, we built the "brain" of our homepage—a dynamic index.html template that acts as a dispatcher. It cleverly loops through our data/homepage.json file and knows to call a specific partial for each section type. However, right now it's like a switchboard operator trying to connect calls to empty offices.

Today, we're going to build the first one of those offices. The learning outcome for this lesson is to generate a reusable partial for a static content section, such as a hero banner with a call-to-action. This is where our abstract data structure finally becomes a visible, tangible part of our website.

What are Partials and Why Do They Matter?

In Hugo, partials are reusable pieces of template code. Think of them as custom LEGO bricks. You design a brick once—like a header, a footer, or a hero banner—and then you can use it anywhere on your site, as many times as you want. This makes your code clean, modular, and much easier to manage.

Hugo Project Structure and Partial Inclusion in VS Code
This image shows a typical Hugo project structure in a code editor. Notice the `partials` directory inside `layouts`, which contains reusable template files like `header.html` and `footer.html`. This is where we'll be working today.

To get a quick overview of what partials are and how they work, let's watch a short video.

Partial Templates | Hugo - Static Site Generator | Tutorial 21

The following video from Giraffe Academy provides a clear, concise introduction to partial templates in Hugo.

Please watch the selected segments to understand the core concept. Focus on: The purpose of partials (00:00 - 00:42). Where partials are created (00:29 - 01:18). How to call a partial from another template using {{ partial "..." . }} (01:31 - 02:02).

As the video explained, we create a file in layouts/partials/ and then call it from our main templates. The . we pass along is the "context"—it's the data the partial needs to do its job. In our case, the context will be the data for a specific homepage section from our JSON file.


Step 1: Defining the Data for Our Hero Banner

Let's revisit the data/homepage.json structure we planned. A hero banner section would contain all the information needed to render it:

{
  "id": "hero",
  "type": "hero-banner",
  "title": "Build Complex Websites with Vibe Coding",
  "content": "Leverage AI to create stunning, modern websites with Hugo and Google Sheets. The future of agile web development is here.",
  "image": "/images/hero-background.jpg",
  "cta_text": "Get Started Now",
  "cta_link": "/course/overview"
}

Our dispatcher in layouts/index.html will find this object, see that its type is hero-banner, and then call the partial layouts/partials/homepage/hero-banner.html, passing this entire block of data as the context.


Step 2: Prompting the AI for the Partial

Now for the "vibe coding" part. Let's write a detailed prompt to ask our AI assistant to generate the hero-banner.html partial. We'll use the same structured approach as last time.

Prompt for AI:

I need you to generate a Hugo partial template for a hero banner section. The file should be named hero-banner.html and located in the layouts/partials/homepage/ directory.

Context:
This partial will be called by a template that passes it a data object (the context, .) with the following fields: title, content, image, cta_text, and cta_link.

Instructions:

  1. Create an HTML <section> element that will serve as the container.
  2. Use the .image value to set a background image for the section using inline CSS. Add a semi-transparent dark overlay to ensure text is readable.
  3. The section content (heading, paragraph, button) should be vertically and horizontally centered. Use CSS Flexbox for this.
  4. Display the .title in an <h1> tag.
  5. Display the .content in a <p> tag.
  6. Create an <a> tag that acts as a call-to-action button. Use .cta_link for the href attribute and .cta_text for the button text.
  7. Add some basic CSS classes for styling the text and button, which I can define later in a separate stylesheet.

This prompt is specific about the data it expects, the HTML structure, and even the desired layout, giving the AI a clear blueprint.


Step 3: Analyzing the AI-Generated Code

The AI would likely produce something like this. Let's analyze the result.

layouts/partials/homepage/hero-banner.html

{{/* 
  This partial receives a context object with hero banner data.
  Example fields: .title, .content, .image, .cta_text, .cta_link 
*/}}
<section class="hero-banner" style="background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('{{ .image }}');">
  <div class="hero-content">
    <h1 class="hero-title">{{ .title }}</h1>
    {{ with .content }}
      <p class="hero-subtitle">{{ . }}</p>
    {{ end }}
    {{ if and .cta_text .cta_link }}
      <a href="{{ .cta_link }}" class="btn btn-primary">{{ .cta_text }}</a>
    {{ end }}
  </div>
</section>

Explanation:

  • style="...": The AI correctly used the .image field to construct an inline background-image style. The linear-gradient is a nice touch for readability.
  • .title, .content, .cta_link, .cta_text: These are direct references to the fields in the JSON data object that was passed to the partial.
  • {{ with .content }}...{{ end }}: This is a robust way to handle optional fields. The paragraph tag will only be rendered if the content field exists and is not empty.
  • {{ if and .cta_text .cta_link }}...{{ end }}: Similarly, this checks that both the button text and link are present before rendering the <a> tag. This prevents broken or empty buttons.

When rendered, this partial would produce a section that looks conceptually similar to this:

Hugobricks Website Homepage with Hero Banner
This image shows a hero banner from the Hugobricks theme. It features a bold headline, descriptive text, and a clear call-to-action button, just like the partial we've designed.
Test your understanding!

You want to add an id attribute to the <section> element for SEO and in-page navigation (e.g., <section id="hero" ...>). The id value is available in your JSON data object.

How would you modify the first line of the hero-banner.html partial to include this?

Show answer

You would add id="{{ .id }}" to the <section> tag. The id field from the JSON object is available as .id within the partial's context.

The modified line would look like this:
<section id="{{ .id }}" class="hero-banner" style="...">


Making Partials More Flexible

Our partial works perfectly within our homepage dispatcher system. But what if you wanted to reuse this hero banner on another page, without adding it to the homepage.json file? This is where passing parameters as a dictionary (dict) becomes incredibly powerful.

A Hugo partial can only accept one parameter. We've been passing the data object as that one parameter. However, we can construct a new "dictionary" on the fly to serve as that parameter. This makes our partials more self-documenting and flexible.

6.2 Reusing content with partials | Hugo In Action

The article 'Reusing content with partials' from Hugo In Action explains this concept well. It shows how to pass multiple, named values to a partial by wrapping them in a dict.

Please read the short section that begins with 'A Hugo partial takes only one argument.' Focus on the example that shows how to call a partial with (dict "Menu" site.Menus.main "Button" true). This demonstrates the syntax for passing multiple named parameters.

Based on that principle, we could call our hero partial from any template like this:

{{ partial "homepage/hero-banner.html" (dict 
    "title" "A Custom Title For This Page" 
    "content" "This content is unique to this specific usage."
    "image" "/images/another-bg.jpg"
    "cta_text" "Learn More Here"
    "cta_link" "/about") 
}}

The partial code remains exactly the same because it still accesses the data via .title, .content, etc. The only difference is how the data is passed. This approach turns your partial into a true, self-contained component that you can drop in anywhere, customizing it as needed. For your work in SEO, this is a powerful technique for creating and placing targeted call-to-action sections across a site.


Conclusion

You've successfully built your first reusable homepage component! You translated a data structure from your Google Sheet into a tangible, styled hero banner. You practiced crafting a detailed prompt for an AI assistant and analyzed the resulting Hugo template code.

Key Takeaways:

  • Partials are the building blocks for modular Hugo sites, located in layouts/partials/.
  • We can generate a partial by prompting an AI with the data structure it will receive (context) and clear instructions for the desired HTML output.
  • Inside a partial, variables like .title and .content are used to access the data passed into it.
  • Using with and if statements makes partials more robust by gracefully handling optional data fields.
  • For maximum reusability, you can call a partial with a dict to pass custom, named parameters.

Preview of the next lesson:
Our hero banner is a static component—it just displays the data it's given. But homepages often need dynamic components that pull in content from elsewhere. In our next lesson, we will tackle exactly that: generating a reusable partial that displays a curated list of content from a specific site section (e.g., 'Latest Blog Posts'). This will be our first step in connecting different parts of the site together on the homepage.