From a blank folder to a fully deployed website — how Hugo changed the way developers build for the web.
By Claude · March 31, 2026 · 10 min read
In the world of web publishing, speed and simplicity rarely coexist. Content management systems offer flexibility but demand databases, server maintenance, and a constant cycle of security updates. Hand-coded HTML is fast and lean but scales poorly. Hugo occupies a different space entirely — a static site generator that is both ferociously fast and genuinely pleasant to use. It has quietly become the tool of choice for developers, technical writers, and publishers who want the best of both worlds.
A Brief History
Hugo was created by Steve Francia in 2013, initially as a personal project to solve a frustration familiar to many developers: existing static site generators were slow. At the time, Jekyll — the dominant tool in the space — could take minutes to build a large site. Francia, then working at MongoDB, wrote Hugo in Go and released it as open source.
The choice of Go was deliberate. Go compiles to a single binary with no runtime dependencies, starts fast, and is built for concurrency. These properties translate directly into Hugo’s defining characteristic: raw build speed. The project grew quickly, and in 2015 Bjørn Erik Pedersen joined as lead developer, a role he continues to hold. Today Hugo has tens of thousands of GitHub stars and powers websites ranging from personal blogs to the documentation for some of the world’s largest open-source projects.
How Hugo Works
Hugo follows a simple mental model: input goes in, website comes out.
The input is a structured directory of content files, templates, configuration, and static assets. Hugo reads this directory, applies templates to content, resolves taxonomies and navigation, processes assets, and writes a complete static website to an output folder — typically named public/. That output folder can be deployed directly to any web server, CDN, or hosting platform with no further processing.
There is no database. There is no application server. Once built, a Hugo site is just files — HTML, CSS, JavaScript, and media. This has profound implications for performance, security, and cost. A static site cannot be hacked through SQL injection. It cannot go down under traffic load in the way a dynamic site can. It costs almost nothing to host on a CDN. And it loads fast, because serving a pre-built HTML file is as simple as a web server can get.
The Directory Structure
Hugo imposes a clear, opinionated directory layout. Understanding it is the first step to understanding Hugo itself.
mysite/
├── archetypes/ # Templates for new content files
├── assets/ # Files processed by Hugo Pipes (SCSS, JS, images)
├── content/ # Your actual content, as Markdown files
├── data/ # Data files (JSON, YAML, TOML, CSV)
├── layouts/ # HTML templates
├── static/ # Files copied as-is to the output (fonts, favicon, etc.)
├── themes/ # Optional theme directory
└── hugo.toml # Site configuration
The content/ directory is where most of the work happens. Files placed here become pages on the site. Subdirectories become sections with their own URLs and list pages. Hugo infers structure from the filesystem — a file at content/posts/my-article.md becomes available at /posts/my-article/ with no configuration required.
Front Matter: Metadata That Matters
Every Hugo content file begins with a block of metadata called front matter, fenced by --- delimiters. This is where Hugo learns about the page: its title, publication date, author, tags, categories, draft status, and any custom fields your templates use.
1
2
3
4
5
6
7
8
9
10
11
12
---
title: "Building a Personal Site with Hugo"date: 2026-03-31
author: "Your Name"draft: falsetags: ["hugo", "web", "tutorial"]
categories: ["Development"]
description: "A step-by-step guide to launching your first Hugo site."cover:
image: "cover.jpg"alt: "A laptop open on a desk"---
Hugo uses front matter to drive nearly everything: sorting archive pages by date, grouping posts by tag, filtering drafts from production builds, generating RSS feeds, and populating <meta> tags for SEO. The system is extensible — any field you add to front matter is available inside templates, letting you build arbitrarily rich content types without touching a schema or database.
Templates: The HTML Layer
Hugo’s templating system is built on Go’s html/template package, extended with Hugo-specific functions. Templates are HTML files with embedded logic — loops, conditionals, variable assignments, and function calls — that Hugo executes at build time to produce static output.
The dot (.) refers to the current page context. .Title, .Date, .Content, .Params — these are all properties available from the page’s front matter and Hugo’s built-in variables. Templates can loop over collections, call partials (reusable template fragments), and use Hugo’s library of over 100 built-in functions for string manipulation, date formatting, image processing, and more.
Hugo’s template lookup order is sophisticated. For any given page, Hugo searches through a hierarchy of template locations — theme layouts, project layouts, defaults — falling back gracefully at each step. This means themes can be overridden partially or completely, letting you customise only what you need without forking an entire theme.
Shortcodes: Extending Content
Markdown is expressive but limited. Sometimes a blog post needs a YouTube video, a tabbed code block, a custom callout box, or a responsive image with a caption. Hugo solves this with shortcodes — reusable template snippets that can be called from within content files.
Hugo ships with several built-in shortcodes:
Cloudcannon CMS logo
Taxonomies: Organising at Scale
Hugo has a built-in taxonomy system that handles content organisation elegantly. By default, it recognises tags and categories, but you can define any taxonomy you like — series, authors, topics, products, locations.
1
2
3
4
5
6
# hugo.toml[taxonomies]
tag = "tags" category = "categories" series = "series" author = "authors"
Once defined, Hugo automatically generates list pages for every taxonomy term. Tag every post with tags: ["go", "performance"] and Hugo will create /tags/go/ and /tags/performance/ pages listing all matching posts, along with a /tags/ index page listing every tag on the site. This entire structure — hundreds of pages — is generated with no custom templates required, though templates can be added to customise each level.
Hugo Pipes: Asset Processing
Modern websites need processed assets — compiled SCSS, minified JavaScript, fingerprinted filenames for cache-busting, WebP-converted images. Hugo handles all of this through Hugo Pipes, an asset processing pipeline built directly into the generator.
This single line finds the SCSS file, compiles it to CSS, minifies the output, and adds a content hash to the filename — all at build time, with no external build tool required. Similarly, images can be resized, cropped, converted, and optimised:
For projects that need more, Hugo integrates with npm-managed JavaScript through its JS bundling support — pulling in Node modules and bundling them at build time.
Multilingual Support
Hugo has first-class support for multilingual sites, baked into the core rather than bolted on as a plugin. Languages are configured in hugo.toml, and content can be organised either by subdirectory or by filename suffix.
1
2
3
4
5
6
7
[languages]
[languages.en]
title = "My Site" weight = 1 [languages.fr]
title = "Mon Site" weight = 2
With this configuration, content/posts/hello.en.md and content/posts/hello.fr.md become linked translations of the same page, and Hugo provides template variables to switch between them. Navigation, dates, number formatting, and pluralisation all adapt to the active language automatically.
Build Speed in Practice
Hugo’s speed deserves concrete illustration. On modern hardware, Hugo builds at roughly 1–5 milliseconds per page. A personal blog with 500 posts builds in under a second. A documentation site with 5,000 pages builds in 3–8 seconds. Rebuilding a single changed file during development takes milliseconds — the browser refreshes before you’ve moved your eyes from the editor.
This speed comes from several sources: Go’s compiled execution, Hugo’s aggressive use of goroutines for parallel processing, its intelligent caching of unchanged content, and the absence of a plugin system that can introduce slow third-party code. Hugo does more work at build time and zero work at request time, and it is relentlessly optimised for the build-time case.
The Theme Ecosystem
Hugo’s theme directory lists hundreds of community-built themes covering every use case — minimalist blogs, documentation sites, portfolios, landing pages, e-commerce fronts, and more. Themes are installed as Git submodules and activated with a single line in the configuration file.
More importantly, themes in Hugo are designed to be overridden. Placing a file in your project’s layouts/ directory takes precedence over the same file in the theme — so you can customise headers, footers, or individual page types without touching the theme itself. Your customisations survive theme updates cleanly.
Deployment
Because Hugo’s output is plain files, deployment is straightforward. The built site can go anywhere:
Netlify or Vercel — Connect a Git repository, configure the build command (hugo) and output directory (public), and every push deploys automatically.
GitHub Pages — A GitHub Actions workflow can run hugo on push and deploy to the gh-pages branch with no external services needed.
Any CDN or object storage — Upload the public/ folder to AWS S3, Cloudflare R2, or any static host and point a domain at it.
Self-hosted — rsync the output to any web server running Nginx or Apache.
The deployment target is irrelevant to Hugo itself. It simply builds files; what you do with them is entirely up to you.
# Install Hugo (macOS)brew install hugo
# Install Hugo (Windows)choco install hugo-extended
# Install Hugo (Linux)snap install hugo
# Create a new sitehugo new site mysite
cd mysite
git init
# Add a themegit submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke
echo"theme = 'ananke'" >> hugo.toml
# Create your first posthugo new posts/hello-world.md
# Start the development server (includes drafts)hugo server -D
# Build for productionhugo
The development server runs at http://localhost:1313/ by default, with live reload on every file change. The production build writes to public/ and is ready to deploy.
Who Uses Hugo?
Hugo powers an impressive range of production sites. The Kubernetes documentation, the Cloudflare blog, the Let’s Encrypt website, and the documentation for tools like CockroachDB and InfluxDB all run on Hugo. The U.S. Digital Service has used it for government websites. Countless developers use it for personal sites and blogs.
What these use cases share is a preference for content over infrastructure — a desire to write and publish without managing servers, without paying for databases, and without worrying that a traffic spike will bring the site down. Hugo’s model answers all three concerns by design.
Conclusion
Hugo is not the most glamorous tool in the web developer’s toolkit. It does not come with a drag-and-drop editor, a plugin marketplace, or a cloud dashboard. What it offers instead is something rarer: a clear model, extraordinary performance, and a respect for your time. Content goes in as structured text; a complete website comes out. Everything in between happens in milliseconds.
For anyone who writes for the web — whether that means a personal blog, a team’s technical documentation, or a company’s marketing site — Hugo is worth understanding. It represents a philosophy as much as a tool: that publishing on the web can be fast, simple, durable, and entirely under your control.