Hugo + PaperMod Theme: A Complete Crash Course
Introduction
Hugo is a blazing fast static site generator written in Go. Combined with the elegant PaperMod theme, it’s a powerful solution for creating modern websites, blogs, and documentation. This crash course will guide you through setting up, configuring, and customising your Hugo site with PaperMod. This is how I created my site.
Installation
Install Hugo
First, you need to install Hugo on your system:
On macOS (using Homebrew):
brew install hugo
On Windows (using Chocolatey):
choco install hugo -confirm
On Linux (Debian/Ubuntu):
sudo apt-get install hugo
Verify your installation:
hugo version
Tip: you’ll need to install Chocolatey as well if not done already.
Creating a New Site
Create a new Hugo site:
hugo new site mysitename
cd mysitename
This creates a new Hugo site in a folder named mysitename
.
Installing the PaperMod Theme
You can install the PaperMod theme in two ways:
Method 1: Using Git Submodules (Recommended)
git init
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
Method 2: Manual Download
- Download the theme from GitHub
- Extract it to the
themes/PaperMod
directory
Basic Configuration
Create or modify the config.yml
file in your site’s root directory:
baseURL: "https://yourwebsite.com/"
title: "Your Site Title"
pagerSize: 5
theme: PaperMod
enableRobotsTXT: true
buildDrafts: false
buildFuture: false
buildExpired: false
minifyOutput: true
params:
env: production
title: Your Site Title
description: "Your site description"
keywords: [Blog, Portfolio, PaperMod]
author: Your Name
DateFormat: "January 2, 2006"
defaultTheme: auto # dark, light, auto
disableThemeToggle: false
ShowReadingTime: true
ShowShareButtons: true
ShowPostNavLinks: true
ShowBreadCrumbs: true
ShowCodeCopyButtons: true
ShowWordCount: true
ShowRssButtonInSectionTermList: true
UseHugoToc: true
disableSpecial1stPost: false
disableScrollToTop: false
comments: false
hidemeta: false
hideSummary: false
showtoc: true
tocopen: false
assets:
# disableFingerprinting: true
favicon: "/favicon.ico"
favicon16x16: "/favicon-16x16.png"
favicon32x32: "/favicon-32x32.png"
apple_touch_icon: "/apple-touch-icon.png"
profileMode:
enabled: false
title: Your Name
subtitle: "Your short bio here"
imageUrl: "/images/profile.jpg"
imageWidth: 120
imageHeight: 120
buttons:
- name: Archives
url: archives
- name: Tags
url: tags
socialIcons:
- name: twitter
url: "https://twitter.com/"
- name: github
url: "https://github.com/"
- name: linkedin
url: "https://linkedin.com/in/"
cover:
hidden: false
hiddenInList: false
hiddenInSingle: false
menu:
main:
- identifier: categories
name: Categories
url: /categories/
weight: 10
- identifier: tags
name: Tags
url: /tags/
weight: 20
- identifier: archives
name: Archives
url: /archives/
weight: 30
- identifier: search
name: Search
url: /search/
weight: 40
Content Management
Creating Posts
Create a new post:
hugo new posts/my-first-post.md
This creates a new file at content/posts/my-first-post.md
with default front matter:
---
title: "My First Post"
date: 2023-04-29T10:30:00+00:00
draft: true
tags: ["first"]
categories: ["example"]
---
Your content here...
Remember to set draft: false
when you’re ready to publish.
Front Matter Options
PaperMod supports many front matter options:
---
title: "My Post Title"
date: 2023-04-29
draft: false
description: "Description of the post"
tags: ["hugo", "papermod", "tutorial"]
categories: ["web development"]
weight: 1
cover:
image: "/path/to/image.jpg"
alt: "Alternative text"
caption: "Image caption"
relative: false
showToc: true
TocOpen: false
hidemeta: false
comments: false
---
Content Structure
content/
├── posts/
│ ├── post-1.md
│ └── post-2.md
├── about.md
└── projects/
├── project-1.md
└── project-2.md
Customising PaperMod
Creating Homepage Layouts
PaperMod offers three homepage layouts:
- Default (List): Shows a list of posts
- Profile Mode: Focused on personal info
- Cover Mode: Shows a full-page cover image
To enable Profile Mode, update your config.yml
:
params:
profileMode:
enabled: true
title: "Your Name"
subtitle: "Your bio or tagline"
imageUrl: "/images/profile.jpg"
buttons:
- name: Blog
url: posts
- name: Projects
url: projects
Adding Search Functionality
- Create a search page:
hugo new search.md
- Add this content to
search.md
:
---
title: "Search"
layout: "search"
summary: "search"
placeholder: "Search posts..."
---
- Add search to your menu in
config.yml
:
menu:
main:
- identifier: search
name: Search
url: /search/
weight: 10
Custom CSS
Create a file at assets/css/extended/custom.css
for your custom styles:
/* Your custom styles here */
body {
/* Custom body styles */
}
.post-title {
/* Custom post title styles */
}
Custom Shortcodes
Create custom shortcodes in layouts/shortcodes/
:
For example, create layouts/shortcodes/notice.html
:
<div class="notice {{ .Get 0 }}">
{{ .Inner | markdownify }}
</div>
Use it in your content:
{< notice info >}
This is an info notice.
{< /notice >}
Deployment
Local Preview
Run a local server:
hugo server -D
This starts a server at http://localhost:1313/
. The -D
flag includes draft posts.
Building for Production
Build your site:
hugo --minify
This generates your site in the public/
directory, ready for deployment.
Deployment Options
GitHub Pages
- Create a
.github/workflows/hugo.yml
file:
name: Deploy Hugo site
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
- 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
- Set your repository settings to deploy from the
gh-pages
branch.
Netlify
- Push your Hugo site to a GitHub repository
- Sign up for Netlify
- Import your repository
- Set build command to
hugo --minify
and publish directory topublic
Hugo Command Line Flags & Environment Variables
Hugo offers numerous command line flags and environment variables that can significantly impact your development workflow and site performance.
Important Command Line Flags
When using hugo server
for local development:
# Basic development server
hugo server
# Include draft content
hugo server -D
# Fast render mode (disable for accurate rendering)
hugo server --disableFastRender
# Force rebuilds on file changes
hugo server --disableLiveReload
# Bind to all network interfaces (access from other devices)
hugo server --bind="0.0.0.0"
# Specify port
hugo server --port=8080
# Watch for changes in theme folder too
hugo server --ignoreCache --themesDir=../..
# Full rebuild on changes (slower but more accurate)
hugo server --disableFastRender --renderToDisk
When building your site for production:
# Standard build
hugo
# Minify output
hugo --minify
# Include expired content
hugo --buildExpired
# Include future-dated content
hugo --buildFuture
# Include draft content (generally not for production)
hugo --buildDrafts
# Specify base URL
hugo --baseURL="https://example.com/"
# Verbose output for debugging
hugo -v
Environment Variables
# Set environment
HUGO_ENV=production hugo
# Change number of parallel workers
HUGO_NUMWORKERMULTIPLIER=2 hugo
# Cache settings
HUGO_CACHEDIR=/path/to/cache hugo
# Resource cache
HUGO_RESOURCEDIR=/path/to/resources hugo
# Disable symlinks in file detection
HUGO_DISABLEPATHTOFILEBYDISABLEDSYMPATHY=true hugo
# Disable .git directory ignore
HUGO_IGNOREGIT=true hugo
Performance Optimisation Flags
# Enable HTTP/2 server push
hugo server --http2
# Disable lazy loading of images
hugo --disableLazyLoading
# Control image processing concurrency
HUGO_IMAGES_PROCESSOR_COUNT=4 hugo
Configuration-Based Settings
You can also set many of these options in your config.yml
:
# Build options
buildDrafts: false
buildFuture: false
buildExpired: false
disableFastRender: false
enableGitInfo: true
# Performance settings
minify: true
disableHugoGeneratorInject: true
Troubleshooting
Common Issues and Solutions
Theme Not Showing: Check if the theme is properly installed and referenced in your
config.yml
# Check theme directory ls -la themes/
Taxonomy Pages Missing: Ensure you’ve defined taxonomies in your config
taxonomies: category: categories tag: tags
Images Not Loading: Verify image paths and try using page bundles
Create a directory structure:
content/ └── posts/ └── my-post/ ├── index.md └── images/ └── featured.jpg
Then reference with:

Hugo Server Error: Clear cache and restart
hugo mod clean hugo server
Advanced Features
Adding a Comment System
To add Disqus comments:
- Update your
config.yml
:
disqusShortname: your-disqus-shortname
- Enable comments in front matter:
---
title: "My Post with Comments"
comments: true
---
Multilingual Support
Update your config.yml
:
languageCode: "en-us"
defaultContentLanguage: "en"
languages:
en:
languageName: "English"
weight: 1
taxonomies:
category: categories
tag: tags
fr:
languageName: "Français"
weight: 2
taxonomies:
category: categories
tag: tags
Create language-specific content:
content/
├── posts/
│ └── hello-world.md # English
└── fr/
└── posts/
└── bonjour-monde.md # French
Content Organisation with Page Bundles
Page bundles keep content and its resources together:
content/
└── posts/
└── my-bundled-post/
├── index.md
├── image1.jpg
└── data.json
Reference bundled resources in your content:

Useful Resources
- Hugo Documentation
- PaperMod Wiki
- Hugo Forum
- PaperMod GitHub Repository
- Markdown Guide
- Learn Hugo in Under 2 Hours
Conclusion
This crash course has provided you with the essential knowledge to get started with Hugo and the PaperMod theme. As you become more comfortable, explore Hugo’s documentation and the PaperMod wiki for advanced features and customisation options.
Hugo’s strength lies in its flexibility and speed, while PaperMod offers a clean, modern design with excellent performance. Together, they provide an excellent foundation for your website.
Happy building!