Discussion on organizing schemas and splitting schemas with the same name in Sanity

6 replies
Last updated: Apr 7, 2022
Hello, i am very new to Sanity and try to organise/structure my schemas nicely. I already did some work and now i am realising that my structure wasn’t that good. My structure is the following:
schema
-- documents
-- objects
-- sections
---- hero.js
I have the problem that i have some sections that have the same name because they are used in different documents. Nevertheless, these elements are different. So i tried to change the structure like following:

schema
-- documents
-- objects
-- sections
---- abc
------ hero.js
---- xyz
------ hero.js
Obviously it is not possible to have schema with the same name. But now my Question. How can I change my schema name without losing all the content in the Studio. If I change the schema name I lose all my content. Perhaps there is a way to transfer the contents? I hope someone can help me. Thank you in advance.
AI Update

I understand your frustration - this is a common challenge when learning Sanity! The good news is that you can reorganize your schema structure without losing content, but it's important to understand what's actually happening under the hood.

The Core Issue

The folder structure (schema/sections/abc/hero.js) is purely for your organization - Sanity doesn't care about it at all. What Sanity does care about is the _type field stored in each document. This is what identifies the schema type.

However, there's a critical constraint: the _type field is immutable. According to the official Sanity migration documentation, you cannot change _type, _id, _createdAt, _updatedAt, or _rev once they're set. These are immutable properties in the Content Lake.

The Right Solution: Unique Schema Names

Instead of trying to have multiple schemas with the same name in different folders, you should give each schema a unique name property that reflects its context:

schema/
  documents/
  objects/
  sections/
    abc/
      abcHero.js  // name: 'abcHero'
    xyz/
      xyzHero.js  // name: 'xyzHero'

In each schema file, make sure the name field is unique:

// schema/sections/abc/abcHero.js
export default {
  name: 'abcHero',  // This is what becomes _type
  type: 'object',
  title: 'ABC Hero Section',
  fields: [
    // your fields
  ]
}

If You Already Have Conflicting Names

If you've already created content with conflicting schema names, you'll need to migrate the data. Since _type is immutable, you can't use the standard migration toolkit's at('_type', set(...)) approach. Instead, you need to:

1. Export Your Dataset

sanity dataset export production --no-assets

This creates a .tar.gz file containing an NDJSON file with all your documents.

2. Modify the Export File

tar -xzvf production.tar.gz

Open the .ndjson file and find/replace the _type values. For example, change documents from:

{"_id": "abc123", "_type": "hero", ...}

to:

{"_id": "abc123", "_type": "abcHero", ...}

Important: You'll also need to update any references to these documents throughout your dataset. If other documents reference these by type (in arrays with type filters, for example), those need updating too.

3. Update Your Schema

Before reimporting, update your schema files with the new unique names.

4. Delete Old Documents (if keeping same IDs)

If you're keeping the same _id values but changing the _type, you'll need to delete the old documents first. Create a migration:

import {defineMigration, delete_} from 'sanity/migrate'

export default defineMigration({
  title: 'Delete old hero documents',
  documentTypes: ['hero'], // the old type name
  
  migrate: {
    document(doc) {
      return delete_(doc._id)
    }
  }
})

Run this with:

sanity migration run "Delete old hero documents" --dataset production

5. Reimport Your Modified Data

sanity dataset import production.ndjson production --replace

Alternative: Create New Documents with Different IDs

If the above seems too risky, you could also:

  1. Keep your old documents as-is
  2. Create new schema types with unique names (abcHero, xyzHero)
  3. Manually recreate the content in Studio with the new types
  4. Delete the old documents once you've verified everything works

This is safer but more manual work.

Better Approach for the Future

To avoid this entirely, establish a naming convention from the start:

  • Prefix by context: homeHero, productHero, aboutHero
  • Prefix by document type: pageHero, postHero
  • Use descriptive names: Instead of generic "hero", use fullWidthHero, splitHero, etc.

The folder structure is just for your convenience - the name field in the schema is what matters to Sanity.

Important Notes

  • Backup first: Always export your dataset before attempting any destructive operations
  • Test on development: Try this process on a development dataset first
  • Strong references: If documents have strong references to the ones you're changing, you'll need to handle those carefully in your NDJSON edits
  • Validate after: Run npx sanity documents validate after migration to ensure everything is correct

The key takeaway: organize your files however you want, but make sure every schema has a unique name property. That's what Sanity uses to identify content types, not the file structure. The migration cheat sheet has more examples of common migration patterns, though changing _type specifically requires the export/modify/reimport approach.

If you have a lot of documents and data in your dataset — This guide for exporting data may be the reference you need. The idea is that you export your data, go through the json data file, and update your document headers or IDs with your new desired types. There are a variety of third party tools to make this easier than it sounds.
BUT… from your change I wonder if there is a way to do this with creative schema updates.
You could add a new field or related document to your hero schema. Continue to use ONE hero schema for your different sections. Then add that field (or a variety of desired fields) to your single hero schema.

Then when you query your data, include a statement like

if this hero is an ABC type, do ABC
if this hero is an XYZ type, do XYZ
Now this is either one extra query statement on your front end or an extra line in your existing query. And you don’t have to do the entire export import thing - along with having a single source of truth for all of your hero sections
Thanks a lot for the answer. I really want to split the two hero schemas. So i will try to do the migration.
Thanks a lot for the answer. I really wont to split the two hero schemas. So i will try to do the migration.
Hey
user U
, , unfortunately I haven’t gotten around to making the change on my end yet. But I have already tried the migration and it worked well.Unfortunately, I am still not satisfied with the structure. I now have the structure as shown above. So in my sections two folders with two different brands of the customer. These each have different hero schemas. Named with abcHero and xyzHero. However, I find this solution unattractive and was hoping to find another.
I still want to separate the two hero’s from each other. Is there any way to manage two schemas with the same “name” attributes? Maybe via two separate schema.js files or something?
Couldn’t find any solution.
For some further discussions on your content structure, you might enjoy the conversations in content-modeling and content-strategy.
For your desires to duplicate schema files, you’re going to come up against some fundamental javascript and coding things in general. Even if you completely duplicate your studio, while you’re in the same dataset - a
hero
document type is going to be the same regardless. If you want to juggle both clients in a single dataset, I think this would be extremely doable.
Maybe most of all, a little
head tilt on the concepts of schemas vs documents might be in order. Your schemas define what appears in your documents. Your documents are where the data is. So, if you make a “hero type” schema, you can make 100 “hero type” documents. If you want to add different fields to different hero types, you’ll need to create a new type or hide/show the fields depending on selections made in the document. Which of those hero or footer docs is referenced into each customer site would depend on your query that you build in your frontend vs the data in your document.
so, if you’re building multiple sites from a single dataset, I would suggest adding a “client” selection to your hero schema and then alter your query in each site to return the specific document for each section you want to display. You could even add a fn to insert a constants value into your query from another file and copy paste all of your sites, just needing to fill in the constants values to change the query sources relative to the client selection I noted.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?