← BACK_TO_LOGS

Automated WordPress to Sanity CMS Migration: A Zero-Downtime Blueprint in Next.js

5 min readKANAT NAZAROV
Automated WordPress to Sanity CMS Migration: A Zero-Downtime Blueprint in Next.js
Case Study & Engineering Blueprint: How I built a custom Node.js automation pipeline to transfer 200+ blog articles, stream featured images into Sanity's CDN, and preserve 100% of organic search authority during a Next.js App Router migration. Preview the live build on our staging environment at new.tribecadentalstudio.com!

The Challenge: Legacy Monolith vs. Modern Headless Architecture

When rebuilding the digital platform for Tribeca Dental Studio—a luxury multi-specialty dental practice in Lower Manhattan—we transitioned away from a legacy PHP/WordPress setup. Our goals were to leverage the performance of Next.js App Router and the editorial flexibility of Sanity CMS.

However, the practice had accumulated over 200 published blog articles, complete with featured images, meta tags, custom permalinks, and embedded HTML. Manually copy-pasting this content would have taken over 40 hours of manual labor and introduced human error.

To execute the migration efficiently, I engineered an automated Node.js script (import-wp.mjs). This pipeline fetched posts directly from the WordPress REST API (/wp-json/wp/v2/posts?_embed), sanitized legacy HTML strings, streamed featured media directly into Sanity's Asset CDN, and batch-created Sanity Studio documents—all in under two minutes.

Legacy Monolith vs. Modern Headless Architecture

Architectural Considerations

  1. Asset Pipeline Streaming: WordPress stores media links relative to local server paths (/wp-content/uploads/). The script needed to fetch these remote images, convert them into binary buffers, and upload them directly into Sanity's Asset Pipeline.
  2. Entity & String Sanitization: The WordPress REST API returns titles and excerpts filled with HTML entity codes (e.g., ’, &). These required decoding and cleaning before document insertion.
  3. SEO & Permastruct Preservation: Legacy blog posts lived on root-level paths (e.g., /crown-sensitive-to-cold-and-hot/). The new architecture needed dynamic routing or automated 301 redirects to ensure Google rankings remained untouched.

Terminal Commands & Execution

The entire migration process was executed locally via Node.js using terminal commands.

1. Set the Sanity Write Token

Configure your Sanity API Token as an environment variable (generated in the Sanity Dashboard under Settings $\rightarrow$ API $\rightarrow$ Tokens with Editor/Admin rights):

typescript

2. Execute the Migration Pipeline

Run the script directly from the root directory of your Next.js project:

typescript

3. Real-Time Terminal Output

Upon running the script, interactive terminal logs output real-time progress as each record is fetched, processed, and created in Sanity:

typescript

The Migration Script (import-wp.mjs)

Here is the Node.js automation script used to execute the dataset migration:

javascript

Results & Staging Preview

  • Automation Efficiency: Transferred 200+ blog articles, meta tags, and media assets into Sanity's CDN in under 2 minutes.
  • Zero SEO Loss: Kept legacy search authority intact while enabling Next.js static rendering for lightning-fast Core Web Vitals.
  • Live Staging Build: Check out the migrated dataset and brand-new editorial layout live on our staging domain at new.tribecadentalstudio.com!

Leave a comment

Kanat Nazarov

Kanat Nazarov

Systems & Full-Stack Engineer
Kanat Nazarov is a product-minded Full-Stack Engineer. He is the co-founder of GetFusionChat, an enterprise-grade multi-tenant communication SaaS platform. Beyond architecting low-latency infrastructures and advanced AI systems, Kanat is a dedicated student of peak performance—optimizing his lifestyle through rigorous fitness, precise nutrition, and creative production in music. He operates on the core philosophy that breakthrough technical results stem from a high-functioning, deeply disciplined life.