Skip to content

Migrating My Blog from WordPress to Astro

Published:  at  02:29 AM

Hello!

I used to run my personal blog on WordPress, but I recently migrated it to Astro, a JavaScript framework built around static site generation. This post explains why I made the move and how I approached it.

Table of Contents

Open Table of Contents

Before WordPress

I started my first personal blog as a university student. At the time, I saw three possible approaches:

  1. Use a hosted service such as Hatena Blog or note
  2. Run WordPress on a VPS
  3. Build everything myself

In terms of difficulty, they run roughly from easiest to hardest in that order. Hosted blogging services handle much of the SEO work and let you get started with almost no effort, which makes them an excellent choice when speed matters.

They do come with constraints, however. Customization is limited to the templates the service provides, and some services require a paid account before you can use your own domain instead of a subdomain. Those limitations may not matter to everyone, but as a software engineer I wanted more control, so I ruled out the first option.

I also did not like the idea that the future of my blog would depend entirely on the success or failure of someone else’s service.

My main purpose was to publish technical work, not to earn money from the blog. I wanted it to function as a personal portfolio, which is still true today. That made me reluctant to place the portfolio completely at the mercy of an external platform, so I aimed to operate it on infrastructure I controlled, even if that meant renting a server.

I also wanted more development experience, so I initially chose the third option and built a backend with Django and a frontend with Vue.js. Yes, plain SPA Vue rather than SSR with Nuxt. At the time I did not yet understand how much of a disadvantage an SPA could be for SEO.

I created a Markdown editor inside Django’s admin interface and stored the blog data in a relational database. Looking back, I was applying far more technology than a simple blog required. I learned a great deal from the project, but the goal of building an entire personal blog from scratch eventually fell apart.

I still wanted an unrestricted place to publish, so I moved to the second option for the time being: WordPress on a VPS.

The WordPress Era

WordPress is an excellent CMS. I used ConoHa VPS, where WordPress was already installed as soon as the server contract began. Being able to add features quickly through plugins also made for a very smooth initial experience.

As a professional programmer, though, I gradually became frustrated by small bugs and awkward behavior. Free versions of plugins for Google Analytics and SEO had restrictions, and many plugin interfaces were not particularly pleasant to use.

There were also few templates I truly liked. Even WordPress did not provide the degree of customization I wanted, and the VPS was expensive. Writing the blog started to feel like a burden, and I eventually stopped.

Moving Away from WordPress

After those false starts, I arrived at four requirements for the next version of my blog:

  1. Use a framework that supports SSR or SSG
  2. Deploy automatically whenever I push to GitHub
  3. Keep implementation simple
  4. Operate it for free

Using an SSR or SSG Framework

My experience with Vue.js taught me to serve rendered pages through SSR or SSG so that the site would be friendly to search engines.

The main candidates were Nuxt and Astro. Nuxt brings SSR to the Vue ecosystem, but it generally requires an application server for rendering. That server has an ongoing cost, and a blog does not need the complex runtime behavior of a typical web application.

That made Astro the stronger candidate.

Astro can use components from UI frameworks such as React and Vue while shipping pages with no client-side JavaScript by default. It offers TypeScript’s type safety, excellent performance, and strong SEO characteristics. Another small but valuable feature is the live preview: keep localhost:4321 open and the article reloads immediately while you write.

For my requirements, Astro was close to the ideal framework.

Deploying on Every GitHub Push

I wanted deployment to begin as soon as I pushed to GitHub, with the articles themselves under version control.

I also use a heavily customized Neovim setup both at work and at home. Writing in the same editor means I can use all my familiar key bindings and work quickly.

Once I had chosen Astro, the obvious hosting candidates were GitHub Pages and Cloudflare Pages. Both can deploy automatically when a target branch receives a push.

The important difference was private-repository support. Cloudflare Pages could deploy from a private repository, whereas GitHub Pages on a free personal account only supported public repositories at the time. Because I wanted the option to keep the blog repository private, Cloudflare Pages won.

Keeping the Implementation Simple

Astro provides a declarative, JSX-like way to build interfaces and can incorporate React or Vue components directly. It also supports MDX, so advanced components remain easy to add when Markdown alone is not enough.

I could have designed everything from scratch with help from GPT-4, but Astro already has many community-built themes. Some are simple and attractive, so I decided to launch by customizing AstroPaper.

Operating for Free

With Heroku’s free tier gone, Cloudflare Pages was the most compelling option. I was also able to obtain a domain through Onamae.com, so the site could be operated at essentially no cost.

Finished!

The finished blog uses:

  1. Astro
  2. A small number of React and Vue components
  3. TypeScript
  4. Cloudflare Pages

It satisfies all the requirements I originally set and should be straightforward to maintain. I especially like that MDX leaves room for charts or richer interface elements whenever an article needs them.

This blog will mainly contain small, frequent pieces of technical output from my day-to-day work and learning.

In other words: even a personal blog can be agile.