Home
Blog

WordPress to Astro Migration: The Complete Guide (Keep Your SEO)

Last updated:
August 26, 2026

Migrating WordPress to Astro is mostly a content and SEO problem, not a coding problem. The build is the easy half. The half that decides whether your rankings survive is how you export the content, map the URLs, and cut over. This guide covers the whole process the way I run it for clients, with the scripts included.

If you would rather hand it off, my WordPress to Astro migration service does everything below for a fixed quote from $1,250. If you are building it yourself, read on.

Short answer: Inventory the site, pick MDX or Sanity for content, export everything through the WordPress REST API with a script, rebuild templates as Astro components, keep every permalink identical (301 anything that must change), carry over your Yoast titles and descriptions, then cut over and watch Search Console for 30 days. Done in that order, rankings hold. Skipped steps are where migrations lose 40 to 60 percent of their traffic.

Should you migrate at all?

Astro fits content-led sites: marketing pages, blogs, docs, portfolios. It does not fit sites where plugins are the product. Stay on WordPress if you run a membership site, an LMS, or a deeply customized WooCommerce store, because rebuilding application behavior costs far more than hosting savings return. If your site is “pages plus a blog plus a contact form,” you are the ideal case, and the rest of this guide is for you.

Step 1: Inventory what you actually have

Before touching code, list four things:

  • Content: pages, posts, custom post types, and which ACF fields each uses.
  • Plugins: every active plugin and the job it does. Most WordPress sites run 20+ plugins where five do something a static site needs.
  • URLs: your permalink structure (/blog/post-name/, /2024/03/post-name/, category archives), pulled from a crawl or your sitemap.
  • Rankings: your top pages and queries from Search Console. These are the pages where URL parity matters most.

Step 2: Choose where content lives: MDX or Sanity

  • MDX puts content in markdown files inside the repo. Free forever, version-controlled, perfect when developers or technical founders edit the site.
  • Sanity gives editors a visual studio. Pick it when marketers edit weekly and would rather never see a code repo. The free tier covers most marketing sites.

The rule I use: if the people editing content can live in markdown, MDX. Otherwise Sanity. Both migrate the same way; only the import target changes.

Step 3: Export your content through the REST API

Every WordPress site exposes its content at /wp-json/wp/v2/. That makes the export a small script instead of a plugin hunt. Here is the core of the one I use, trimmed to the essentials:

// export-posts.mjs (Node 20+): WordPress posts -> markdown files
import fs from 'node:fs';

const SITE = 'https://your-site.com';
const posts = [];
for (let page = 1; ; page++) {
  const res = await fetch(
    `${SITE}/wp-json/wp/v2/posts?per_page=100&page=${page}&_embed`
  );
  if (!res.ok) break;
  const batch = await res.json();
  posts.push(...batch);
  if (batch.length < 100) break;
}

fs.mkdirSync('src/content/blog', { recursive: true });
for (const post of posts) {
  const description = post.excerpt.rendered.replace(/<[^>]+>/g, '').trim();
  const front = [
    '---',
    `title: ${JSON.stringify(post.title.rendered)}`,
    `pubDate: ${post.date.slice(0, 10)}`,
    `description: ${JSON.stringify(description)}`,
    '---',
  ].join('\n');
  fs.writeFileSync(
    `src/content/blog/${post.slug}.md`,
    `${front}\n\n${post.content.rendered}\n`
  );
}
console.log(`Exported ${posts.length} posts`);

Notes from running this on real sites:

  • content.rendered is HTML. Markdown files render embedded HTML fine, but if you want clean markdown, pipe it through the turndown package before writing.
  • Repeat the loop for pages and for each custom post type (they appear at /wp-json/wp/v2/your-cpt-slug once the type has show_in_rest enabled).
  • ACF fields show up in the response when the “show in REST” option is on, and land in frontmatter with a few extra lines in the script.
  • The classic WXR/XML export works as a fallback, but the REST route gives you structured data you control, which is why I default to it.

Step 4: Bring the media library

Post HTML references images on your old domain. Two options: download the wp-content/uploads folder over SFTP and drop it into Astro’s public/ with the same paths (fastest, zero HTML edits), or fetch each image URL found in the exported content and rewrite references as you go. For most migrations the uploads-folder copy wins, and image optimization can come later through Astro’s image tooling.

Step 5: Rebuild templates as Astro components

Your theme becomes a handful of components: a base layout, a blog listing, a post layout, and your page sections. Astro’s content collections replace the WordPress loop, and the things themes bury in functions.php become plain code:

  • Shortcodes and embeds become Astro components you can see and edit.
  • Forms move to hosted handling (Netlify Forms or similar) instead of a form plugin.
  • SEO plugin output (titles, metas, Open Graph, schema) becomes a head component that reads frontmatter, which is exactly how this site works.

Match the current design first. A migration that is also a redesign is two projects wearing one deadline.

Step 6: Preserve your SEO at cutover

This is the step that decides everything:

  1. URL parity. Build Astro routes to match your permalinks exactly, including trailing slashes and date-based patterns.
  2. 301 the exceptions. Anything that must change gets a redirect. On Netlify that is a _redirects file:
# _redirects: only URLs that changed
/2024/03/old-post/    /blog/old-post/    301
/category/news/       /blog/             301
  1. Carry metadata over. Yoast and Rank Math expose titles and descriptions in the REST response (or via their own export). Apply them to the new pages before improving anything. Parity first, upgrades after.
  2. Rebuild schema in code. Article, breadcrumb, and organization markup belong in your layouts now, not in a plugin.
  3. Sitemap and Search Console. Generate the sitemap with Astro’s integration, submit it, and watch coverage daily for 30 days. Small dips in week one recover; missing redirects do not.

Once the classic SEO layer is safe, the migration is also the perfect moment to add the AI-citation layer: schema, answer-first structure, and llms.txt. My technical AEO guide covers that checklist.

The launch checklist

  • Every old URL returns 200 (same page) or 301 (mapped redirect), never 404
  • Titles and meta descriptions match or improve the old pages
  • Sitemap submitted, robots.txt reviewed
  • Forms tested end to end
  • Analytics wired before, not after, cutover
  • Lighthouse 95+ verified on key templates
  • Old site kept on standby for rollback during week one

What this costs if you hire it out

Doing this yourself is 20 to 60 hours depending on content volume and how exotic the theme is. Hiring me is a fixed quote from $1,250, which includes the export, rebuild, redirect map, metadata parity, and 30 days of post-launch monitoring, with the honest option to tell you WordPress is still the right home for your site. That recommendation and the full process live on the WordPress to Astro migration service page.

FAQ

How long does a DIY migration take?

A weekend for a small blog with a simple theme if you are comfortable in JavaScript. Two to four weeks of evenings for a marketing site with custom post types, forms, and a design worth preserving. The export script is the fast part; template rebuilding and redirect QA are where the hours go.

Can I keep my comments?

WordPress-native comments do not carry into a static site by themselves. Options: retire them (most marketing blogs quietly should), embed a hosted system like Giscus backed by GitHub discussions, or keep the old threads as static HTML under each post. Decide before cutover so nothing silently disappears.

What about WooCommerce?

Do not migrate a working store to a static site. Either stay on WordPress, or split the setup: marketing site and blog on Astro, store remaining on its own subdomain. The split keeps the content half fast and cheap without rebuilding checkout.

Will my rankings drop?

If URL parity, redirects, and metadata parity are done as described above, expect small fluctuations that settle within two to four weeks. Migrations lose traffic when URLs change silently, redirects are skipped, or metadata is rewritten wholesale on day one. The checklist exists because every item on it is a lesson someone learned the expensive way.

Table of Contents

Want it done for you, rankings intact?

I migrate WordPress sites to Astro with every URL preserved, plugins retired, and Search Console monitored for 30 days after launch. From $1,250 fixed after a free audit.