When I started coding my first site was builded with JSF (JavaServer Faces), which was quite a known choice back in the day. I still remember that manipulating templates with Java was fun. The first thing I created was nothing more than a simple diary website where I could log in with my credentials and store data online. Of course, there were many issues (security issues included). I was trying to avoid JavaScript as much as possible. It was kind of a scary monster for me, like something my grandfather told me stories about.

 

Then I started diving into the JavaScript world and realized it wasn’t that scary and it was easy to control, if you stick to the clean code principles, of course. And my websites evolved. I created React applications for many different puposes. So it went on and on, I changed and my websites also changed. And here I am standing here on my fresh blog website written in Markdown and rendered with Hugo.

What is HUGO?

Hugo is a static site generator written in Go. It’s like having a super powered text editor that takes your content and transforms it into a complete website. Think of it as a chef that takes raw ingredients (your markdown files) and turns them into a delicious meal (a fully functional website).

 

What makes Hugo special is its speed. It’s incredibly fast at building sites. We’re talking about thousands of pages in seconds. This is because it’s written in Go, which is known for its performance. It’s like having a sports car instead of a regular sedan when you’re building websites.

Deployment of this website took 90ms.

— Alparslan YILMAZ

The way Hugo works is pretty straightforward. You write your content in markdown files, create some templates, and Hugo does the heavy lifting of converting everything into static HTML files. No database needed, no server-side processing required.

 

One of the things I love about Hugo is its flexibility. You can use it for blogs, documentation sites, or even complex web applications.

Metrics

To demonstrate Hugo’s impressive performance, I ran the hugo --templateMetrics --templateMetricsHints command on my current website. Here’s what the metrics show:

  cumulative       average       maximum      cache  percent  cached  total  
     duration      duration      duration  potential   cached   count  count  template
   ----------      --------      --------  ---------  -------  ------  -----  --------
   8.561583ms    2.853861ms    4.745667ms          0        0       0      3  posts/single.html
   3.296041ms     366.226µs     863.709µs          0        0       0      9  rss.xml
   2.829417ms     404.202µs     576.042µs         59        0       0      7  _partials/head.html
   1.898709ms    1.898709ms    1.898709ms          0        0       0      1  posts/list.html
   1.860541ms    1.860541ms    1.860541ms          0        0       0      1  contact/single.html
   1.633792ms    1.633792ms    1.633792ms          0        0       0      1  index.html
    867.959µs     867.959µs     867.959µs          0        0       0      1  sitemap.xml
    368.834µs     368.834µs     368.834µs          0        0       0      1  404.html
    165.083µs      23.583µs      38.292µs         86        0       0      7  _partials/nav.html
      6.248µs         892ns           2µs        100        0       0      7  _partials/footer.html
      4.792µs       4.792µs       4.792µs        100        0       0      1  _partials/home.html

The template rendering times are incredibly fast, with most templates taking less than 2 milliseconds to render. For example, the single post template (posts/single.html) takes about 2.85ms on average, while simpler components like the footer (_partials/footer.html) render in under 1 microsecond.

 

These metrics show that Hugo’s template system is highly efficient, with good caching potential (notice the high cache potential percentages for partials like nav and footer). For a deeper dive into Hugo’s performance capabilities and optimization techniques, check out the official performance documentation.

Development Experience

As a developer, there are times when you crave simplicity. Constantly dealing with complex logic, architectural decisions, and setup configurations can be mentally exhausting. Sometimes, all you want is to write content and let the magic happen behind the scenes. This is where Hugo shines. It handles the technical complexity while you focus on creating. While it’s not a no-code platform (you’ll need to adjust settings if you’re not using pre-made themes), the development experience remains enjoyable and straightforward.

 

Creating project

To create a project with hugo first you have to install it to your local environment. Follow the link for installation.

After installation you can write this following command to your terminal:

hugo new site quickstart

This command creates a new Hugo site in a directory named quickstart. The directory structure will look like this:

quickstart/
├── archetypes/
├── assets/
├── content/
├── data/
├── layouts/
├── public/
├── static/
└── config.toml

Let’s go through what each directory is for:

  • archetypes/: Contains templates for new content files
  • assets/: Stores files that need processing by Hugo Pipes
  • content/: Where your content files (like blog posts) live
  • data/: Contains additional data files in YAML, JSON, or TOML format
  • layouts/: Custom templates for your site
  • public/: The generated site (created when you build)
  • static/: Static files like images, CSS, and JavaScript
  • config.toml: Your site’s configuration file

Base Templates and Partials

One of Hugo’s most powerful features is its template inheritance system. Let’s explore how to set up base templates and create reusable components.

Base Template

First, create a base template that will serve as the foundation for all your pages. Create a file at layouts/_default/baseof.html:

<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}">
<head>
    {{ partial "head.html" . }}
</head>
<body>
    {{ partial "header.html" . }}
    <main>
        {{ block "main" . }}{{ end }}
    </main>
    {{ partial "footer.html" . }}
</body>
</html>

This base template defines the basic structure of your site and uses blocks that can be overridden by other templates.

Creating Partials

Partials are reusable template components. Let’s create some essential partials:

  1. Create layouts/partials/head.html:
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} | {{ .Site.Title }}{{ end }}</title>
<link rel="stylesheet" href="{{ "css/main.css" | relURL }}">
  1. Create layouts/partials/header.html:
<header>
    <nav>
        <a href="{{ .Site.BaseURL }}">Home</a>
        {{ range .Site.Menus.main }}
        <a href="{{ .URL }}">{{ .Name }}</a>
        {{ end }}
    </nav>
</header>
  1. Create layouts/partials/footer.html:
<footer>
    <p>&copy; {{ now.Year }} {{ .Site.Title }}</p>
</footer>

Using Partials in Templates

Now you can create specific templates that extend the base template. For example, create layouts/_default/single.html for single pages:

{{ define "main" }}
<article>
    <h1>{{ .Title }}</h1>
    {{ .Content }}
</article>
{{ end }}

Reusable Components

You can create more complex partials for reusable components. For example, a card component:

Create layouts/partials/card.html:

<div class="card">
    {{ if .image }}
    <img src="{{ .image }}" alt="{{ .title }}">
    {{ end }}
    <div class="card-content">
        <h3>{{ .title }}</h3>
        <p>{{ .description }}</p>
        {{ if .link }}
        <a href="{{ .link }}" class="button">Learn More</a>
        {{ end }}
    </div>
</div>

Use it in your templates like this:

{{ partial "card.html" (dict 
    "title" "My Card"
    "description" "This is a description"
    "image" "/images/card.jpg"
    "link" "/some-page"
) }}

This modular approach makes your templates more maintainable and reusable. You can create partials for any component you use frequently, such as:

  • Navigation menus
  • Social media links
  • Author information
  • Related posts
  • Custom shortcodes

The key to effective Hugo templating is to break down your site into logical, reusable components and use Hugo’s powerful template inheritance system to maintain consistency across your site.

Conclusion

My journey from JSF to Hugo has been a testament to how web development has evolved over the years. What started as a complex, server-side rendered application has transformed into a lightning-fast static site that’s both performant and maintainable. The metrics speak for themselves - with build times under 100ms and template rendering in microseconds, Hugo has proven to be an excellent choice for my blog.

 

The development experience with Hugo has been refreshingly straightforward. While it requires some initial setup and understanding of its templating system, the payoff is worth it. The ability to write content in Markdown while having full control over the presentation layer through templates and partials gives me the perfect balance of simplicity and flexibility.

 

For developers looking to build fast, secure, and maintainable websites, Hugo offers a compelling solution. Its performance, combined with its powerful templating system and straightforward development workflow, makes it an excellent choice for blogs, documentation sites, and even complex web applications. As for me, I’m excited to continue my journey with Hugo, exploring its features and pushing its capabilities to create an even better web experience.

 

Happy coding!