Make It Yours: Sanity Studio v3 Developer Preview (ssr)

Written by Knut Melvær

Missing Image!

Have you ever felt painted into a corner by a CMS? Most of us have. That’s why we designed Sanity Studio as a flexible framework for developers to build exceptional editorial experiences for their teams, leveraging structured content.

You can get up and running quickly with an editing interface without losing momentum as custom needs arise. Developers and editors consistently tell us that they love to make the Studio their own. With Sanity Studio Version 3, you’ll be able to do so with the tooling you’d like and patterns you know.

A major upgrade to developer experience

We’re delighted to share a preview of the next major version of Sanity Studio with you. We’ve synthesized six years of learning and feedback to give it a significant upgrade, so it’s even faster and easier to customize to your needs. We hope you’ll download and try it out and provide us with feedback on how it works for you.

Sanity Studio v3 comes with the following improvements:

This upgrade also makes it easier for us to move faster and more reliably in bringing new features to Sanity Studio.

You can bootstrap a new v3 Studio from the command line and learn how to migrate existing ones in the new docs beta:

npm create sanity@dev-preview
PortableText [components.type] is missing "protip"

Heads up: breaking changes

Until now, we’ve been able to avoid breaking changes. Because let’s face it: breaking changes for code you rely on sucks. But to unlock the many improvements with this upgrade, we decided to remove the Parts System in v3 and build new APIs from scratch based on feedback and learnings (and a lot of contemplation).

The Parts system in V2 is under-documented, and it has been hard to decide what should be a public API or not. And we were stuck on Webpack 3 (from 2017) because it is too hard to upgrade with confidence.

Removing the Parts System meant we got to design new APIs. And creating new APIs was an opportunity to improve and modernize. So, this is the first time in 5 years that you can’t just run sanity upgrade with our latest updates. It's not a decision we made lightly.

While we hope that the new features and possibilities will sweeten the deal, we will also:

What does this mean for v2?

We haven’t set a date to sunset v2 yet and will listen and learn from our community and customers before we do. Our advice is that you should, for the time being, use v2 for production, but look into what it takes to migrate to v3. You should be able to fork out and try out v3 in parallel. There are no breaking changes in how the Studio operates with the Content Lake, and the Schema API is, for the most part, the same.

Now, let’s take a closer look at what’s new!

Bring your Sanity Studio anywhere

The Studio is now bundler agnostic; in fact, you don’t really need a bundler at all. We have upgraded all the packages to ECMAScript Modules (ESM) with CommonJS fallback. In fact, v3 ships in with a so-called “monopackage.” The Studio, including the Desk tool plugin, is found in the sanity package on NPM.

In other words, the Studio comes as a React component, with a renderStudio function that lets you mount it on any DOM element. As long as you can redirect all subpaths for the Studio’s basePath, as you would with any Single Page Application (SPA), you’re good!

This means that you can embed the Studio in your web apps and backoffice systems. Since ESM supports URL imports, you don’t need to install the studio dependencies locally but get them from Skypack or similar services.

<html>
  <head>
    <style>
      html {
        -webkit-text-size-adjust: 100%;
        text-size-adjust: 100%;
        -webkit-tap-highlight-color: transparent;
        -webkit-font-smoothing: antialiased;
      }
      html,
      body,
      #app {
        height: 100%;
        margin: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <div id="app">
    In the near future, you should be able to do something like this 🤯
  </div>
  <script type="module">
    import {
      renderStudio,
      createConfig,
    } from "https://cdn.skypack.dev/@sanity/base";
    import { deskTool } from "https://cdn.skypack.dev/@sanity/base/desk";

    const config = createConfig({
      plugins: [deskTool()],
      name: "Sanity Studio in HTML",
      projectId: "b5vzhxkv",
      dataset: "production",
      schema: {
        types: [
          {
            type: "document",
            name: "post",
            title: "Post",
            fields: [
              {
                type: "string",
                name: "title",
                title: "Title",
              },
            ],
          },
        ],
      },
    });
    renderStudio(document.getElementById("app"), config);
  </script>
</html>

We don’t know about any other CMS or content editing solutions that offer this kind of flexibility. And we believe it sets Sanity apart as a true content platform and developer tool.

We will ship examples of how to embed Sanity Studio v3 in some popular frameworks very soon.

Dynamic configuration

Before v3, the way you let the Studio know what project and dataset connect to, as well as which plugins and parts it should use and override, was to tell it in a sanity.json file. This has now been deprecated in v3. We have adopted a pattern that you’ll recognize from popular JavaScript-based frameworks.

With the new built-in dev-tooling, you can now export the createConfig function in a sanity.config.js (or .ts ) file. And you can return configuration conditionally based on environment and even user roles. It also means that schemas and other configurations can be imported in runtime, which opens up interesting opportunities we can’t wait to explore.

You can now bootstrap a new v3 Studio with only package.json and sanity.config.js.

// sanity.config.ts
import { createConfig } from "sanity";
import { deskTool } from "sanity/desk"

export default createConfig({
  name: "default",
  projectId: "bx531vlt",
  dataset: "production",
  plugins: [deskTool()],
  schema: {
    types: [
			{
				type: 'document',
				name: 'post',
				title: 'Post',
				fields: [
					{type: 'string', name: 'title'},
					{type: 'slug', name: 'slug'},
					{type: 'image', name: 'image'},
					{type: 'content', name: 'array', of: [{type: 'block'}]},
				]
			}
		],
  },
});

If you’re using the out-of-the-box tooling, Sanity Studio v3 will run Vite for the development server and for bundling for production. The Hot-Module-Reloading should be very fast, and your production builds of the Studio should be lighter since we can better leverage tree-shaking (that is, avoid bundling code that’s not used).

Workspaces and support for multiple plugin instances

Notice that deskTool is loaded into the plugins array. Desk tool is the editing environment where you can work in real-time with documents in the Content Lake. It was, in fact, always a “plugin.”

With this new update, you can load multiple deskTools with a combination of shared and specific structures and configurations. This has been a frequent feature request and is useful when you want to offer different contexts for custom workflows.

In v3, we have also deprecated __experimental_spaces by introducing a new concept called Workspaces. You create a new workspace by passing in additional configurations in an array to createConfig. While __experimental_spaces let you quickly switch between datasets, Workspaces enables you to switch between any combination of projects, datasets, and configurations.

Simplified but more powerful form customization

Sanity Studio comes with powerful form building out of the box. You can use the built-in schema types combined with the array and object inputs to express pretty much any structure and get an automatically generated intuitive and responsive UI for it. However, structured content also allows for specialized input components.

Take content about time and duration. You can model this using a combination of date, string, and array fields. It will work, but it isn’t exactly a fun experience. So we have tried to make it fun and convenient to make custom input components!

In fact, one of our industrious Solution Engineers made a custom input component for setting availability using the new APIs in… less than a day. We think it’s a good example of things you totally should be able to do without too much fuss.

PortableText [components.type] is missing "muxVideo"

We also expose hooks into the form building that lets you wrap input components and insert your own programmatically using a reducer pattern. Below you find a simple example of adding character count to any field with the name title:

// sanity.config.ts
// Add a simple character count to any title field
export default createConfig({
	// ... other config
  form: {
    renderInput: (props, next) => {
      if (props.schemaType.type?.name == "title") {
        return (
					<Card>
						<Stack space={2}>
              <div>{next(props)}</div>
              <Text>Character count: {props.value?.length}</Text>
            </Stack>
          </Card>
        )  
      }
      return next(props)
  }
}

By exposing the different layers of the Studio’s forms, it should be easier to customize exactly what you need and leave the rest to the Studio. This way, you can feel confident that your forms are consistent and accessible. Concentrate on the customization you want to do without having to reproduce a lot of internal Studio logic. It may be a cliché to say, but we truly can’t wait to see what you’ll do with this!

The new Plugins API and toolkit

Maybe you make a custom input component that’s so useful (or fun) that you want to share it with others? Shipping code that others should rely on onto npm isn’t necessarily the easiest task (believe us, we know). That’s why we made a new Plugin toolkit that will help you with local plugin development, validate that the plugin has the formal configuration in order, and with publishing new versions on npm.

We built this toolkit to assist our migration of the official Sanity Studio plugins, which all are v3 Ready. We will update the sanity.io/plugins site to reflect this too. If you are a plugin maintainer and want to discuss or give us feedback on the migration experience, do let us know on GitHub Discussions.

Dark Mode is here. Coming soon: Theming!

The Sanity Studio v3 UI pretty much looks and works the same as before. In fact, refactoring all the visual elements to Sanity UI was the first step toward getting rid of the Parts System. That being said, we did take the opportunity to add dark mode support for this release, as well as the plugins we have migrated. Dark mode uses the operating system’s setting to (de)activate. And, of course, if you use Sanity UI to customize, it will just work.

A screenshot of the studio in dark mode with custom input components for duration and availability

Dark mode relies on the fact that Sanity UI is themeable, but its API is very granular and requires you to do a lot of configuration. We’re working on a Theme API that lets you start with some simple values to brand your Studio and opt into more advanced functionality if you need to. The new Theme API will ship for the Developer Preview before v3 hits general availability, and we look forward to getting your feedback on it!

The new Sanity Docs Beta

V3 introduces completely new API surfaces and makes it possible to auto-generate API reference documentation from code. We took this as an opportunity to modernize our documentation site and are launching it in a beta version together with the Developer Preview.

The new documentation site seeks to make it easier to learn the many features found in the Sanity platform, and find cleaner information about the API surfaces, both as unpacking mental models as well as pure API reference documentation. The Sanity Docs Beta will also feature migration guides from v2 to v3. We will actively take feedback and improve these docs as we go towards the general availability of v3.

The new API reference docs showing the signature for the WorkspaceOption interface

A framework for exceptional editor experiences

Developers consistently tell us how much they love the ability to customize Sanity. The ambition with Sanity Studio is to make the building blocks that let you move quickly without sacrificing extensibility. Too often, developers have to say “no” to their teams or spend huge amounts of time getting around systems to give their teams what they need.

This release of Sanity Studio v3 strikes the delicate balance of giving you all the useful out-of-the-box features you expect while not getting in your way with our assumptions. With the release of Sanity Studio v3, we’re raising the bar for how easy and convenient it can be to get started quickly with a content editing experience and keep up the momentum without having the system getting in your way.