← Back to DevBytes

How to Build a Portfolio Website with Hugo Static Site Generator

What is Hugo Static Site Generator?

Hugo is a lightning-fast static site generator written in Go. It takes plain text files (usually Markdown with YAML/TOML front matter) and a set of HTML templates to produce a complete, ready-to-deploy website. There is no database, no server-side processing at runtime, and no dynamic content generation—every page is pre-built as a static HTML file. This makes Hugo sites incredibly fast, secure, and easy to host on services like GitHub Pages, Netlify, or any simple web server.

Hugo’s strengths include blazing build speeds (a medium-sized site builds in milliseconds), flexible content organization, a powerful templating language, and a rich ecosystem of pre-made themes. For developers, designers, and writers building a personal portfolio, Hugo offers the perfect balance between simplicity and control.

Why Hugo for Your Portfolio Website?

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

A portfolio site needs to load quickly, showcase your work effectively, and be easy to update. Hugo delivers on all fronts:

Whether you’re a front-end developer, designer, or data scientist, a Hugo-powered portfolio gives you a clean, fast, and professional online presence with minimal overhead.

Setting Up Hugo

Before creating your portfolio, install Hugo on your development machine. Hugo runs on macOS, Linux, and Windows.

macOS (Homebrew)

brew install hugo

Linux (apt or snap)

sudo apt update
sudo apt install hugo   # Debian/Ubuntu
# or using snap
sudo snap install hugo

Windows (Chocolatey or Scoop)

choco install hugo -y    # Chocolatey
# or
scoop install hugo      # Scoop

Verify the installation:

hugo version

You also need a text editor (VS Code, Sublime, etc.) and Git for version control. A basic understanding of the terminal/command line is helpful.

Creating a New Hugo Portfolio Site

Hugo’s CLI makes scaffolding trivial. Navigate to your projects folder and run:

hugo new site my-portfolio
cd my-portfolio

This creates the basic directory structure without a theme. Right now, the site has no visual appearance. Next, we’ll add a theme specifically suited for portfolios.

Choosing and Installing a Theme

Hugo themes are available on themes.gohugo.io. For a portfolio, look for themes tagged “portfolio” or “personal.” Popular choices include hugo-coder, hugo-creative-portfolio-theme, hugo-devfolio, and hugo-tranquilpeak. In this tutorial, we’ll use a hypothetical theme called hugo-portfolio. Replace it with your chosen theme’s repository URL.

# Initialize git (themes are added as git submodules by convention)
git init

# Add the theme as a submodule
git submodule add https://github.com/someauthor/hugo-portfolio.git themes/hugo-portfolio

After adding the theme, you need to tell Hugo to use it. Open the site’s main configuration file (by default config.toml in the site root) and set the theme:

# config.toml (or config.yaml, config.json)
theme = "hugo-portfolio"

Now you can start the Hugo development server:

hugo server -D

The -D flag includes draft content. Open http://localhost:1313 in your browser. You’ll see a basic site with placeholder content provided by the theme.

Understanding Hugo Directory Structure

A typical Hugo site after adding a theme looks like this:

my-portfolio/
├── archetypes/
│   └── default.md
├── config.toml          (or config.yaml)
├── content/
│   ├── _index.md        (home page content)
│   ├── projects/
│   │   ├── _index.md    (projects list page)
│   │   └── project1.md
│   ├── about/
│   │   └── index.md     (or _index.md)
│   └── blog/
│       ├── _index.md
│       └── post1.md
├── data/
├── layouts/             (optional: override theme templates)
├── static/              (images, CSS, JS – copied as-is)
├── themes/
│   └── hugo-portfolio/  (the theme you installed)
└── .gitignore

Key directories for portfolio building:

Configuring Your Site

The configuration file controls everything from the site title to social links. Here’s a sample config.toml for a portfolio using our imaginary theme:

baseURL = "https://yourusername.dev/"
languageCode = "en-us"
title = "Alex Rivera – Full‑Stack Developer"
theme = "hugo-portfolio"

[params]
  # Homepage intro
  author = "Alex Rivera"
  tagline = "I build accessible, performant web applications."
  avatar = "images/avatar.jpg"
  email = "hello@alexrivera.dev"
  github = "https://github.com/alexrivera"
  linkedin = "https://linkedin.com/in/alexrivera"

# Menu configuration
[[menu.main]]
  name = "Projects"
  url = "/projects/"
  weight = 1

[[menu.main]]
  name = "About"
  url = "/about/"
  weight = 2

[[menu.main]]
  name = "Blog"
  url = "/blog/"
  weight = 3

# Enable syntax highlighting for code blocks (if theme supports it)
pygmentsCodeFences = true
pygmentsStyle = "monokai"

Most portfolio themes expect certain front matter fields in your content files (like title, date, draft, and custom ones like featured_image). Read your theme’s documentation to see what’s available.

Adding Portfolio Content

Now the real work begins—creating pages that showcase your projects, skills, and background.

Homepage (_index.md)

The home page content usually lives in content/_index.md. This file controls the homepage copy, not the layout. For a portfolio, it might contain a hero message and a brief introduction:

---
title: "Home"
date: 2025-04-01T10:00:00+02:00
draft: false
---

# Hello, I'm Alex Rivera

I'm a full‑stack developer passionate about building tools that make people's lives easier. Here you'll find a selection of projects, articles, and my professional journey.

Take a look around, and if something sparks your interest, [get in touch](mailto:hello@alexrivera.dev).

The front matter (the YAML/TOML between ---) sets metadata. The Markdown body becomes the page content. The theme’s layout will wrap this in your chosen design.

Projects Section

For each project, create a Markdown file under content/projects/. A typical project page:

---
title: "Weather Dashboard"
date: 2025-03-20T18:00:00+02:00
draft: false
summary: "A real‑time weather dashboard with interactive maps and alerts."
tags: ["React", "D3.js", "OpenWeather API"]
featured_image: "images/weather-dashboard-thumb.jpg"
---

## Overview
The Weather Dashboard fetches live weather data from the OpenWeather API and visualizes it using D3.js maps and charts. Users can search any city, view 7‑day forecasts, and set custom alerts.

## Technical Highlights
- **React** front‑end with custom hooks for data fetching
- **D3.js** for dynamic map overlays and animated charts
- **Node.js** backend proxy to secure API keys
- **Service Worker** for offline support and caching

## Links
- [Live Demo](https://weather.example.com)
- [Source Code](https://github.com/alexrivera/weather-dashboard)

The theme may render the featured_image as a thumbnail on listing pages. Tags can be used for filtering (if the theme supports it). Keep project pages concise but informative.

About Page

Create content/about/index.md (or _index.md if the theme uses list pages for about sections). This is your personal bio, skills, and timeline.

---
title: "About Me"
date: 2025-04-05T14:30:00+02:00
draft: false
---

## Who am I?
I'm a software engineer based in Barcelona, currently working at TechCo. I specialize in front‑end architecture and accessibility. Outside work, I contribute to open‑source mapping tools and write about performance optimization.

## Skills
- **Languages:** JavaScript, TypeScript, Python, Go
- **Frameworks:** React, Next.js, Svelte, FastAPI
- **Tools:** Docker, Kubernetes, AWS, Terraform

## Experience
- **Senior Frontend Engineer @ TechCo** (2023–present)
- **Full‑stack Developer @ StartUp Inc** (2020–2023)
- **Junior Developer @ WebAgency** (2018–2020)

Blog (Optional)

A blog adds personality and demonstrates communication skills. Create posts under content/blog/. Hugo automatically orders them by date.

---
title: "How I Reduced Build Times by 60% with esbuild"
date: 2025-02-10T09:00:00+02:00
draft: false
tags: ["performance", "esbuild", "webpack"]
---

We recently migrated our React app from webpack to esbuild. Here's what we learned...

Customizing the Theme

A portfolio must reflect your personal brand. Hugo allows you to override any theme template without modifying the theme itself. This keeps theme updates easy via git.

Overriding Layouts and Partials

To customize the homepage layout, copy the theme’s layouts/index.html (or list.html for listing pages) into your site’s layouts/ directory, preserving the path structure. For example, to override the single project page template:

cp themes/hugo-portfolio/layouts/projects/single.html layouts/projects/single.html

Now edit layouts/projects/single.html. You can rearrange sections, add new classes, or insert custom partials.

Common customizations for a portfolio:

Adding Custom CSS

Most themes include a way to add extra styles. If not, override the head.html partial (often in layouts/partials/head.html) and add a link to your custom stylesheet:

<link rel="stylesheet" href="{{ "css/custom.css" | relURL }}">

Then place your CSS in static/css/custom.css. For example, adjust typography or add subtle animations:

/* static/css/custom.css */
body {
  font-family: 'Inter', sans-serif;
}
.project-card {
  transition: transform 0.2s ease;
}
.project-card:hover {
  transform: translateY(-4px);
}

Using Shortcodes for Richer Content

Hugo shortcodes let you embed complex HTML or interactive elements without leaving Markdown. A typical portfolio might use a shortcode for a responsive image gallery or a code sandbox embed. If your theme lacks them, you can create your own. Create a file like layouts/shortcodes/codepen.html:

{{- with .Get "url" -}}
<iframe
  src="{{ . }}"
  width="100%"
  height="400"
  frameborder="0"
  loading="lazy"
  allowfullscreen></iframe>
{{- end -}}

Then in any Markdown file:

{{< codepen url="https://codepen.io/alex/pen/example" >}}

Deploying Your Portfolio

A static site needs a host that serves HTML files. Two popular, free options are GitHub Pages and Netlify. Both integrate seamlessly with Hugo.

GitHub Pages

Create a GitHub repository named <username>.github.io (for user pages) or any repo for project pages. Push your Hugo site source to a branch (often main or source). Then use GitHub Actions to build Hugo and deploy to the gh-pages branch. Many Hugo themes include a sample workflow.

Example workflow (.github/workflows/hugo.yml):

name: Deploy Hugo site to GitHub Pages

on:
  push:
    branches:
      - main

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true  # fetch Hugo themes

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: 'latest'

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public
          publish_branch: gh-pages

After the first push, your portfolio will be live at https://<username>.github.io (or your custom domain if configured).

Netlify

Netlify offers drag-and-drop simplicity. Connect your GitHub/GitLab repository, tell Netlify the build command is hugo --minify and the publish directory is public. Netlify automatically detects Hugo and adds the correct build environment. It also provides free SSL, a CDN, and automatic branch deploys for previews.

For a custom domain, set the baseURL in config.toml to your domain, and Netlify handles HTTPS. You can also add a netlify.toml for fine-grained control:

[build]
  command = "hugo --gc --minify"
  publish = "public"

[build.environment]
  HUGO_VERSION = "0.120.0"  # pin a version for consistency

Both services work excellently. Netlify’s form handling and serverless functions can also power contact forms, but a simple mailto link or a third-party service (Formspree) often suffices for a portfolio.

Best Practices for a Hugo Portfolio

To make your portfolio stand out and remain maintainable, follow these guidelines:

Conclusion

Hugo turns the process of building a portfolio website into an enjoyable, code-focused experience. You write content in Markdown, control layout with simple templates, and deploy with a single push. The result is a blazing-fast, secure, and highly customizable site that you fully own. By choosing a good theme, adding your projects and story, and following best practices around optimization and maintainability, you’ll create a portfolio that not only showcases your work but also demonstrates your technical taste. Now open your terminal, run hugo new site, and start building.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles