From Wordpress To Eleventy With Ease
Preface: This version of the article is for humans and search engines. Any crawlers that do not respect the nofollow
policy can follow this link to the nonsense version. And they can choke on it.
I recently converted this site from an old Wordpress to Eleventy. I then promised I’d share how I did it, because it really doesn’t have to be difficult. In fact, with the small node script to follow, you should have everything set up in about 5 minutes.
Step 1: Get the old Wordpress data
First you need to get your post content—and associated media—from Wordpress. Since I’ve obliterated the original Wordpress site now, I can’t retrace quite how I did this. I remember it being very straightforward. To get all of my Wordpress post data as JSON, I either used the core export functionality or a popular plugin. Or maybe the Wordpress REST API. If I could manage it, you shouldn’t have much trouble. To get all the images, I almost certainly used a plugin like this one.
In any case, you should end up with a JSON file full of stuff that looks something like this…
...
"post": {
"ID": 14,
"post_author": "1",
"post_date": "2014-08-01 00:00:09",
"post_date_gmt": "2014-08-01 00:00:09",
"post_content": "<p>Hi everybody! I've just done a lot of cocaine on the company expense account...",
"post_title": "Reinventing The Hyperlink",
...
… and a directory of media with subfolders named after years, like:
- 📂 2011
- 📂 2012
- 📂 2013
- 📂 2014
- etc.
You’ll want to unzip this exported media archive into wherever the rest of your Eleventy images go.
Step 2: JSON to markdown plus Front Matter
This is where you can use my simple node script. Here it is in its entirety, with notes to follow:
const transformAndWriteToFile = require('json-to-frontmatter-markdown').default;
const wordpressData = require(__dirname + '/wordpress.json');
const slugify = require('slugify');
const posts = wordpressData.post.posts;
Object.keys(posts).forEach((p, i) => {
let post = posts[p].post;
transformAndWriteToFile({
frontmatterMarkdown: {
frontmatter: [
{ title: post.post_title },
{ date: post.post_date.split(' ')[0] },
{ permalink: `article/${slugify(post.post_title).toLowerCase()}/index.html` }
],
body: post.post_content.replace(/http:\/\/www.heydonworks.com\/wp-content\/uploads/g, '/images')
},
path: './src/posts',
fileName: `${slugify(post.post_title).toLowerCase()}.md`
})
})
- Take a note of the
require
lines. You will have tonpm install
(or Yarn, whatever) thejson-to-frontmatter-markdown
andslugify
dependencies. Thewordpress.json
file is the JSON data I exported in Step 1: Get the old Wordpress data. - The
frontmatter
part takes the properties I’m interested in from each post and converts them to front matter values. The permalink structure I happen to use starts with/article
. By salvaging this structure from the original site, I could avoid doing rewrites/redirects. - The
body
part writes the post content but, critically, re-paths each of the images to use the local Eleventy URL - The
path
is where to write the file (presumably where all my non-legacy posts also reside) - Finally,
fileName
actually names the markdown file itself, slugifying thepost_title
value as my Wordpress site was instructed to do.
Step 3: Run the script
You can set up an npm script if you really must, but since I knew I’d only run this once, I just hit node wordpress.js
(where wordpress.js
is the name of the script file, and it’s in the root of the directory).
Step 4: There is no step 4
This step doesn’t even exist. But it's worth noting that, on my site, I split my old Wordpress posts between archive and best (my best posts) directories. Each article (including each new article) on my site has an article/slug-here
URL structure, but belongs to one of the latest, best, or archive collections.
In Eleventy, you can set the collection per-post by adding a tags
property to its front matter. But it’s less verbose to to add a data file to the appropriate directory instead. For example, my latest posts go in the /latest
directory, which contains a latest.json
file with the line "tags": "latest"
.
Not everyone is a fan of my writing. But if you found this article at all entertaining or edifying, I do accept tips. I also have a clothing line: