👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

Migrating Workspaces (Experimental Spaces)

In v2, you could use the __experimental_spaces property to enable switching between datasets in a studio. In v3, this is replaced with Workspaces. The Workspaces feature is essentially passing an array of configuration objects to the defineConfig function. This is a much more powerful and flexible system that also allows users of the Studio to switch quickly between projects and other configurations.

Minimal Workspace example

Let's compare setting up switching between two datasets (staging and production) in v2 using __experimental_spaces and in v3, passing an array of configs to defineConfig.

This is what it looks like in v2:

// /sanity.json
{
  "root": true,
  "project": {
    "name": "My Sanity Studio"
  },
  "api": {
    "projectId": "my-project-id",
    "dataset": "productiont"
  },
  "__experimental_spaces": [
    {
      "name": "production",
      "title": "Prod",
      "default": true,
      "api": {
        "projectId": "my-project-id",
        "dataset": "production"
      }
    },
    {
      "name": "staging",
      "title": "Staging",
      "api": {
        "projectId": "my-project-id",
        "dataset": "staging"
      }
    }
  ],
  "plugins": [
    "@sanity/base",
    "@sanity/default-layout",
    "@sanity/default-login",
    "@sanity/desk-tool",
    "@sanity/code-input"
  ],
  "parts": [
    {
      "name": "part:@sanity/base/schema",
      "path": "./schemas/schema"
    }
  ]
}

And here is the same setup in v3, passing an array of configs to to defineConfig:

// /sanity.config.js (.ts)
import {defineConfig, definePlugin} from 'sanity'
import {structureTool} from 'sanity/structure'
import {schemaTypes} from './schemas'

const sharedConfig = definePlugin({
  name: 'shareConfig',
  tools: structureTool(),
  schema: {
    types: schemaTypes
  }
})

export default defineConfig([
  {
    name: 'default',
    title: 'Prod',
    projectId: 'my-project-id',
    dataset: 'production',
    // the base path is required whenever more than one workspace is defined and is used for route matching
    basePath: '/prod',
    plugins: [sharedConfig()],
  },
  {
    name: 'staging',
    title: 'Staging',
    projectId: 'my-project-id',
    dataset: 'staging',
    basePath: '/staging',
    plugins: [sharedConfig()],
  },
])

  • The first config in the array is also the default space (deprecating "default": true)
  • The name property isn't used at the moment, but you should give it a meaningful value to support future features
  • title is what ends up in the Studio's upper left corner (if it's not overridden by a logo plugin and in the WorkSpaces switcher
  • basePath controls the Studio's URL routing. If you go from one to multiple spaces in the Studio, then any external Studio links might break since you go from /structure to /basePathValue/structure
  • In this example, we demonstrate how to set up a shared configuration between the spaces using the definePlugin function and placing structureTool in its tools property.

New features

  • Workspaces not only let you switch quickly between datasets it also supports switching between different projects, as well as any configuration.
  • You can also share some parts of a configuration between Workspaces and have other things specific.

Frequently Asked Questions

Can I return Workspaces conditionally?

There is no out-of-the-box for returning Workspaces based on conditions like the logged-in user or other dependencies. You can facilitate it by embedding the Studio in a React component that checks for the current user and renders the Studio and its config based on it.

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?