Host a Website for Free with Hugo and GitHub Pages
If you want a personal site or portfolio and don't want to pay for hosting or deal with a CMS, Hugo + GitHub Pages is the cleanest option out there. Your site builds in milliseconds, lives in a git re
If you want a personal site or portfolio and don't want to pay for hosting or deal with a CMS, Hugo + GitHub Pages is the cleanest option out there. Your site builds in milliseconds, lives in a git repo, and deploys for free.
This guide walks through the whole thing from scratch.
What You Need
Before starting, make sure you have:
- Hugo installed β gohugo.io/installation
- A GitHub account
- Git installed
Install Hugo:
# macOS
brew install hugo
Windows
choco install hugo-extended
Linux
sudo snap install hugo
Verify it's working:
hugo version
π‘ Make sure you install the extended version β many themes require it for SCSS compilation.
Step 1 β Create a New Site
hugo new site my-site
cd my-site
git init
This generates the Hugo scaffolding β content/, layouts/, static/, and hugo.toml.
Step 2 β Add a Theme
Hugo ships with no default theme, so you need to add one. Browse themes.gohugo.io and pick one. We'll use PaperMod here β clean, fast, and well-maintained.
git submodule add https://github.com/adityatelange/hugo-PaperMod themes/PaperMod
Then open hugo.toml and tell Hugo to use it:
theme = "PaperMod"
β οΈ Always add themes as git submodules, not by copying files. This keeps the theme updateable and plays nicely with GitHub Actions.
Step 3 β Configure the Site
Open hugo.toml and fill in your details:
baseURL = "https://your-username.github.io/"
languageCode = "en-us"
title = "Your Name"
theme = "PaperMod"
[params]
description = “Your site description”
π‘ The
baseURLmust match your GitHub Pages URL exactly β including the trailing slash. Get this wrong and your CSS, images, and links will all break.
Step 4 β Add Your First Post
hugo new content posts/hello-world.md
Open the generated file at content/posts/hello-world.md. It will look like:
---
title: Hello World
date: 2026-04-29
draft: true
---
Set draft: false and write your content below the second ---.
Preview the site locally:
hugo server -D
Visit http://localhost:1313 β you should see your post live with hot reload on every save.
Step 5 β Create a GitHub Repository
Go to GitHub and create a new repository named exactly:
your-username.github.io
This naming convention is what makes GitHub serve it at the root URL. For example, if your username is chris, the repo is chris.github.io and the site lives at https://chris.github.io.
Push your local site to it:
git add .
git commit -m "initial site"
git branch -M main
git remote add origin https://github.com/your-username/your-username.github.io.git
git push -u origin main
Step 6 β Set Up Automated Deployment
Instead of manually running hugo and copying files, we'll use GitHub Actions to build and deploy on every push.
Create the file .github/workflows/deploy.yml:
name: Deploy Hugo Site
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive # needed to pull the theme
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: latest
extended: true
- name: Build
run: hugo --minify
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
Commit and push this file:
git add .github/workflows/deploy.yml
git commit -m "add deploy workflow"
git push
Step 7 β Enable GitHub Pages
In your repository:
- Go to Settings β Pages
- Under Source, select GitHub Actions
- Save
That's it. GitHub will now run the workflow on every push to main. Check the Actions tab to watch the build β it takes about 30β60 seconds.
Your site will be live at:
https://your-username.github.io
What's Next
Once your site is running, a few things worth doing:
- Add more posts β create files under
content/posts/and push - Customise the theme β most themes expose config options in
hugo.toml, check the theme's README - Custom domain β buy a domain, add a
CNAMEfile to yourstatic/folder, and configure DNS to point atyour-username.github.io - Analytics β drop in a script tag via
layouts/partials/without touching the theme files
Why Hugo Over Other Options
| Hugo | Jekyll | Next.js | |
|---|---|---|---|
| Build speed | β‘ Milliseconds | Slow on large sites | Medium |
| Hosting | Free (GitHub Pages) | Free (GitHub Pages) | Vercel free tier |
| Learning curve | Low | Low | MediumβHigh |
| Customisation | Theme-based | Theme-based | Full control |
| Good for | Blogs, portfolios | Blogs | Apps + blogs |
Hugo wins on build speed and simplicity for content-first sites. If you need interactivity or server-side logic, reach for Next.js instead.
The whole setup takes under 30 minutes and costs nothing. Once it's running, publishing is just writing a markdown file and running git push.
