· site building · 11 min read

How I Migrated from WordPress to Astro JS


In my earlier post, I explored the advantages of moving from WordPress to Astro. Today, I'll delve into the intricacies of how this significant shift occurred, from challenges encountered to the decisions made. If you're contemplating a similar transition, this behind-the-scenes account may provide valuable insights.

In my last post, I wrote about the benefits of migrating from WordPress to Astro. In it I spoke to why I made such a drastic change to this very site. It boiled down to performance, site control, and costs. All of which dramatically improved with this migration. Today, I will talk about HOW I made this change, the challenges I ran into, the decisions I had to make along the way, drawbacks, and what I might do differently in the future.

Decisions To Be Made

To start this off, I had to make some decisions regarding the best way for me to move forward with my website rebuild. What can I do to make it faster? What are my overall goals? How do I want the website to look? How do I want it to be structured? All of these things are important and drove each decision I made along the way.


The speed aspect was relatively easy to solve. In WordPress, as with most Content Management Systems (CMSes), to get the best performance you have to implement various caching schemes. Using the database, PHP itself, and Varnish. But this is complicated and prone to problems. With the switch to Astro we can use several different modes to generate our pages. This includes SSG (Static Site Generation), SSR (Server-Side Rendering), or a hybrid approach. In this case I stuck with the default SSG mode.

By using an SSG we already have all pages built and saved as static HTML files during the build and deploy process. This means that the server only has to serve static files on every page load. It doesn’t have to load caching from within PHP or cached elements from the database or even Varnish. There is no fresh generation of built pages on user visits. It is all just there already. This saves a ton of time.

I am able to use static mode because there is nothing running on my site that needs sessions at all. Its just content (for now). I am considering re-introducing post comments. But if I do I will use Disqus or another similar tool that doesn’t require anything to be saved to the website itself.

What all of this means is that, aside from some basic caching provided by CloudFlare (my host for all things with this site) there is no complex caching setup for this website. Its all pre-compiled static assets it is serving. I don’t have to configure framework-specific caching with a cache clearing scheme. I don’t have to work with PHP Opcache caching. I don’t have to setup and configure Varnish caching. None of that. I just deploy my site and away it runs.


I have already covered speed. I want my site to be faster. But I also want it to be more secure. You have trouble getting that with WordPress. It is the most popular CMS in the world. As such, it is the most targeted CMS in the world for security breaches. Just like Windows is/was the most targeted operating system because its widespread use. We regularly see articles about security breaches due to WordPress core or plugins, including security plugins.

Next, I would like to write articles in the markdown format. Its a widely available, highly flexible text format. Saving the contents to files also means I get full version control functionality from using git as my repository. Sure, WordPress and other CMSes do offered content versioning. But the features are often clunky and problematic to use.

I also wanted to greatly simply my efforts to add new features, new components, and complex content feeds and layouts to my website. In WordPress I can make a custom post type and save the data. But to query it and say show the latest content of a specific type (and have full control over the appearance of it) I would either have to write my own code for it (maybe creating some shortcodes for the task) or pay for a plugin with all the features and customizations I am looking for. With Astro I can just write my HTML and build in any loops to go through any data for display and sort however I want. Its easier and less intrusive then doing so on a WordPress site.

The next concern is the themes. I was honestly not that thrilled with both the paid and the free WordPress themes. Especially when it comes to tweaking the design, you consistently run into headaches. I was running a child theme on the latest ShiftCV WordPress theme and had all sorts of strange issues with widths, page sizing, and other small customizations. Theming in Astro is pretty easy and straighforward. No caches to clear. No more half-baked themes I have to work around and fight to get what I want.

I wanted to reduce costs. Astro solves this by eliminating my need for webservers I control and manage. Instead just host the site on CloudFlare’s dead-simple Pages system. I don’t have to worry about infrastructure at all. And its free to use.

Finally, customization. I want full and easy control of customizations to the website, something I did not get with WordPress. Astro made things a lot easier with a lot less battles to wage.


I wanted a clean site design. More like a marketing site, which is important because my website is a marketing tool for me. I also wanted to be able to easily achieve changes to the look including adding in new components and component structures. I decided to go with a Tailwind-based Astro theme called AstroWind. I chose Tailwind because it is relatively simple and clean, it limits the amount of CSS you transmit immensely, and I can easily copy good component ideas from other themes.

AstroWind ticks both of those boxes, marketing and using Tailwind. To prove my point, on my homepage I added new blog post component that I copied from another Tailwind-based Astro theme. Thus demonstrating how easy it is to modify and add new components.


I really wanted a more logical structure for my content and content paths. Originally I did it all willy nilly and now I want things to look professional, organized, and be well thought out. To decide on my structure I would need to decide what is most important to me. I knew I wanted to continue blogging. I wanted to essentially build my resume into the website. I also wanted to demonstrate my knowledge, contributions, and skills.

After some back and forth with myself I came up with the following structure diagram…

Navigation Diagram

The Migration

The migration itself came in three stages. First, the export from WordPress, which was easy enough, creates an XML file of all the content. Then the data for each page and post needs to be converted to markdown format, massaged, and reshaped to how it will be used in Astro. This includes pruning any content you no longer want. Finally, you need to copy the markdown files and their images to the correct folders in your Astro project.

Astro’s documentation has a page about WordPress and migrating to Astro from WordPress. This page leads you to the WordPress to Markdown conversion tool that you will need for this process. The rest of this article assumes you have created a basic Astro site locally and committed the files to a source code repository such as Git (the industry standard).

To help guide you on this and honestly I did this to make my life easier, I setup this site starting with the AstroWind theme/build of Astro. Using that projects structure, components, and cues for my own purposes, but modifying it along the way (even to this day I make tweaks to it).

Exporting from WordPress

Exporting your content from WordPress is pretty easy. Simply login to admin. Then go to Tools > Export. Once on the export page, select “All content” as what you want to export. Then click on the “Download Export File” button. This will create an XML file with all your content plus references to all image and file assets (which will be automatically downloaded during the conversion step).

You may also follow this guide on exporting from WordPress.

Converting to Markdown

This is where things get a bit more tricky and you might try a few different arguments and options in the conversion tool before you are happy with the results. For my part I had it convert all content. Then I pruned the content later.

We will start by using the WordPress Export to Markdown tool. This assumes you have the latest version of node installed. Take the following steps…

  1. Create a directory to work from, dedicated to this task.
    1. Open Terminal (or iTerm, Warp, or whatever your preferred terminal interface is).
    2. Go to your home/profile directory: cd ~
    3. Create your desired folder to work from (call it whatever you want): mkdir data-conversion-project
    4. Then go into that directory: cd data-conversion-project
  2. Copy the XML file from the exporting step into this new directory. You can use your terminal or your file management UI (such as Finder or Windows Explorer).
  3. Install the conversion tool: npx wordpress-export-to-markdown
    1. Alternatively you can download the files for the tool from the Github repo and run the following:
      1. npm install
      2. node index.js
  4. This will install the tool and its dependencies. Then it will ask you where the XML file is. Answer the questions and you will be ready to rock out.
  5. Now run the tool (these are the options I chose):
    1. npx wordpress-export-to-markdown --post-folders=true --year-folders=true --month-folders=true --prefix-date=true --include-other-types=true --output=my-content

This will create a folder and file structure containing not only the content of your site, but also download the file assets referenced by the content. We will use all of this later on.

Copying the Files and Massaging the Data

The first thing I had to do with this is change the structure a bit. I am taking advantage of Astro’s ability to use a folder structure for content as part of the URI. Thus, in Astro, under “/src/content/post”, I created a folder for each year of each post, then under that each month I have a post for, and finally for each day I have a post for.

Next, I copied the post markdown files to their respective folders. Since the export criteria I specified creates a folder for each post which contains the image and an index.md file, I had to rename the file to the post URI name (sans the prepended date) then copy this markdown file into the Astro structure.

Once all content is copied, I then copied all of the images to “/src/assets/images/posts” from their post directories. Next, I moved on to setting up the front matter data structure.

The references to the date and images in the Astro collection definition are different than what is output during the conversion. So I did a find and replace on all of the markdown files for the appropriate strings in my IDE (Webstorm). For “date” it was converted to “publishDate” with no quotation marks around the date itself. The “coverImage” field was change to “image”.

Then I had to fix references to the images. In Astro you can simply say tilde then assets (or ~/assets/) as the basis for accessing assets. Example, for this article the primary image is referenced like this: "~/assets/images/posts/wordpress-to-astro-migration.jpeg"

This tilde reference allows the Astro system to find and convert images to the preferred formats. AstroWind leverages some Astro tools to allow the automatic conversion to the webp format. Using this reference also allows file references to work both during local dev sessions that use npm run dev and the compiled output on your deployed site.

Finally, I added an excerpt to each article. Some I hand wrote. Some I just asked ChatGPT to generate one for me from the content I provided.

I repeated these steps for all content that I wanted to keep. After that, you can move on to customizing components and pages to your hearts content.


This process, while a bit tedious, was also very helpful and sped up the conversion. It is a bit part of how I was able to relaunch my site with only two weeks of work here and there. Using Astro has been a great experience for me and I hope to expand upon it in the future, including finding a way to have an external content management system be able to create page components on an Astro site. I believe this may have been accomplished already, I just need to research it and try it out.

Good luck!

Back to Blog