Skip to content
tutorial

How to Migrate Your WordPress Site to Astro Step by Step

March 08, 2026 Updated September 17, 2026 By Alex Crabinsky
How to Migrate Your WordPress Site to Astro Step by Step

A WordPress to Astro migration is two projects wearing one name. The first is moving content, which is mostly mechanical. The second is keeping the rankings that content earned, which is where sites get hurt. This guide does both, in the order that protects the second.

There is no magic converter at the end of it. The exporters below do the bulk work, an AI editor is useful for the frontmatter clean-up, and the rest is redirects and checking.

Before You Touch Anything

Inventory the site. You cannot redirect a URL you forgot existed.

  1. Every URL. Crawl the site with Screaming Frog or pull the sitemap at /sitemap_index.xml (Yoast) or /wp-sitemap.xml (core)
  2. Content types. Pages, posts, custom post types, categories, tags, authors
  3. Features. Contact forms, search, comments, e-commerce, gated content
  4. Plugins. List every active one and what it does. Most either have a static equivalent or were never needed
  5. Traffic. From Search Console or Analytics, the top 50 pages by organic clicks. These are the pages a broken redirect will cost you real money on

Grade the site before you start. Run it through the free Website Grader and keep the report. The point of the migration is a better second report, and you want the first one on record.

Size the job honestly. A twenty-page business site is a day or two of work. A two-hundred-post blog with custom post types is closer to a couple of weeks once redirect testing is included.

Step 1: Export the Content

Posts and Pages to Markdown

WordPress keeps content in a database; Astro wants Markdown files with frontmatter.

Option A: the XML export plus a converter. In WordPress go to Tools, then Export, and download all content as XML. Then:

npx wordpress-export-to-markdown --input=export.xml --output=src/content/blog

It asks a few questions (folder layout, date prefixes, whether to download images) and writes one Markdown file per post with the title, date, categories and tags in frontmatter. Expect to fix formatting by hand where page builders and complex blocks were involved.

Option B: an exporter plugin. The Jekyll Exporter plugin writes posts and pages as Markdown with YAML frontmatter straight from the admin. The output is aimed at Jekyll, so a few frontmatter keys will need renaming, but it is often cleaner than the XML route for plain posts.

Images

Pull wp-content/uploads/ and flatten it under public/images/ in the Astro project, then update the paths in your Markdown:

rsync -avz user@server:/var/www/html/wp-content/uploads/ ./public/images/uploads/

Images that should get Astro’s optimization (hero and post images) belong in src/assets/ instead, imported from frontmatter so the <Image> component can resize and convert them. Everything in public/ is served as-is.

Step 2: Set Up the Destination

Start from a template that already has the pages a business site needs, so the migration is content in, not site out. The free Amrify Starter is a complete site (home, services, about, blog with tags, contact, thank-you, privacy, 404) with structured data, sitemap, RSS, llms.txt and deploy configs for Netlify, Vercel and Cloudflare Pages. Amrify Pro adds trade templates and the lead engine on the same base.

# the public Starter repo opens with the product launch
git clone https://github.com/amrify/starter.git my-sites
cd my-sites && pnpm install

Site Configuration

In the Starter a site is one validated site.json plus a folder of Markdown. Set the domain, business name, logo and colors there; the layouts derive canonicals, the sitemap, JSON-LD and the social cards from it.

Content Collections

Define schemas that match what you exported. The Content Collections guide goes deeper; the shape is:

// src/content.config.ts
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "astro/zod";

const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    description: z.string(),
    date: z.coerce.date(),
    categories: z.array(z.string()).default([]),
    image: z.string().optional(),
    draft: z.boolean().default(false),
  }),
});

Run the build after every schema change. Each failure names the file and field, which turns the clean-up into a checklist.

Step 3: Move the Content In

Posts

Copy the exported Markdown into src/content/blog/ and make the frontmatter match the schema:

---
title: "Your Post Title"
description: "A one-sentence summary for search results"
date: 2025-06-15
categories: ["tutorial"]
image: "/images/uploads/post-image.jpg"
---

The usual clean-up:

  • Strip WordPress shortcodes ([gallery], [contact-form-7 ...])
  • Rewrite image paths from /wp-content/uploads/ to /images/uploads/
  • Convert leftover HTML blocks to Markdown
  • Write descriptions; WordPress rarely exports them, and Yoast keeps its own in a separate table

This is the step an AI editor earns its keep on. With the schema in the repo and a CLAUDE.md describing it, you can hand Claude Code or Cursor fifty posts and ask for the frontmatter fixed to spec, then review the diff.

Pages

About, Contact and Privacy go into the Starter’s page collections. Pages that were built from sections (hero, features, testimonials) map to frontmatter blocks the layouts already render.

Categories and Tags

If WordPress had thirty categories and five carried traffic, keep five. A handful of well-populated categories beats a long tail of thin archive pages, which you will otherwise have to redirect or noindex anyway.

Step 4: Protect the Rankings

This is the half of the project that decides whether the migration was a success.

Map Every Old URL

Build a complete table from the inventory in the first section:

WordPress URL                    ->  Astro URL
/2024/06/15/my-post-title/       ->  /blog/my-post-title/
/category/tutorials/             ->  /blog/
/about-us/                       ->  /about/
/services/web-design/            ->  /services/web-design/
/feed/                           ->  /rss.xml

Date-based post URLs are the most common change. Keeping the old structure is allowed, but flat /blog/slug/ URLs are easier to maintain, and a redirect handles the difference.

Add the 301s

For Netlify and Cloudflare Pages, a public/_redirects file:

/2024/06/15/my-post-title/   /blog/my-post-title/   301
/category/tutorials/          /blog/                  301
/about-us/                    /about/                 301
/feed/                        /rss.xml                301

For Vercel, vercel.json:

{
  "redirects": [
    { "source": "/2024/06/15/my-post-title/", "destination": "/blog/my-post-title/", "statusCode": 301 }
  ]
}

Astro’s own redirects config option also works, but on a static build it emits meta-refresh pages rather than real 301 responses, so use the host’s redirect layer for anything Google needs to follow.

Every indexed URL that returns a 404 after launch throws away whatever authority it had. The 301 carries it to the new address.

Keep the Meta Data

For each migrated page, confirm the title is the same or better, the description exists, the Open Graph image resolves, and the canonical points at the new URL rather than the old domain.

Resubmit

After launch, submit the new sitemap in Search Console and watch the Pages report for 404s from URLs you missed in the map.

Step 5: Replace the Plugins

Contact Forms

Contact Form 7 and Gravity Forms need PHP. On a static site the form posts somewhere else. The Starter’s form works on static hosting out of the box, posting to Formspree, Basin or an endpoint of your own, with a honeypot field for bots. Pro replaces that with its lead engine: a serverless API that stores every lead, emails it, and pushes it to Telegram or SMS, with spam filtering in front.

WordPress searched its database. For a static site, Pagefind indexes the built HTML at build time and searches it in the browser, which covers most business sites. Larger content libraries can use a hosted service such as Algolia.

Comments

Giscus (backed by GitHub Discussions) suits developer audiences; Disqus is the general-purpose option. Most business sites remove comments during the move and never miss them.

RSS

WordPress served the feed at /feed/. The Starter already generates /rss.xml; on a fresh Astro project, add @astrojs/rss and an rss.xml.ts route. Either way, redirect /feed/ so existing subscribers keep receiving posts.

Step 6: Test on a Staging URL

Deploy to a preview URL first and check:

  1. The top 20 pages by traffic render correctly
  2. Every row in the redirect table returns a 301 to the right place (a shell loop with curl -I does this in a minute)
  3. Titles, descriptions and canonicals are right on a sample of pages
  4. Structured data validates in Google’s Rich Results Test
  5. Lighthouse scores meet the bar you set; the Starter’s CI gate expects 100 in all four categories
  6. The form delivers a test submission
  7. No broken images from the path rewrite

Step 7: Go Live

  1. Point DNS at the new host
  2. Confirm HTTPS and the www or apex redirect
  3. Submit the sitemap in Search Console
  4. Check Search Console daily for the first two weeks
  5. Watch for crawl errors, indexing drops and ranking changes on the top 50 pages

A short dip while Google processes the redirects is normal. With a complete redirect map it is small and it recovers; without one it is neither.

The Mistakes That Cost Traffic

  1. Missing redirects. The number one cause of post-migration losses, every time
  2. “Small” URL changes without 301s. A trailing slash is a different URL to Google
  3. Lost descriptions. Yoast stores them outside the post content and the export does not include them
  4. Stale internal links. Old-structure links inside migrated posts create redirect chains; rewrite them
  5. A dead /feed/. Subscribers silently stop receiving posts
  6. Nobody watching. Search Console for two weeks, or you learn about the 404s from the traffic graph

What Amrify Gives You Here

The destination, not a converter. The Starter is the finished site the content lands in, with the SEO plumbing (canonicals, sitemap, JSON-LD, RSS, llms.txt) already wired. Pro’s new-site scaffolder creates that destination in one command inside a multi-site repo, which matters when you are moving a portfolio of client sites one at a time. The export and clean-up are the steps above; the four bundled Claude Code skills in Pro can take the frontmatter and content work off your hands.

For the case for moving at all, read Astro vs WordPress for agencies. For running the migrated sites afterwards, read one codebase, a whole fleet of sites.


Keep a before-and-after you can show the client. Grade the WordPress site with the free Website Grader today, then add the new domain to the free Website Monitor once it is live: it keeps the last ten Lighthouse results per site, so the old score and the new one sit on the same chart. Both are free; the monitor needs a free account and no card.

Tags: tutorial
Share:

Ready to build your next agency site?

Start with the free tools today and the free Starter at launch, or own Amrify Pro - every niche template in one purchase.

Get Amrify Docs