Moving a Drupal estate to Sanity isn’t a case of hitting export, importing content, and expecting everything to carry on from where it left off. The content has to be reconfigured and rebuilt, which is where the majority of the migration work must be done.
This guide walks through the mapping decisions in order, from content types down to individual fields, and shows what really drives the effort in a Drupal-to-Sanity move. Whether you’re migrating a straightforward brochure site or untangling a decade’s worth of accumulated taxonomy, you’ll see exactly what needs rebuilding, and why. With the right steps, you’ll have a cleaner, more flexible content model that’s easier to manage and evolve long after the migration is complete.
Can You Migrate Drupal to Sanity Directly?
No, you can’t move Drupal to Sanity as a direct transfer. Your content has to be remodeled on the way across rather than copied over as-is. That remodeling work is also what unlocks Sanity’s real advantage: content your editorial team can update and ship without waiting on a developer ticket.
That’s because of how the two platforms store content. Drupal spreads content across relational database tables, meaning its structure lives in the relationships between those tables rather than in one self-contained record. Sanity takes a fundamentally different approach, storing each item as a single structured JSON document, decoupling content from any front end and delivering it via API to any channel.
That means you’re changing the shape of your content, not simply its location. A migration script can’t just lift rows from Drupal’s database and drop them into Sanity and expect them to work within your intended Sanity content model. You first need to define that model in Sanity Studio, then map and transform the Drupal content to fit it.
How Does Drupal Content Map to Sanity Documents?
Each Drupal content type can map to a Sanity document type, while taxonomy terms can become reusable referenced documents. That’s the starting point for the mapping work, but the real detail is in how you handle the individual fields.
| Drupal construct | Sanity equivalent | What changes |
|---|---|---|
| Content type | Document type | Defined as a schema in code, not configured through an admin UI |
| Field (text) | String or text field | Typed explicitly, rather than inferred by Drupal’s field system |
| Field (boolean) | Boolean field | Direct mapping, minimal structural change |
| Field (date) | Date or datetime field | Format and timezone handling need explicit decisions |
| Entity reference | Reference field | Points to another document rather than a table foreign key |
| Taxonomy term | Referenced document | Becomes its own document type, queryable independently |
Every Drupal field maps to a typed Sanity field, whether that’s text, boolean, date, or reference, and each needs to be considered individually rather than handled through one blanket rule. A text field containing loosely formatted data in Drupal, for example, may need a stricter type in Sanity, or a decision about whether it should become a string or a full block of rich text. None of this is specific to a particular Drupal release; the same principles apply regardless of the Drupal estate you’re migrating from.
How Is Rich Text Converted to Portable Text?
Drupal body HTML gets converted into Portable Text, Sanity’s structured rich-text format. This is one of the more involved parts of a migration, so it’s useful to understand what the process involves before you begin.
The standard approach runs the HTML through @portabletext/block-tools and its htmlToBlocks() function, which parses the markup into Portable Text’s block structure. The function handles plenty automatically, but there are still important exceptions you’ll need to account for.
Embedded images, shortcodes, inline markup, and pasted tables each need their own conversion rules because they don’t map neatly to Portable Text’s default block types. A shortcode that rendered a custom widget in Drupal, for example, needs a defined replacement rather than simply having its tag stripped out. This is the same conversion challenge covered in Multidots‘ WordPress to Sanity guide, since the underlying HTML-to-Portable-Text problem is largely the same whichever CMS you’re migrating from.
Get this conversion right, and you’ll improve your editorial velocity, allowing writers to work in a structured block editor instead of fighting shortcodes and raw HTML.
What Happens to Images and Media Files?
Drupal image and file fields become Sanity assets, uploaded through Sanity’s asset pipeline rather than simply copied from one storage location to another.
An important distinction to recognize from the outset is that media embedded within body content is handled separately from media attached directly to a field. A field-level image already has a clear, structured relationship with its parent document. An image embedded inline within a body of rich text needs to be extracted during the HTML-to-Portable-Text conversion and then re-linked as its own asset reference.
A practical step that can save you a lot of trouble later is to keep the source image URLs intact so the migration script can download and properly ingest the files through Sanity’s pipeline. Avoid embedding base64-encoded files directly. Doing so unnecessarily increases document size and bypasses the asset pipeline’s built-in optimization and CDN delivery entirely.
What Determines How Long a Migration Takes?
There’s no fixed timeline for a Drupal-to-Sanity migration: how long it takes depends on how much structure lives in your content, not how many pages you’re moving. A thousand simple pages with a flat structure can migrate faster than a hundred pages tied up in deep taxonomy and inconsistent markup.
There are three factors that account for most of that effort:
- Content volume.
- Taxonomy depth.
- Markup buried inside body fields.
Although volume matters, on its own it’s the least significant of the three. Taxonomy depth is more impactful because every level of nested categorization requires its own mapping decision. And markup buried in body fields, including the shortcodes, embedded widgets, and pasted tables mentioned earlier, is often where estimates get stuck, because that complexity only becomes clear once someone looks closely at the content.
The key point to understand before scoping anything is that the modeling decisions need to happen before any script runs, and that’s where much of the time goes. Writing the extraction and transformation scripts is often relatively quick. Deciding what the new schema should actually look like is what determines whether a migration runs smoothly or stretches out for months. Running sanity schemas validate before the first import catches errors in your schema definitions. To catch mismatches between migrated content and your finished schema, use sanity documents validate --file to check the prepared import file before thousands of documents are imported.
For a CMO scoping this, taxonomy depth and body-field markup are the two questions worth asking early, since they’re what turn a fixed-price estimate into a moving target.
How Do You Sequence a Drupal to Sanity Migration?
A migration follows a defined order:
- Audit and model the content first.
- Extract.
- Transform.
- Import.
- Validate.
Jumping ahead to scripting before the modeling is settled is one of the most common ways this process goes off track.
Extraction pulls from Drupal through its JSON:API rather than querying database tables directly, since the API already handles the relational structure Drupal uses to connect content. Where JSON:API access is limited, or a site needs a heavier extraction pass, a Drush script that queries entities directly and dumps them to JSON is a common fallback – particularly on older Drupal 7 estates that never had JSON:API enabled. From there, the export is transformed into NDJSON, with one document per line, which is the format Sanity’s import tooling expects, and then imported using the Sanity CLI. Each line is a complete document identified by its _type and _id – a migrated blog post, for instance, carries _type: “post”, its slug, and a body array of Portable Text blocks, with any inline image already swapped for an asset reference by the time it reaches the file.
Before any of this touches production, run the import against a staging dataset first. This catches schema mismatches and conversion errors while they’re still relatively easy to fix, rather than after they’ve landed in a live dataset editors are already using. Running sanity datasets import against a staging dataset rather than production is what makes the dry run meaningful: you’re validating against the same schema constraints as live content, with zero risk to it. This is the same phased approach covered in more depth in Multidots’ Sitecore to Sanity guide and AEM to Sanity guide, since the underlying sequencing logic applies regardless of the source platform.
Because the import runs against staging first, the live site stays up throughout. Before the production import, take a fresh export of the production dataset so you have a rollback point if anything goes wrong.
What Happens to Drupal URLs After Migrating to Sanity?
Drupal URL aliases don’t transfer automatically. Whether they were created through pathauto’s automated pattern rules or added manually, that configuration won’t carry over to a new platform on its own.
The practical fix is to export the existing aliases from Drupal, then build a 301 redirect map on whichever frontend framework serves the new Sanity-backed site. That mapping needs to account for every URL pattern currently indexed and point each changed URL to its most relevant new destination.
Timing matters more than it might seem, though. Define the redirect map as part of the migration itself, while you still have full visibility into the old URL structure, rather than leaving it as clean-up work after launch. Internal links, canonical URLs, and the XML sitemap should also point to the final URLs when the new site goes live. Gaps here lead to broken links and lost search rankings, which is exactly the kind of damage that’s much harder to reverse once the old site is gone.
Which Drupal to Sanity Migration Approach Fits Your Situation?
There are a few realistic routes off Drupal: an in-house scripted migration, migration tooling built around community scripts, or a specialist agency handling the process end to end.
In-house builds and community tooling can be a good fit for a simple content model, and there’s little reason to overpay for a straightforward brochure site. The risk tends to emerge around rich text conversion, asset handling, and modeling errors discovered too late, after content has already been imported and editors have started working with a structure that turns out to be wrong.
For a large estate or genuinely deep taxonomy, a specialist partner can meaningfully reduce that risk while keeping the site live throughout the transition rather than forcing a disruptive cutover. Multidots runs enterprise Drupal migrations to Sanity as an official Sanity partner, with the specific goal of preserving structured content and editorial workflows throughout the move.
Plan Your Drupal to Sanity Migration with Multidots
A Drupal-to-Sanity move is a remodel, and it’s one worth making. Where Drupal ties content to a self-hosted, database-driven stack, Sanity gives you structured content delivered by API to any channel, a real-time collaborative editor your team can use without ongoing developer assistance, and fully managed content infrastructure with usage-based scaling that reduces the burden of server maintenance, patching, and infrastructure management, potentially lowering total cost of ownership. Done well, your editors get a faster, more flexible platform they’ll notice from day one.
The content-model decisions are where most of the time goes, which is why the safer route is to work with a partner who can make those decisions alongside you, rather than making assumptions and correcting them later. Multidots has completed over 1,000 platform migrations and is an official Sanity partner, moving estates at real scale with zero downtime throughout the transition.
If you’re scoping a Drupal estate and want a clearer sense of the effort involved, Multidots’ Sanity migration services team can walk you through exactly what your content requires.
