Hugo’s File Loading Order: Project vs. Theme#

Hugo follows a priority system when reading files:

  1. Project-level files (your custom files)
    • If a file exists in your project (layouts/partials/header.html), Hugo uses that first.
  2. Theme-level files
    • If the file isn’t in your project, Hugo looks in the theme (themes/mytheme/layouts/partials/header.html).
  3. Hugo defaults
    • If no file exists in either place, Hugo may use a built-in default (rare but possible).

This means:

  • If you copy header.html into layouts/partials/, Hugo will use that version instead of the theme’s.
  • If you don’t copy header.html, it will fall back to the theme’s version.
  • If the theme doesn’t have a header.html, Hugo just won’t include one.

Front Matter & Archetypes#

Using archetypes is better than manually adding front matter to every .md file.

Why?#

  • Saves time—pre-fills front matter automatically.
  • Ensures consistency—avoids missing or inconsistent fields.

How Many Archetypes Can You Have?#

As many as you want.

Types of Archetypes:#
  1. Global Default (archetypes/default.md)

    • Used when no section-specific archetype exists.
  2. Section-Specific (archetypes/blog.md, archetypes/projects.md)

    • Used when creating content inside a matching section.

    • Example:

      hugo new blog/my-post.md  # Uses archetypes/blog.md
      
  3. Custom Archetypes

    • You can define multiple archetypes for different content types.

    • Example:

      archetypes/
      ├── default.md
      ├── blog.md
      ├── project.md
      ├── event.md
      
    • Then, create content using:

      hugo new blog/my-article.md     # Uses blog.md
      hugo new project/new-website.md # Uses project.md
      hugo new event/conference.md    # Uses event.md
      

Customizing the Header While Keeping the Rest of the Theme#

If you only want to modify the header but keep everything else from the theme, Hugo will automatically merge your custom file with the theme.

How Hugo Loads Files in This Case#

  1. It first looks for layouts/partials/header.html in your project.
    • If found, it uses this file instead of the theme’s.
  2. For everything else, it keeps using the theme files.
    • Example: layouts/partials/footer.html will still come from the theme unless you override it.

How to Do It Step by Step#

1. Copy Just the Header Partial#

Run this in your project root:

mkdir -p layouts/partials
cp themes/mytheme/layouts/partials/header.html layouts/partials/header.html
  • This overrides only the header, leaving all other theme files untouched.

2. Modify the Header#

Now, edit layouts/partials/header.html however you like.


What If the Header Calls Other Theme Files?#

If the theme’s header.html includes other theme partials, like:

{{ partial "nav.html" . }}
  • Hugo will first check for layouts/partials/nav.html in your project.
  • If it doesn’t exist, it will fallback to themes/mytheme/layouts/partials/nav.html.

Alternative: Extending Instead of Overriding#

Instead of copying and modifying the entire header.html, you can modify only a part of it while keeping the theme structure.

Example: Using Blocks Inside the Header#

If your theme’s header.html has this:

<header>
    <h1>{{ .Site.Title }}</h1>
    {{ block "custom_header" . }}{{ end }}
</header>

Then in your project’s layouts/partials/header.html, you can just do:

{{ define "custom_header" }}
    <p>Custom message here!</p>
{{ end }}

This method is cleaner because:

  • You don’t have to replace the entire file.
  • If the theme updates, your customizations still work.