Prismic and Storyblok are both built around page-building with reusable sections, called slices in Prismic and bloks in Storyblok. Sanity does the same with arrays of object types. That makes the move more mechanical than most, but two things decide whether it's a success: how cleanly the blocks map, and whether editors get a preview that's as good as what they had. These notes cover both. For the wider set of routes, see our headless CMS migration guide.
Why do teams migrate from Prismic or Storyblok to Sanity?
Teams migrate from Prismic or Storyblok to Sanity mostly for a more flexible content model, a customisable editing studio and querying with GROQ. Sanity Studio is a React app you configure in code, so teams can shape the editor around their content instead of working within a fixed interface.
The common triggers we hear about are content models that have outgrown page-centric types, a need to reuse content across several sites or apps, and editor requests that the current interface can't meet. Pricing tiers can be a factor too; compare current plan pages for your seat count and usage rather than relying on old numbers.
It's not a one-way upgrade. Storyblok's Visual Editor is excellent for marketers who build pages by clicking on them, and Prismic's Slice Machine gives developers a tidy workflow for section-based sites. If those workflows are what your team loves, weigh that before moving. Our comparison of Contentful, Sanity, Payload and Strapi covers the wider options.
How do Prismic slices and Storyblok bloks map to Sanity?
Prismic slices and Storyblok bloks map to Sanity object types placed inside an array field, usually called sections or pageBuilder. Each slice or blok type becomes one object type with matching fields, and the slice zone or bloks field becomes the array that holds them in order.
Prismic | Storyblok | Sanity |
|---|---|---|
Custom type (repeatable) | Content type component | Document type |
Custom type (single) | Single story or global settings | Singleton document |
Slice zone | Bloks field | Array of object types |
Slice | Nestable component (blok) | Object type |
Slice variation | Component option or separate blok | Variant field or separate type |
Repeatable group | Nested bloks | Array of objects |
Content relationship | Story reference | Reference |
Rich text field | Richtext field | Portable Text |
Image field (Prismic CDN) | Asset (Storyblok CDN) | Image asset in Sanity |
How should slice variations be handled?
Variations are the main design decision. If two variations share most fields, such as a hero with the image left or right, model one Sanity type with a layout field. If they have different fields, model separate types. Keeping variants as fields stops the editor's insert menu from growing to forty options.
How do you convert Prismic and Storyblok rich text to Portable Text?
You convert Prismic and Storyblok rich text to Portable Text with a script, because all three formats are structured JSON. Prismic stores rich text as blocks with spans for bold, italic and links; Storyblok stores a nested node tree. A script walks either format and writes Portable Text blocks, marks and link annotations.
- Paragraphs and headings map directly to Portable Text block styles.
- Bold, italic and code map to decorators.
- Links become link annotations; internal document links become Sanity references after IDs are remapped.
- Embedded images become image objects inside the Portable Text array, pointing at re-uploaded assets.
- Embedded bloks inside Storyblok rich text become custom object types in Portable Text.
Why we avoid converting through HTML
Both platforms can render rich text to HTML, and Sanity's block tools can turn HTML into Portable Text, so going via HTML is tempting. It works for simple text. But internal links lose their document IDs, embedded components flatten into markup, and empty paragraphs and line breaks behave unpredictably.
A direct JSON-to-JSON script takes a little longer to write and keeps references intact. We use the HTML route only for archived content that nobody will edit again.
What are the steps in a Prismic to Sanity migration?
The steps are to model first, export with the platform's API, move assets, transform and import documents, rebuild preview, then cut over. Prismic content comes out through its Document API; Storyblok's through its Content Delivery or Management API, which also exposes stories by folder and full slug.
Model the Sanity schema
Write document and object types from the mapping table, merging similar slices. Our guide to content modeling for a CMS migration explains how to avoid copying old mistakes.
Export everything
Fetch every document or story, including all locales, and save raw JSON so you can re-run transforms without re-exporting.
Move assets
Download each image and file from the old CDN, upload it to Sanity, and keep a map from old URLs to new asset IDs. Carry alt text and focal points.
Transform and import
Convert slices or bloks to Sanity objects, rich text to Portable Text, and relationships to references. Import with the Sanity client in dependency order.
Rebuild preview
Set up Sanity's Presentation tool and Visual Editing in your front end, then test it against the parity checklist below.
Map URLs and cut over
Rebuild routes from Prismic UIDs or Storyblok full slugs, redirect anything that changes, freeze edits, do a final import and launch.
How do you check preview parity before switching editors?
You check preview parity by writing down every preview behaviour editors use today, then testing each one in Sanity with a real editor before launch. Storyblok users in particular are used to clicking a section on the page to edit it, so Sanity's click-to-edit overlays need to work on every block type.
Preview check | What to test in Sanity |
|---|---|
Draft preview | Unpublished changes show on the real page |
Live updates | The page updates as the editor types |
Click to edit | Clicking any section opens the right field |
New pages | A never-published page can be previewed |
Shareable links | A reviewer without edit rights can see a draft |
Locales | Each language previews on its own URL |
Mobile view | Editors can preview at phone width |
What usually goes wrong, and how do you avoid it?
What usually goes wrong is quiet data loss: a slice type nobody remembered, a locale that wasn't exported or images still pointing at the old CDN. Avoid it by counting. Compare the number of documents, slices or bloks and assets per type before and after import, and investigate every mismatch.
Also crawl the old and new sites and compare titles, descriptions and status codes for every URL. If you're moving from Contentful at the same time or later, the process is similar; see our Contentful to Sanity migration guide. AI coding agents can help write the transforms, as our guide to AI-assisted website migration explains, but the counting and preview checks need a person. And if you later want a self-hosted setup, our Sanity to Payload migration guide covers that route.
