Skip to main content

Migrating a Site From Wordpress to Hugo

·7 mins

I recently migrated several sites, including this one, from WordPress to Hugo. I learned a lot doing the migration and decided to share what I learned to help others who want to migrate to Hugo.

Prerequisites #

Getting the most out of this article requires the following:

  • You installed Hugo.
  • You know how to use the command line.
  • You know how to access your site’s files on your web host.

Backup WordPress #

Start by backing up your WordPress data in case the migration goes wrong. Export your WordPress content using the Export tool in the WordPress administration panel. Backup the database as well. You can even backup the whole site if your web host has a tool to do that.

Convert the WordPress Posts to Markdown #

WordPress and Hugo store posts and pages differently. WordPress posts and pages are HTML files that are stored in a database. Hugo uses Markdown to store posts and pages. To convert your WordPress posts and pages to Hugo, you must convert them to Markdown.

I used the WordPress to Hugo Exporter plugin to migrate the WordPress posts and pages to a format that Hugo can use.

This plugin is not part of the WordPress plugin directory so you have to download the plugin from GitHub and copy the plugin to the plugins folder on your WordPress site. Once you have the plugin copied, you can activate it from the WordPress administration panel. After activating the plugin, you can export the data by choosing Export to Hugo from the Tools menu.

When you choose Export to Hugo, the plugin will download a zip file that contains a folder with the following items:

  • A posts folder that contains Markdown files for each blog post.
  • A folder for each page that contains a Markdown file for the page.
  • A wp-content folder that contains the images in your posts and pages.
  • A config.yaml file that contains the URL, name, and description of the site.

Create the Hugo Site #

After converting your WordPress content to Markdown, you can create your Hugo website.

The Hugo website has a Quick Start guide that shows you how to create a new site. I’m not going to repeat the information here.

Add a Theme #

Every Hugo site requires a theme that controls how the site looks. The Hugo site has a page of themes for you to browse.

The easiest way to add a theme to your site is to navigate to the themes directory in your project and run the git clone command, supplying the URL of the GitHub repo for the theme. The following command installs the Congo theme:

git clone https://github.com/jpanther/congo

After installing the theme set the theme to use in the hugo.toml file. The following code sets the theme to Congo:

theme = 'congo'

When I was testing out themes to use for my sites, I noticed that themes that had not been updated in 6 or more months caused problems. I would get errors when I built the site. I recommend starting with themes that have been updated in the past few months.

Configure the Site #

Open the file hugo.toml. The contents of the file should look similar to the following:

baseURL = 'https://example.org/'
languageCode = 'en-us'
title = 'My New Hugo Site'

Change the baseURL and title to the URL and title of your site. If you use the Wordpress to Hugo Exporter plugin, you can use the contents of the config.yaml file to configure the site.

Add a Navigation Menu #

Most sites have a navigation menu. Open the hugo.toml file to add a navigation menu to your site.

Add a [menus] section to add the menu. Add an entry for each item. The following code recreates the navigation menu for this site:

[menus]
	[[menus.main]]
		name = 'Articles'
		pageRef = '/posts'
		weight = 10
	[[menus.main]]
		name = 'GitHub'
		url = 'https://github.com/meandmark'
		weight = 20
	[[menus.main]]
		name = 'RSS Feed'
		pageRef = '/index.xml'
		weight = 30
	[[menus.main]]
		name = 'Contact'
		pageRef = '/contact'
		weight = 40

The name argument is the name of the item. Use the pageRef argument for internal links and url for external links. I’m not sure what the weight argument is used for. But every example I’ve seen uses increasing weight values for menu items.

The Hugo documentation says to use pageRef for internal links. But I found that Hugo generated empty links for the internal links. I had to use url to generate working links. If you get empty links, use url instead of pageRef.

[menus]
	[[menus.main]]
		name = 'Articles'
		url = '/posts'
		weight = 10
	[[menus.main]]
		name = 'GitHub'
		url = 'https://github.com/meandmark'
		weight = 20
	[[menus.main]]
		name = 'RSS Feed'
		url = '/index.xml'
		weight = 30
	[[menus.main]]
		name = 'Contact'
		url = '/contact'
		weight = 40

Copy Your Content to Hugo #

If you use the WordPress to Hugo Converter plugin, the download contains a posts folder for your posts and a folder for each WordPress page. Copy those folders to the content folder of your Hugo project.

Add a Home Page #

Some of the WordPress sites I was migrating did not have a dedicated home page. The home page would show a list of posts. I found that what the home page showed on those sites depended on the theme. If you want more control over the contents of the home page, I recommend creating a dedicated home page for your Hugo site.

Add a file named _index.md to the content folder to create a home page. Notice the leading underscore character in the file name. If you omit the underscore, the changes you make to the site will not appear on the rest of the site. When I named the file index.md on one of my sites, the changes I made to the links in the navigation menu would only apply to the home page.

After creating the _index.md file, you can add whatever content you want on the home page.

Dealing with Images #

If you look at the Markdown file of a post or page with images, you will notice the file uses HTML image tags instead of Markdown tags. The HTML image tag looks similar to the following:

<img loading="lazy" decoding="async" src="https://www.meandmark.com/blog/wp-content/uploads/2022/02/Xcode13InfoPlist.png" alt="Xcode13InfoPlist" border="0" width="512" height="245" /> 

The parser Hugo uses to convert Markdown to HTML ignores raw HTML in Markdown by default. When you build the Hugo project, the HTML image tags are ignored. The HTML files for your site will have no images in them.

To get the images to appear, you must configure your project to tell the Markdown parser to process raw HTML in Markdown. In the hugo.toml file, add the following code:

[markup.goldmark.renderer]
  unsafe = true

Looking at the HTML markup for the image, notice that the image file is buried in a hierarchy of folders inside a wp-content folder. The WordPress to Hugo Converter plugin generates a wp-content folder. This folder and its contents must be in the folder where your site resides on your web host’s server.

Copy the wp-content folder into the Hugo project’s content folder. When you build the project, the folder will be copied to the public folder. The Hugo documentation says image files belong in the assets folder, but the folder wasn’t copied when I had the wp-content folder in the assets folder.

Another alternative is to copy the wp-content folder and its contents directly to your web host.

Test Your Site #

At this point you are ready to test your site. Start by running the hugo command to build the project.

hugo

Run the hugo server command to start a server to test your Hugo site.

hugo server

You can access your site in a web browser with the following URL:

localhost:1313

Deploy Your Site #

When everything is working correctly, you can deploy your site. Run the hugo command to build the project.

hugo

The public folder contains the built website.

Go to your web host and copy the contents of the public folder to the main folder for your domain. The exact location depends on your web host, but most web hosts have a public_html folder as the main folder. Go inside that folder and copy the contents of the public folder.

Questions #

If you have any questions about migrating a WordPress site to Hugo, go to the Contact page to email me your question.