Jussi Roine
Home About Me Contact Categories
Home About Me Contact Categories

Migrating my content to Astro, and I learned a few lessons

May 14, 2026 Jussi Roine General
Reflecting back on the journey to move from Wordpress to Ghost to finally now Astro for my all of my content.

So, back in 2025 I figured maybe time’s up for me in writing blogs. With ChatGPT essentially enabling everyone and their pets to produce noisy and poor content, I saw my interest vane at the same trajectory - even if I write all of my content like a true artisan; manually. I feel there’s value in the content that I produce, so I took a short break from thinking about what to write - and didn’t really write anything in public. But here we are.

Wait, why?

You might recall I initially built my blog on top of Wordpress. That ran pretty great for about a decade. Tinkering with PHP, plugins, security issues and the awful themes and templates eventually drove me to look for alternatives. A few friends had migrated to Ghost. The initial promise was awesome: write content in Markdown! Just focus on content, click publish and forget the rest. So, I migrated my then hundreds of articles to Ghost. It was tedious, as exporting from Wordpress wasn’t exactly something you do with surgical precision, but more of a trial-and-error type of exercise. Once I had my content floated to Ghost, I felt I was at home. Just write, and publish! And I sure did that over the years. But the problem with Ghost is two-fold for me: cost, and inflexibility.

I wanted to tweak the theme just a bit, and that required a premium tier subscription that ran at $60/month. That’s about $700 annually! For a blog. Yeah, no. So, I once more collected my content, and spent a few evenings figuring out where to move on. Wordpress was out of the question. I had excess hardware capacity at home, so it was pretty neat to build a separate network, with separate hardware, to host my tiny blog with Ghost, in a bunch of Docker containers. So awesome! Almost like a private cloud, without the upside of actually having your own cloud platform. Eventually, that turned out pretty well. It was rock solid, fast, and just.. works. But I couldn’t shake the feeling of not being able to tweak the visuals at all - and working with handlebar-based files is like trying to do nordic curls without yelling at yourself. So, once more I started seeking for an alternative.

Why not $X or $Y?

I briefly contemplated moving to a hosted platform, such as Substack or Medium. But I really want to own my content - not hand it of to someone else, who might change the rules of the game when it’s not convenient for me. Again, back to the artisan mindset: why not build it yourself?

Hello, Astro and Markdown

My friend Elio Struyf told me about Astro what seems like years ago. It might have been last week, but time compresses somehow, when you work remotely and just try to get stuff tackled from the endless backlog. I am, by no means, an expert with Astro now. I know just enough to be dangerous.

In essence, Astro provides a nice, mostly HTML-based setup, that allows you to produce content with Markdown. It’s a static site generator, thus anything I produce, eventually gets output to a collection of .html files, served with Node.js. Very neat, very fast, and pretty lightweight to operate on the backend.

The setup

My setup is pretty simple - and far from done. The intention isn’t to build the greatest agentic workflow to “just do it”. Instead, I want to dissect the process into pieces that I can understand - and then over time automate it to a degree I think I can control and manage, even if life is busy. My Astro files sit in a private GitHub repo: all UI and UX elements, core image files (profile pic, favicon, and that’s about it), and all content and structure. Each blog article is a separate Markdown file, with minimal FrontMatter-based metadata like publish date, hero image URL, and such. I’ve got a virtual workstation I can reach anywhere, and that’s mostly where I build the site, if I tweak something. Visual Studio Code, GitHub Copilot, Astro extension and that’s mostly it.

Once done, I test locally by running npm run dev. It builds the solution, and allows me to check stuff looks decent via http://localhost:123. Eventually, when it’s time to publish to production, I push directly to an Azure Web App. Hold up - why not use a fancy, automatic CI/CD pipeline, you ask? Because there isn’t a need (yet). I don’t do daily updates, and I like to be on top of the workflow for now. I’ll eventually deploy a GitHub Actions-based workflow that will push from the Git repo Azure directly. Artisan mindset strikes again. What about images? My previous content includes about 5GB of static image files - mostly jpg and png, with numerous dimensions. I considered (briefly) the option of pushing all of those to the repo, but GitHub SLA already being less than 90%, I figured it would tank totally. You can thank me later. So I did the obvious thing - pushed all static images to a dedicated Azure Storage account. It sits neatly there, and NEVER needs to do anything else. This way, it’s outside the actual publish process, although I do need to update any future images semi-manually right now. I’ll work on that later.

Challenges

No problems with this approach but plenty of challenges.

First, content migration: all content, when you export from Ghost, is bundled into a single .json file. That’s a +40K line file, with a lot of data. I worked with Anthropic’s Opus 4.7 to parse all articles to individual .html files first, and then I parsed them to Markdown. It’s a one-time process, and the parser is a somewhat esoteric Node.js-based thingamajinga. I got a lot of issues down the road - tags and categories were all over. Just to have fun, I wired up my local Ollama-rig with Gemma4:e4b to analyze all tags and categories, and to condendse them into 25 main ones. It was surprisingly efficient, categorization took about 3 minutes. Armed now with confidence and caffeine, I started scanning through the articles programmatically. Chaotic HTML still somewhere? Fixed. Absolute URLs to images that need changing? Changed. Missing metadata? Added. Overall, it took about two evening sessions to get from ghost.json to +350 cleaned Markdown files. Not bad.

Once I started building the actual solution - and learning about Astro at the same time - I realized I’d either have to stop the work, and actually study Astro, or just vibe-code, ahem, agentic engineer my way through the issues. I chose the latter, of course, as it always seems like the most obvious and efficient solution. I purchased an affordable theme that pleased my eye. Some tweaks here and there, but I didn’t have to spend a lot of time working on the outcome. Once content was fixed, it was time to fret the small stuff. How to exclude images from being pushed to GitHub? How to produce robots.txt and sitemap.xml? For each question, I found a thoughtful solution - that again took a bit of time to understand.

Here we are

So, here we are. I’m utilizing DNS from Cloudflare, and thankfully they produce decent web analytics for free on top it. AI crawling is enabled, and allowed - and I’m enjoying seeing about 2,000-3,000 requests per day from your favorite AI services crunching and cannibalizing my content. I really don’t mind. I have grand plans, that I hope to eventually build: full CI/CD pipeline for publishing. Azure FrontDoor and CDN capabilities. Geo-redundancy with automatic ealing. Proper AppInsights, and alerting. But the time for these comes later, when I have the urge to scratch those itches.

Jussi Roine

Jussi Roine

Microsoft MVP and consultancy founder with 30+ years of experience, passionate about Microsoft security, AI governance, and sharing what I learn along the way.

Categories

  • Productivity 45
  • Azure 45
  • General 118
  • Networking 15
  • Security 34
  • Cloud 20
  • Wellness 19
  • Automation 12
  • AI 12
  • Data 4
  • Career 29
  • Architecture 4
  • Development 16
  • Leadership 3
  • Strategy 6
  • Integration 8
  • Identity 3

Tags

Productivity Cloud Computing Professional Development Azure Automation Remote Work Microsoft 365 Security AI SharePoint PowerShell Software Development Microsoft Teams Power Platform Networking Web Development Azure OpenAI Identity Docker DevOps IoT Power Automate Raspberry Pi Azure Functions .NET
Jussi Roine

Microsoft MVP and consultancy founder with 30+ years of experience, passionate about Microsoft security, AI governance, and sharing what I learn along the way.

© 2026 Jussi Roine. All rights reserved.