All work
Moving a WordPress site to Astro without losing rankings
Astro 6Content collectionsSvelte 5TypeScriptNetlify
40Legacy URLs redirected, generated rather than hand-written
34Articles migrated with their SEO metadata intact
0Server runtime: every route is a file on a CDN
- A long-running WordPress site carried years of articles and a set of per-location landing pages, all of which held rankings worth keeping.
- The page structure had accumulated to the point that a layout change meant editing each page individually.
- Article metadata lived in an SEO plugin's database fields, which do not survive an export unless something deliberately extracts them.
- Wrote migration scripts rather than migrating by hand: one to export the WordPress content and assets, another to convert posts to Markdown with their SEO fields preserved in frontmatter.
- Modelled content as a typed collection, so an article's shape is validated at build time instead of discovered when a page renders wrong.
- Generated the redirect map from the old permalink structure, so the mapping is reproducible and cannot drift from the content it describes.
- Consolidated the per-location landing pages into anchors on a single contact page, with the old URLs redirecting to their section.
- Every historical URL resolves, so nothing that had accumulated ranking returns a 404.
- The site has no PHP, no database and no plugin surface to maintain or patch.
- Content is Markdown in version control, so an article change is a reviewable diff.
Technical detail
- Redirects are generated by a script that runs as part of the build, reading the old slug set and emitting the redirect file. Hand-written redirect lists go stale the moment content moves; a generated one cannot.
- The collection schema includes the migrated SEO fields as a nested object, which means a post that lost its metadata in the export fails the build rather than quietly rendering without a description.
- Interactive pieces -- the header, an accordion, two carousels -- are Svelte islands; everything else ships as static HTML with no JavaScript at all.
- The deploy adapter is enabled only for builds, not for the dev server, because leaving it on made the dev server serve stale output from the previous build.
- Page copy lives in typed modules rather than in the templates, so the same content can be restructured without touching markup -- which is the problem that made the original site hard to change.