Gears and Cogs As you may have noticed, I recently moved this blog to a new platform.

Some have asked me what all went into this new version of my blog. In my last post on this topic, I covered the primary frameworks and infrastructures I used for the blog. In this post, we'll look at the secondary tools as well as the migration process.

Other Infrastucture & Tools

As described before, I am using Ghost for the blogging platform with some CPanel-managed hosting by MDD Hosting and Cloudflare sitting in front of the host. However, that's not quite the full picture. Here are the other important things:

Image Hosting: Cloudinary

If you're familiar with Ghost, you'll know that hosting images and other content is not something it's good at. For content in a post, like screenshots or file downloads, Ghost doesn't natively handle this well. Somewhat confusingly, though, it does have an image-hosting mechanism for a post's hero image. For the most part, I'm not using that feature and am instead using my own custom hero images (like the cogs at the top of this post). But that comes back to the question: How do I host images and photos?

Turns out, there's a great service at that works well. Prior to embarking on this migration I had never before used Cloudinary, so time will tell whether that was a good decision or not. However, so far it's been really good! There was a great migration path that they supported (which we'll get into later) and they have a free option that covers my needs very well! The only problem I have at this point is that I'm not a huge fan of how well they scale cost-wise since their cheapest non-free plan is nearly $50 per month, which is a pretty big jump in expense!

One of the neat things that Cloudinary supports is querystring-based image manipulation. That means I can upload an image there once and then request it in different formats and sizes and they'll perform the transformation on their end (I think it's real-time the first time then saved/cached for future requests). They support a LOT of manipulates so I recommend you try them out but you can do things like add filters, borders, rounded corners fading to a background color, and lots more, all just by tweaking the querystring request of the image. I haven't used them for anything with heavy traffic but for this little blog, they're working very well so far.

Comment System: Disqus

Again, if you're familiar with Ghost, you'll know that comments are not something built into the Ghost platform. So this means that, if you want to even support comments, you need to find a third-party platform for them. Fortunately, we have some options there. While I was hesitant to do so, I ended up going with Disqus on this one.

Why was I hesitant? Because they've had some bad problems in the past with inadvertently allowing malicious ads coming through their network.

Why did I still go with them? Three reasons:

  1. Like them or hate them, they're the platform that you most likely have an account on (unless I go Facebook, but no thanks!)
  2. They're by far the easiest-to-integrate platform to Ghost
  3. They had a viable migration option for preserving comments from my old blog system to this system

Okay. That's Great. How'd you do it?

So first of all, I am NOT going to be able to give you a step-by-step recount of exactly what I did. A lot of it I was figuring it out as I went. I was doing it in a way such that if it was a spectacular failure then I could just throw away the changes and start all over. Turns out my first trial attempt was my only one, so it wasn't very well documented. However, I can certainly point you in the right direction!


Okay, first, let's recap what we were migrating from and to:

Old Setup

  • Platform: Wordpress
  • Hosting: CPanel shared Linux host
  • Images: Wordpress
  • Comments: Wordpress

New Setup

  • Platform: Ghost
  • Hosting: Different CPanel shared Linux host
  • Images: Cloudinary
  • Comments: Disqus

Step 1: Migrate Comments

Wordpress has some pretty decent documentation on this process. I recommend you follow their information since the steps can change over time but I mostly did something like this:

  1. Installed the Disqus plugin for Wordpress
  2. Created/logged into my Disqus account and provisioned my blog application
  3. Exported & migrated all comments in my Wordpress blog over to Disqus using the above plugin associated with my Disqus application
How'd it go?

Well, the migration was pretty easy/trivial. It only took about 5 minutes of actual migration time for my comments to move over and be active in Disqus instead of the Wordpress comment system. However, post-migration, you'll notice none of my old posts' comments are there. Turns out I didn't quite plan everything perfectly and as I moved from Wordpress to Ghost, my blog posts' URLs changed. This is a pretty common problem with a ton of ways to work around and address. However, I made the decision that I'm okay losing those comments for now. However, I still have all of those comments (both a backup & online in Disqus) so if I ever change my mind, I can always recover those comments to restore them. This is probably the biggest problem with this entire migration and, honestly, I'm not losing any sleep over it. Yes, I could have done better but I ultimately decided it was a project for another day.

Step 2: Migrate images & photos

Cloudinary has a plugin that makes this a very easy task. I recommend you find some better documentation on this process but I did something like this:

  1. Installed the Cloudinary plugin for Wordpress
  2. Created/logged into my Cloudinary account & acquired API keys/secrets/magic sauce
  3. Configured the Cloudinary plugin for my account
  4. Exported & migrated all images/photos in my Wordpress blog over to Cloudinary using the above plugin associated with my API keys and such
How'd it go?

Very nicely. It was almost effortless and everything worked perfectly. I'm sure there are some edge case limitations but I didn't hit any. Fortunately, I didn't have a ton of graphical content to move over so it was also very fast. This was probably the easiest part of the entire migration for me.

Step 3: Migrate blog posts

So if you haven't noticed, the steps I took before to get to this point has ultimately been an effort to make it such that my blog posts are nothing but text-based content linking to outside third-party systems for any other functionality. Sure, there's formatted text but that's pretty much it. That was my goal since Ghost posts are pure and simple Markdown with a little bit of additional metadata.

Now that I was to this point, I was ready to move the posts over. This process looked something like this (I'm ignoring installation & configuration of Ghost, DNS, Cloudflare, etc.):

  1. Installed the Ghost plugin for Wordpress(If you haven't noticed, there's a plugin to Wordpress for almost everything, which is why it's so popular!)
  2. The plugin has an "Export to Ghost" feature that generates a JSON file for you to download. This is what you need.
  3. Once you have the JSON file download, go into your new Ghost deployment and upload it into Ghost.
  4. Go check it out and fix up anything that's wacky
How'd it go?

Well enough. I actually had to hack at the JSON file a little bit. For some reason, the way it was exporting users from Wordpress was preventing the file from importing into Ghost. A little bit of googling helped me find the problem and I was able to get it working. Unfortunately, I can't really elaborate on what I did. Other than this, it was about what you would expect: The import worked well for about 95% of things but still needed some manual touching up to be 100% good (which I've not yet fully done). The specific issues I had to manually touch up:

  • Hacking at the JSON file to get it to import successfully
  • Reformatting all of my formatted code in blog posts (I think this was mostly because years ago I got a little fancy with a code formatting plugin in Wordpress that used some non-standard syntax - you may not have this same problem). I think I still have some poorly-formatted code in some old posts to keep going through. I fixed some but not all of them.
  • The JSON import will create a new user and attribute all posts to that user - it won't be attributed to your current user in Ghost. I initially started to move them from one user to another until I decided not to and just let old posts stay assigned to the other user. So I just tweaked the two users' metadata such that it won't impact my site's readers in any meaningful way but if I ever need to know which posts are "old Wordpress posts" instead of Ghosts posts, this is one way I can do that. You know, like when I finally recover my old blog's comments.
  • Other than that, I think there might have been 1-2 random things to address. Nothing major.


Overall, it was a pretty easy process. I think I spent more time figuring out how to do things than I did actually doing things. The end product wasn't perfect but I think with more planning, and if I spent more time practicing the migration, I could have gotten it to perfect. But I'm very satisfied with the results and, so far, I'm enjoying the Ghost platform much more than I was with Wordpress. Between the ability to load it up with plugins and tweaks you can make and advanced settings to play with in addition to the burden of security, Wordpress was becoming a liability for me and it's nice no longer having that burden. Ghost is much simpler and takes far less of my time to do anything with it. I'd do it all over again if I had the choice though I'd probably have spent another hour or two trying to get my comments to come through seemlessly if I knew then what I know now.