After years of running my blog on WordPress, I finally made the switch to Hugo and GitHub Pages. The result? A blazingly fast, version-controlled blog that costs nothing to host. Here’s how I did it and what I learned along the way.
Why I Made the Switch
WordPress is powerful, but over time I found myself frustrated with:
- Performance issues: Even with caching plugins, my site felt sluggish
- Security concerns: Constant updates and vulnerability patches
- Hosting costs: Paying monthly for shared hosting
- Database complexity: Backing up and managing MySQL databases
- Plugin bloat: Each feature required another plugin
Hugo offered a compelling alternative: static site generation, Git-based workflow, and free hosting on GitHub Pages.
Prerequisites
Before starting, make sure you have:
- Hugo installed (
brew install hugoon Mac, or download from gohugo.io) - Git installed
- A GitHub account
- Access to your WordPress admin panel
Step 1: Export Your WordPress Content
First, I needed to get my content out of WordPress.
Using the WordPress Exporter Plugin
- Install the “WordPress to Hugo Exporter” plugin (or use the built-in WordPress exporter)
- Go to Tools → Export in your WordPress admin
- Select “All content” and download the XML file
For the WordPress to Hugo Exporter plugin:
# Install via WP-CLI if you prefer
wp plugin install wordpress-to-hugo-exporter --activate
wp hugo-export
This creates a ZIP file with your posts in Markdown format, organized by date.
Alternative: Manual Export with Jekyll Exporter
If the Hugo exporter doesn’t work well, you can use the Jekyll exporter and convert later:
wp plugin install jekyll-exporter --activate
wp jekyll-export
Step 2: Set Up Hugo Locally
Create your new Hugo site:
# Create a new Hugo site
hugo new site my-blog
cd my-blog
# Initialize git repository
git init
# Add a theme (I chose PaperMod, but there are many options)
git submodule add https://github.com/adityatelange/hugo-PaperMod themes/PaperMod
Edit hugo.toml (or config.toml) to configure your site:
baseURL = 'https://yourusername.github.io/'
languageCode = 'en-us'
title = 'My Awesome Blog'
theme = 'PaperMod'
[params]
description = "A blog about technology and life"
author = "Your Name"
[menu]
[[menu.main]]
name = "Home"
url = "/"
weight = 1
[[menu.main]]
name = "Posts"
url = "/posts/"
weight = 2
[[menu.main]]
name = "About"
url = "/about/"
weight = 3
Step 3: Import and Clean Your Content
Copy your exported WordPress posts to Hugo:
# Create posts directory if it doesn't exist
mkdir -p content/posts
# Copy exported posts
cp -r ~/Downloads/wordpress-export/* content/posts/
Now comes the tedious part: cleaning up the content. I had to:
Fix Front Matter
WordPress posts might have messy front matter. Standardize it:
---
title: "Your Post Title"
date: 2024-01-15T10:00:00Z
draft: false
tags: ["tag1", "tag2"]
categories: ["category1"]
---
Convert Image Paths
WordPress uses absolute URLs for images. I needed to:
- Download all images from WordPress
- Place them in
static/images/ - Update image references in posts:
# Find and replace image URLs
find content/posts -type f -name "*.md" -exec sed -i '' 's|https://oldsite.com/wp-content/uploads/|/images/|g' {} +
Fix Shortcodes
WordPress shortcodes don’t work in Hugo. I replaced them with standard markdown or HTML:
WordPress:
[gallery ids="1,2,3"]
Hugo (using HTML):
<div class="gallery">
<img src="/images/img1.jpg" alt="Image 1">
<img src="/images/img2.jpg" alt="Image 2">
<img src="/images/img3.jpg" alt="Image 3">
</div>
Or use standard markdown:



Step 4: Set Up GitHub Repository
Create a repository for your Hugo site:
# On GitHub, create a new repository named: yourusername.github.io
# Add remote and push
git remote add origin git@github.com:yourusername/yourusername.github.io.git
git add .
git commit -m "Initial commit: Hugo site"
git push -u origin main
Step 5: Configure GitHub Actions for Deployment
Create .github/workflows/hugo.yml for automatic deployment:
name: Deploy Hugo site to Pages
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
defaults:
run:
shell: bash
jobs:
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.121.0
steps:
- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v4
- name: Build with Hugo
env:
HUGO_ENVIRONMENT: production
HUGO_ENV: production
run: |
hugo \
--gc \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Step 6: Enable GitHub Pages
- Go to your repository Settings
- Navigate to Pages (in the sidebar)
- Under “Source”, select “GitHub Actions”
- Your site will build and deploy automatically
Step 7: Set Up Custom Domain (Optional)
If you want to use your own domain:
Add a
CNAMEfile to yourstatic/folder:yourdomain.comConfigure DNS records with your domain provider:
- Add A records pointing to GitHub’s IPs:
- 185.199.108.153
- 185.199.109.153
- 185.199.110.153
- 185.199.111.153
- Or add a CNAME record:
yourusername.github.io
- Add A records pointing to GitHub’s IPs:
In GitHub repository settings, add your custom domain
Step 8: Set Up Redirects
To preserve SEO, I set up redirects from my old WordPress URLs to new Hugo URLs.
Create static/_redirects (if your hosting supports it) or use meta refresh:
<!-- In your 404.html or individual posts -->
<meta http-equiv="refresh" content="0; url=/posts/new-url/">
For GitHub Pages, I created alias front matter in posts:
---
title: "My Post"
aliases:
- /2024/01/old-wordpress-slug/
---
Lessons Learned
What Went Well
- Speed improvement: My site loads 10x faster
- Version control: Every change is tracked in Git
- Cost savings: Zero hosting costs
- Simplicity: No database, no PHP, just static files
- Security: No backend to hack
Challenges I Faced
- Time investment: Content cleanup took longer than expected
- Learning curve: Hugo’s templating syntax required learning
- Missing features: Comments required third-party services (I used Giscus)
- Build times: Large sites can be slow to build locally
Things I’d Do Differently
- Start with a simpler theme to learn Hugo basics
- Automate the content cleanup with scripts
- Set up staging branch for testing before deployment
- Document my custom shortcodes from the start
Useful Resources
Conclusion
Migrating from WordPress to Hugo was one of the best technical decisions I’ve made for my blog. The initial time investment was worth it for the long-term benefits of speed, simplicity, and cost savings.
If you’re considering making the switch, my advice is: start small, migrate one category at a time if needed, and don’t rush the content cleanup process. Your future self will thank you for taking the time to do it right.
Post created with AI
Last updated: February 9, 2026