Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Migrating Schema types

Declaring your schema types is a fundamental part of configuring your studio. In v2, schemas were dependent on the part:@sanity/base/schema-part, and was typically included by default when initializing a new project.

In the new Config API, schemas are declared in the top-level schema.types property of the root workspace configuration.

Minimal example

You don't need to explicitly concatenate your custom schemas with the built-in and plugin schemas anymore. Simply add your schemas to the schema.types array in the config object.

import {defineConfig} from 'sanity'

const schemaTypes = [
  {
    name: 'post',
    type: 'document',
    title: 'Blog Post',
    fields: [
      {
        name: 'title',
        title: 'Title',
        type: 'string',
      },
      {
        name: 'body',
        title: 'Body',
        type: 'array',
        of: [{ type: 'block' }]
      }
    ]
  },
  // ...more document types here
]

export default defineConfig({
  // ...rest of config
  schema: {
    types: schemaTypes,
  },
})

New features

defineType and defineField helper functions

Although you can build out schemas by defining them as objects that you pass to the schema.types array, you can also start to wrap them in the defineType and defineField helper functions. Since these are typed, they can provide both autocomplete suggestions for properties and instant feedback on errors in your configuration. Let's take the schema example above and add these functions to it:

// /schemas/book.js (.ts)
import { defineType, defineField } from "sanity";

export const book = defineType({
  name: "book",
  type: "document",
  title: "Book",
  fields: [
    defineField({
      name: "title",
      type: "string",
      title: "Book title",
    }),
    defineField({
      name: "firstPublished",
      type: "datetime",
      title: "First published",
    }),
  ],
})

Breaking change: The new components property

The Schema API is mostly the same between v2 and v3. The only thing that has been changed is how you add custom components in the schema definition. If you had custom input components that you passed into inputComponent and custom preview components that you passed into preview.component, then these have to be moved to the new components property.

Migrating a custom input component

In v2, you would do:

// /schemas/document.js
import MyCustomString from '../src/MyCustomString'

export default {
  name: 'documentSchema',
  title: 'A document',
  type: 'document',
  fields: [
    {
      name: 'customString',
      title: 'This is a cool custom string',
      type: 'string',
      inputComponent: MyCustomString
    },
    // ... All other inputs
  ]
}

In v3, you can do:

// /schemas/book.js
import { defineType, defineField } from 'sanity'
import MyCustomString from '../src/MyCustomString'

export const book = defineType({
  name: 'book',
  title: 'Book',
  type: 'document',
  fields: [
    {
      name: 'title',
      type: 'string',
      title: 'Book Title',
      components: {
        input: MyCustomString
      }
    },
    // ... All other inputs
  ]
})

Migrating a custom preview component

See also: (List) previews in the v2 docs.

In v2, you would do:

// /schemas/book.js
import { ISBNBarcodePreview } from '../src/ISBNBarcodePreview'

export default {
  name: 'book',
  title: 'Book',
  type: 'document',
  fields: [
    // ... All other inputs
    {
      name: 'metadata'
      type: 'object',
      title: 'Metadata',
      preview: {
        select: {
          isbn: 'isbn',
          isbn13: 'isbn13'
        },
        component: ISBNBarcodePreview
      },
      fields: [
        {
          name: 'isbn',
          type: 'string',
          title: 'ISBN'
        },
        {
          name: 'isbn13',
          type: 'string',
          title: 'ISBN'
        },
      ]
      
    }
  ]

In v3, you would do:

// /schemas/book.js
import { defineType, defineField } from 'sanity'
import { ISBNBarcodePreview } from '../src/ISBNBarcodePreview'

export const book = defineType({
  name: 'book',
  title: 'Book',
  type: 'document',
  fields: [
    // ... All other inputs
    defineField({
      name: 'metadata'
      type: 'object',
      title: 'Metadata',
      preview: {
        select: {
          isbn: 'isbn',
          isbn13: 'isbn13'
        },
      },
      components: {
        preview: ISBNBarcodePreview
      },
      fields: [
        defineField({
          name: 'isbn',
          type: 'string',
          title: 'ISBN'
        }),
        defineField({
          name: 'isbn13',
          type: 'string',
          title: 'ISBN'
        }),
      ]
      
    })
  ]
})

Migrating a custom diff component

How to migrate a custom diff component. See also: Diff components in the v2 docs.

In v2, you would do:

// /schemas/product.js
import {customStringDiff} from '../diffComponents/customStringDiff'

export default {
  name: 'product',
  title: 'Product',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
      diffComponent: customStringDiff
    },
    // ... Additional fields
  ]
}

In v3, you would do:

// /schemas/product.js (.ts)
import { defineType, defineField } from 'sanity'
import { customStringDiff } from '../diffComponents/customStringDiff'

export const product = defineType({
  name: 'product',
  title: 'Product',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
      components: {
        diff: customStringDiff
      }
    }),
    // ... Additional fields
  ]
})

Feedback or questions?

These guides are under development. If you have questions or suggestions for improvement then we want to hear from you. Get in touch via our GitHub discussions page.

Was this article helpful?