DEV Community

Cover image for The Great Gatsby Migration
Sung M. Kim
Sung M. Kim

Posted on • Updated on • Originally published at

The Great Gatsby Migration

Photo by Ray Hennessy on Unsplash

I finished migrating a WordPress blog, to Gatsby,, yesterday (2019-11-10).

I will provide a "rough" list to describe what's done, as there is no one specific way to accomplish this and share my experience.

For a specific way to create a Gatsby blog, I will add links in the Resources section.

Why migrate?


  1. Pricing
    • I couldn't justify $170/year cost as the site isn't for profit.
  2. Slowness
    • As the site was running on a shared plan, the site was slow and a myriad of plugins made it even slower.
  3. The domain name sucked
    • was purchased years ago as it was cheap and not taken, and also based off on one of my favorite books, The Slight Edge.
    • But it's really a bad name, as it's hard to remember, type, long, and not memorable.
    • is short, memorable, and describes the site purpose.

Why Gatsby?

I've been working with React and that's what I know. There are other SSG or SSR frameworks, but the documentations and ecosystem made me choose it as the migration needed happen quickly. (I started migration after the site went offline).

Rough list

Export WordPress file

Follow steps here up to Move content from one WordPress site to another -> Export from Site A

Note that this exports an XML file, not as markdown.

I've tried Jekyll Exporter but it exported associated images to different folder, not within a folder with Markdown content.

I found it didn't co-located related files (content files and media) thus decided not to use this approach.

Export WordPress to Markdown

I used lonekorean/wordpress-export-to-markdown to convert exported WordPress file from previous step into Markdown files and download media thereof.

It's not a CLI, so you'd need to clone the source.

It's a node application with useful flags for options such as exporting grouped by years, months, etc.

Note that it won't import images in the body unless --contentimages flag is set.

Optional - Add more frontmatters

I had all content imported on DEV. DEV has a nice feature to export your content as JSON.

Under Settings/misc, you can export all of your content.

dev export

Previous step exports markdown but many frontmatters (such as tags, tags, author, etc.) are missing.

So I created a small node script, dance2die/fix-sungcodes-markdown-frontmatters to merge missing frontmatters from DEV json file.

Create or branch existing Gatsby site

Gatsby requires some learning curve so I will refer to you to the Gatsby tutorial.

I already had an existing repository, dance2die/ so I just created v2 branch to start from existing Gatsby site. (v1 was simply using WordPress RSS data to create a static version of it.)

After familiarizing with Gatsby, you can pursue further with following articles (I didn't follow the all the steps in both, just took the parts I needed)

Or, you can do what I did, standing on the shoulders of giants

Optional - Following Kent C. Dodds blog source

I knew that Kent C. Dodds (KCD, hereafter) migrated from Medium to Gatsby recently (and took very small part finding issues/typos during migration).

Reference: kentcdodds/

KCD has generously made the code open source with MIT, I decided to follow his steps and learn from it as well. You know, he is Kent C. Dodds.

KCD has create a global configuration, which made it easy to apply to the whole site.

It was crucial as the common configurations can be used for site content, SEO, or styling for a consistency and traffic.


  1. SEO components
  2. config

I've taken most of his configuration and SEO as well as blog post banner display codes.
Doing so made it easy to provide OpenGraph data for SEO and get the consistent configuration data throughout the whole site.

Optional - Redirect traffic

I decided to abandon in favor of

Firat Özcan helped me learn a way to 301 redirect easily with CloudFlare, which is what I did.

Reference: Configuring URL forwarding or redirects with Cloudflare Page Rules

If you need to keep your existing URL, rewrite your URL, instead of redirecting.

To Dos

  1. There are still a lot of styling issues for blog posts.
  2. To report an issue, I added a tweet link per post, but will make it work for GitHub (after creating a template).
  3. Also the biggest issue is a lack of CMS (Current I've created this blog markdown manually.)
    • I decided to go with NetlifyCMS because of its git based workflow, and the site being hosted on Netlify.
  4. RSS feed is not yet implemented. Need a manual copy & paste to share on DEV.



Here are the some issues that I've encountered.

  1. After "Export WordPress to Markdown", the frontmatter date didn't match by a day for some posts with WordPress slug, which used published dates.
  • It was due to WordPress using my local EST time to publish, while lonekorean/wordpress-export-to-markdown used UTC to parse dates and add it as "date" frontmatter metadata.
  • The fix was done during the "Optional - Add more frontmatters" step.
  • It was a sorta critical as I needed to do 301 redirect, and the off-by-one day wasn't able to properly forward to the new domain.
  1. I had no idea how KCD's banner code worked.
  1. Not all banner images or body images are exported/imported.
  • As there are 100+ posts, I wasn't able to check missing media for each.
  • But whenever I write my blogs, I store them on OneDrive, so able to recover'em all (but one by one).
  1. Might be none issue.
    • I've exported markdown in "content/<year>/blog" structure while KCD had a flat "/content/blog".
    • But it wasn't much of an issue because slug is generated dynamically within gatsby-node.js.


To provide a consistent UI, I used Theme-UI as gatsby plugin, gatsby-plugin-theme-ui.

Gist workaround

"gists" are shown as raw link, thus I used gatsby-remark-embed-gist but hacked by embedding gist CSS for blog post component.


Top comments (9)

bayuangora profile image
Bayu Angora

What about build and deploy time benchmark? Is it fast enough?

dance2die profile image
Sung M. Kim • Edited

I haven't done a benchmark (not sure how to...).

As I am using a free tier of Netlify, I just checked about 10 deploy logs.

The build + deploy ranges between 4~9 minutes (I have many images and posts therefore, so gatsby is generating thumbnails, optimized images etc).

It's fast enough as it's a static content mostly and not updated frequently for my use-case (free, fast load time, and can test locally before publishing, etc.).

bayuangora profile image
Bayu Angora

That's what I mean. I don't use Gatsby. But 4 minutes or more (for personal blog) is really slow. I use Hugo for my personal blog with hundred posts and few images, it's only takes below 2 minutes to build and deploy.

Thread Thread
dance2die profile image
Sung M. Kim

Build time is relative (to project size). And also, it's not just about build time.

Thread Thread
bayuangora profile image
Bayu Angora

Yes, it's depends on your needs.

joeey profile image

Although you was trying to migrate simple personal blog from WordPress to Gatsby you faced alot of hiccups in the process.. So I am wondering what if a huge WordPress site depends on woocomerce in its design want to take the same move.. Will be even possible of course without losing its traffic

dance2die profile image
Sung M. Kim

I lost lotcha traffic as the migration started "after" the site went down (recovered most of it nowadays).

what if a huge WordPress site depends on woocomerce in its design want to take the same move.

I had a trouble with a simple "table" plugin (to show a ToC) didn't work so I believe a migration of such a site would be require more up-front plan (what plugins are installed and how they are rendered etc).

powerc9000 profile image
Clay Murray

Oh so this is all your fault! I was trying to google how to do something and your article was a top hit. However since you deactivated your account I couldn't see it. You really aught to look into redirecting the old domain.

dance2die profile image
Sung M. Kim

Yupz it was my fault, as I let it suspend 😅

Try the old one, which will take you to the new one now.