My Web Development Journey: From JavaServer Faces to Hugo - A Performance-Focused Migration Story

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 filesassets/
: Stores files that need processing by Hugo Pipescontent/
: Where your content files (like blog posts) livedata/
: Contains additional data files in YAML, JSON, or TOML formatlayouts/
: Custom templates for your sitepublic/
: The generated site (created when you build)static/
: Static files like images, CSS, and JavaScriptconfig.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:
- 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 }}">
- 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>
- Create
layouts/partials/footer.html
:
<footer>
<p>© {{ 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!