Why migrate from WordPress to Hugo?
WordPress-to-Hugo is the most aggressive simplification path available for a content site. WordPress is a PHP application talking to MySQL on every request; Hugo is a Go binary that produces flat HTML files. The static output deploys to any CDN (Cloudflare Pages, Netlify, S3 + CloudFront) for cents per month, has zero attack surface for plugin CVEs, and serves in single-digit milliseconds at the edge.
The trade is ergonomics. WordPress's admin gives a non-technical editor a what-you-see-is-what-you-get UI; Hugo gives you a filesystem of Markdown files and a Git workflow. Every dynamic feature -- search, comments, contact forms, member areas -- requires a separate third-party JavaScript service or a separate backend. Hugo is the right answer when content is the entire product and the editorial team is comfortable with Markdown + Git.
The other gotcha: theme migration is rewrite, not port. Hugo themes are Go templates with a specific shape; WordPress themes are PHP. Plan on either using a stock Hugo theme or a 1-2 week rebuild of your design.
Before you start
- Pick your hosting. Cloudflare Pages, Netlify, Vercel, or GitHub Pages all serve Hugo output for free or near-free. Build-on-push from GitHub is the canonical workflow.
- Pick a theme. themes.gohugo.io has 400+ options. Filter by "blog" + look for active maintenance.
- Backup. Full WordPress DB +
wp-content/uploads. Same as any cutover.
Step-by-step migration
1. Install the WordPress-to-Hugo exporter
Two reasonable tools:
wp2hugo(Go binary) -- runs against the WordPress REST API remotely; no plugin install needed.wordpress-to-hugo-exporterPHP plugin -- runs inside WordPress, downloads a tarball.
The plugin path is most common:
wp plugin install wordpress-to-hugo-exporter --activate
# Then in WP admin: Tools -> Export to Hugo -> download .zip
The output is a directory tree:
content/
posts/
2024-04-15-my-post.md
pages/
about.md
static/
uploads/
2024/04/header.jpg
Each .md has YAML frontmatter (title, date, tags,
categories, featured_image).
2. Initialise a Hugo site
hugo new site mysite
cd mysite
git init
git submodule add https://github.com/your-theme/hugo-theme themes/yourtheme
echo "theme = 'yourtheme'" >> hugo.toml
Drop the exported content/ and static/ over the empty Hugo
defaults.
3. Run Hugo locally
hugo server -D
Visit http://localhost:1313. Walk through every section + every
post type. Common breakage:
- Featured-image paths may need a search-and-replace
(
/wp-content/uploads/->/uploads/). - Shortcodes like
[gallery]won't render -- replace with Hugo shortcodes or plain HTML. - Categories vs tags semantics differ; check theme expectations.
4. Set up redirects
Same as the Ghost migration: WordPress's /2024/04/my-post/
becomes Hugo's /posts/my-post/ (default theme) or /my-post/
(if you set permalinks in hugo.toml).
In Cloudflare Pages, use a _redirects file at the project root:
/2024/:month/:post /posts/:post 301
In Netlify, same syntax. In GitHub Pages, use a JS-based redirect in a one-off HTML page per old URL (less clean -- prefer a host that supports server-side redirects).
5. Build + deploy
hugo --minify
# output is in ./public
Push to your host. Build-on-push from GitHub is the canonical workflow:
# .github/workflows/deploy.yml
- uses: peaceiris/actions-hugo@v2
with: { hugo-version: 'latest' }
- run: hugo --minify
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
6. Replace dynamic features with static-friendly alternatives
- Search: Pagefind, lunr.js, or Algolia DocSearch.
- Comments: Disqus, Giscus (GitHub Discussions), Cusdis.
- Forms: Formspree, Tally, Cloudflare Workers handler.
- Newsletter: Buttondown, ConvertKit signup form.
What doesn't migrate automatically
- WooCommerce + any e-commerce primitive.
- Membership plugins (Restrict Content Pro, MemberPress) -- Hugo has no auth layer.
- Comments (lost; bridge to Disqus or accept the loss).
- WordPress search box (replace with Pagefind).
- Custom post types beyond simple
posts+pages.
Common pitfalls
- Theme rebuild is the hidden cost. Plan a week, not an
afternoon. Hugo themes have specific layout assumptions (which
partials they expect, what data the
Siteobject exposes); a WordPress theme designer can't drop a PSD and expect Hugo to render it. - Image paths break. Run a search-and-replace across exported
.mdfiles before commit (/wp-content/uploads/->/uploads/). - Drafts get exported. Filter
draft: trueposts in your build pipeline (hugo --buildDrafts=false, the default). - Author taxonomy doesn't survive cleanly. Hugo's default theme
uses a single author; WordPress's
Authorfield becomes a string with no link. Plan accordingly.
How BeaverCheck measures the difference
We've audited 713 WordPress sites and 33 Hugo sites. Average Lighthouse performance: WordPress 45 / 100, Hugo 69 / 100, a difference of +24 points.
The static-output gap is real and measurable. Run a free audit on your current WordPress site to see the numbers before committing to the move.
Further reading
- Hugo Quick Start
- WordPress-to-Hugo exporter
- Compare both stacks side-by-side: WordPress vs Hugo