WordPress to Keystone.js Migration Guide
WordPress to Keystone.js Migration Guide

Key Takeaways
- Keystone.js replaces WordPress's coupled theme model with a code-first, TypeScript-native headless CMS that serves content over an auto-generated GraphQL API.
- Going headless decouples authoring from rendering, improving performance, security, and developer experience while enabling one content source to feed many clients.
- Content modeling maps WordPress posts, taxonomies, and ACF fields onto typed Keystone lists with relationships, access control, and a structured document field for rich text.
- The migration is a data pipeline plus a front-end rebuild: export via the WordPress REST API, transform HTML into Keystone's document JSON, migrate media, and bulk-load through GraphQL.
- Preserving SEO requires identical URLs, 301 redirect mapping, migrated metadata and structured data, and a staged cutover validated against a crawl-based checklist.
WordPress still runs a large share of the web, but for teams building modern, API-driven products it increasingly feels like a ceiling rather than a foundation. Themes, plugins, and PHP templating tie your content to a single presentation layer, and every performance or security concern is inherited from a monolith you did not design. Keystone.js takes the opposite approach: it is a code-first, TypeScript-native headless CMS that gives you a fully typed schema, an auto-generated GraphQL API, and a polished Admin UI, while leaving the front end entirely to you.
Migrating from WordPress to Keystone.js is not a plugin swap. It is an architectural shift from a coupled template engine to a decoupled content platform that serves structured data to any client you choose to build. This guide walks through why the move makes sense, what actually changes under the hood, how to model your content and stand up the API, the step-by-step migration itself, and how to protect the search rankings you have spent years earning.
Why Go Headless From WordPress
The core argument for going headless is separation of concerns. WordPress bundles authoring, storage, business logic, and rendering into one process. That coupling is convenient at first and expensive later: a theme update can break your API, a plugin can open a security hole, and scaling the front end means scaling the admin too. Keystone.js keeps content in a schema you own and exposes it over an API, so your Next.js, Remix, or mobile client consumes data without ever touching the CMS runtime.
- Performance: A static or server-rendered front end pulling from GraphQL avoids WordPress's per-request PHP and plugin overhead, so you ship pre-rendered HTML and cache aggressively at the edge.
- Security: The public site never exposes an admin login or a plugin surface. Keystone's Admin UI can live behind a private network or auth wall entirely separate from your marketing site.
- Developer experience: Content types are defined in TypeScript, versioned in Git, and code-reviewed like any other part of your stack, rather than clicked together in a dashboard.
- Omnichannel reuse: The same content feeds a website, an app, and third-party integrations from one API instead of being trapped in theme markup.
If you are still weighing the tradeoffs, our breakdown of headless CMS versus traditional CMS maps out which project profiles actually benefit and which are better left on WordPress.
The Decoupled Architecture And What Changes
In a traditional WordPress build, a request hits Apache or Nginx, PHP renders a theme template, and HTML comes back in one round trip. In a Keystone.js architecture, responsibilities split into three layers. Keystone runs as a Node.js content server backed by a relational database (PostgreSQL or SQLite via Prisma). It generates a GraphQL API and an Admin UI automatically from your schema. Your front end is a separate application, typically Next.js, that queries that API at build time or on demand and owns all routing, SEO, and presentation.
The practical consequences are worth internalizing before you write any code:
- Themes and PHP templates disappear entirely; markup now lives in React components in your front-end repo.
- The WordPress loop and shortcodes are replaced by GraphQL queries and typed content fields.
- Rich text is stored as structured JSON through Keystone's document field, not as a blob of HTML, which makes content portable and render-target agnostic.
- Media is handled through Keystone's image and file fields with a storage adapter (local disk or S3-compatible object storage) rather than the WordPress uploads directory.
- Deployment becomes two pipelines: one for the Keystone server and database, one for the front end, often on different hosts.
This is genuinely a rebuild of the delivery layer, which is why teams frequently pair it with a broader custom website and CRM development effort rather than treating it as an isolated CMS switch.
Content Modeling And API Setup
Keystone's schema is the heart of the system, and modeling it well is where most of the value is captured. You define lists (the Keystone term for content types) in a keystone.ts config using the list() and fields helpers. A blog post that was a WordPress post plus a pile of custom fields and taxonomies becomes an explicit, typed structure.
- Map WordPress posts and pages to Keystone lists with
text,document,timestamp, andselectfields for status. - Convert categories and tags into related lists joined with
relationshipfields, giving you referential integrity that WordPress taxonomies never enforced. - Replace ACF custom fields with first-class schema fields, so what was loosely typed metadata becomes validated, queryable data.
- Model authors as their own list with a relationship back to posts, and reuse it for the access-control layer.
Once the schema compiles, Keystone auto-generates a GraphQL endpoint (default /api/graphql) with full CRUD queries and mutations, plus filtering, ordering, and pagination for free. You configure access control declaratively per list and per operation, and add hooks for derived fields such as auto-generating slugs or reading time. Seed your front end by querying this API in getStaticProps or a server component, and use the generated types to keep queries type-safe end to end.
The Step-By-Step Migration
With the target architecture defined, the migration itself follows a repeatable sequence. Treat it as a data pipeline plus a front-end rebuild running in parallel.
- Export the WordPress data: Pull content through the WordPress REST API (
/wp-json/wp/v2/posts,/pages,/media) or a WXR/SQL dump. The REST API is usually cleaner because it returns JSON with rendered and raw fields. - Transform the content: Write a Node script that maps each WordPress record to your Keystone list shape. The hardest part is converting post HTML into Keystone's document JSON; use a parser like
rehypeto walk the HTML tree and emit the structured document format, preserving headings, links, and embeds. - Migrate media: Download every attachment, re-upload it through Keystone's image/file storage adapter, and rewrite URLs in the content body to point at the new asset locations.
- Load into Keystone: Run the transformed records through Keystone's GraphQL
createItemsmutations or the Prisma layer directly for bulk inserts, ideally in an idempotent script you can re-run safely. - Rebuild the front end: Implement React components that render the document field and recreate every template WordPress previously served, matching URL structures exactly.
- Verify and reconcile: Diff the live WordPress sitemap against your new routes to confirm nothing was dropped before cutover.
Because the failure modes here are subtle, a formal cutover plan matters. A managed website migration service handles the staging environment, the parity checks, and the DNS switch so you are not discovering broken URLs in production.
SEO Preservation During The Move
The fastest way to sabotage a migration is to let URLs and metadata drift. WordPress permalinks, Yoast titles, and schema markup all carry ranking signals, and Keystone gives you a blank canvas, which means preservation is entirely your responsibility.
- Preserve URL structure: Store the original WordPress slug on each Keystone item and configure your front-end router to serve identical paths. Where paths must change, build a comprehensive redirect table rather than accepting 404s.
- Map redirects properly: Every changed URL needs a 301, not a 302, so link equity transfers. Our 301 redirect map guide shows how to build and test that table before launch.
- Reproduce metadata: Migrate SEO titles, meta descriptions, canonical tags, and Open Graph fields as real schema fields in Keystone, then render them in your front-end
headper page. - Regenerate structured data: Recreate JSON-LD for articles, breadcrumbs, and organization data in your React components so rich results survive.
- Rebuild sitemaps and robots: Generate an XML sitemap from your GraphQL data and resubmit it in Search Console the day you cut over.
Run the whole process against a structured checklist rather than from memory. Following a documented website migration SEO checklist catches the metadata and crawl issues that only surface weeks later as ranking drops.
Testing, Cutover, And Monitoring
Before flipping DNS, stand the new stack up on a staging domain and validate it end to end. Crawl the staging site with Screaming Frog, compare its URL inventory and status codes against the WordPress crawl, and confirm every 301 resolves in a single hop. Load-test the GraphQL endpoint under realistic concurrency, and verify that image storage, forms, and any authenticated flows behave as expected.
Schedule the cutover for a low-traffic window, keep the WordPress instance running read-only as a fallback, and monitor closely afterward. Watch Search Console for crawl errors and coverage changes, track Core Web Vitals, and keep an eye on 404 logs for the first few weeks so you can patch any redirect you missed. Because Keystone serves structured data to a decoupled front end, you also gain clean observability: API latency, cache hit rates, and build times are all measurable in ways a WordPress monolith never exposed.
Frequently Asked Questions
Is Keystone.js a good replacement for WordPress?
How do I move WordPress content into Keystone.js?
Will migrating to Keystone.js hurt my SEO?
What database does Keystone.js use?
Do I need a separate front end with Keystone.js?
Get a FREE GEO/AEO/SEO Audit
We'll analyze your site's SEO, GEO, AEO & CRO — completely free — and show you exactly how to get found across Google and AI answers.
Don't have a site yet? Get in touch →






