Visual Editor /Content sources /

Use Sanity with Visual Editor

Visual Editor has first-class support for two-way syncing content between Sanity and Visual Editor.

# Configure Sanity as a content source

Visual Editor has a tight integration to support Sanity as a content source. This guide covers what you need to know about configuring Visual Editor to provide a two-way data sync between your Sanity project(s).

Here is an example configuration that uses Next.js as the site framework and uses a page content type to represent pages:

// stackbit.config.ts
import { defineStackbitConfig } from "@stackbit/types";
import { SanityContentSource } from "@stackbit/cms-sanity";

export default defineStackbitConfig({
  stackbitVersion: "~0.6.0",
  ssgName: "nextjs",
  nodeVersion: "16",
  contentSources: [
    new SanityContentSource({
      rootPath: __dirname,
      studioPath: path.join(__dirname, "studio"),
      studioUrl: "",
      projectId: process.env.SANITY_PROJECT_ID!,
      token: process.env.SANITY_ACCESS_TOKEN!,
      dataset: process.env.SANITY_DATASET || "production"
  mapModels: ({ models }) => {
    return => {
      if ( === "page") {
        return { ...model, type: "page", urlPath: "/{slug}" };
      return model;

Notice the following:

  • SanityContentSource is being loaded from the @stackbit/cms-sanity which must be installed first. This package is not needed in your production site.
  • Sanity is being configured using local environment variables. Visual Editor automatically loads a .env in the root of your project.
  • There is a content type with an ID of page that is being used to store page data in Sanity. That content type has a field with name slug that determines the URL path at which the page is made available.

# Prerequisites

To be able to work with Sanity, you must first have the following:

  • A Sanity project with content in a dataset.

  • The proper API keys and related environment variables that can access your content. (See options below.)

  • Installed @stackbit/cms-sanity package as a development dependency. (We also recommend @stackbit/types to help with configuration.)

    npm install -D @stackbit/types @stackbit/cms-sanity

# Usage

import { SanityContentSource } from "@stackbit/cms-sanity";

new SanityContentSource({
  rootPath: "...",
  studioPath: "...",
  studioUrl: "...",
  projectId: "...",
  token: "...",
  dataset: "...",
  studioInstallCommand: "..."

# Options

The following are all required options unless otherwise noted:

  • dataset: name of the dataset to be used when editing the content. This is often set as production.
  • projectId: unique ID value assigned to your Sanity project.
  • rootPath: absolute path to the front-end project. This is note the path to the studio, which is covered by studioPath.
  • studioPath: (optional) absolute path to the studio project, which is often contained within the rootPath project directory. The default path is: ${rootPath}/studio.
  • studioInstallCommand: (optional) custom command to run when installing Sanity studio in a cloud project. This can be ignored if using the typical studio installation pattern. To skip install the installation process entirely, set to an unobtrusive command such as echo 'skipping install'.
  • studioUrl: (optional) the URL to the deployed Sanity Studio instance.
  • token: API access token.
# Store sensitive values

Sensitive values can be stored in a .env file, which will then be available when Visual Editor configuration file is loaded.

# .env

# Model type inference

The Sanity CSI module makes the following inferences:

  • Object models in Sanity are automatically inferred as Visual Editor object models.
  • Document models are inferred as Visual Editor data models.

Therefore, page models must be defined using the modelExtensions property.

# Custom Studio installation

If you need to run a custom command when installing Sanity Studio in a cloud project, use the studioInstallCommand option.

new SanityContentSource({
  studioInstallCommand: "..."
  // ...

# Skip Studio installation

To skip the Sanity Studio installation process entirely, specify an arbitrary and unobtrusive command. For example, to simply print "skipping install" to the console, do this:

new SanityContentSource({
  studioInstallCommand: `echo 'skipping install'`
  // ...

# Provision Sanity


This is only relevant when creating a Visual Editor project by duplicating a GitHub repository.

You don't need Sanity provisioning if you have already set up a Sanity project for your project, or if you plan to manually create and configure a project.

Visual Editor will handle provisioning a new Sanity project, along with the initial payload of models and content when creating a new project by duplicating a GitHub repository.

# Export content from Sanity

In most cases, projects that can be provisioned with Sanity as a content source have a Sanity project as the source of truth for duplicated projects.

The first step in preparing your project to be duplicated is to export the content schema and the initial site contents from your Sanity project.

Be sure to configure the export to include a compressed file of all appropriate schemas, documents, and assets. Commit the exported data file to your project. See here for an example.


Here is an export script we often use in Sanity projects. It generates a export.tar.gz file, like the one found in our Sanity starter.

# Import configuration

Once you've exported the content (and committed the data file), all that is left to do is add configuration for importing the content during the provisioning process.

The following properties should be added to an import property in your Visual Editor configuration file. All properties are required and are strings, unless otherwise noted.

  • contentFile: path relative to the root of the project, pointing to the file that contains the exported data. This should be compressed (typically something like export.tar.gz)
  • datasetEnvVar: a string representing the name of the environment variable that specifies the dataset to which the imported content should be added. This is not the name of the dataset, but the name of the environment variable.
  • deployGraphql: (boolean) set to true to ensure that Visual Editor deploys Sanity GraphQL API when creating the site.
  • deployStudio: (boolean) set to true to ensure that Visual Editor deploys Sanity Studio when creating the site.
  • projectIdEnvVar: a string representing the name of the environment variable that contains the Sanity project ID. This is not the project ID itself, but the name of the environment variable.
  • sanityStudioPath: path to the studio directory, relative to the root of the project.
  • tokenEnvVar: a string representing the name of the environment variable that contains the Sanity API access token. This is not the token itself, but the name of the environment variable.
  • type: set to sanity.
// stackbit.config.js
export default {
  contentSources: [
    new SanityContentSource({
      rootPath: __dirname,
      studioPath: path.join(__dirname, "studio"),
      studioUrl: "",
      projectId: process.env.SANITY_PROJECT_ID,
      token: process.env.SANITY_ACCESS_TOKEN,
      dataset: process.env.SANITY_DATASET || "production"
  mapModels: ({ models }) => {
    // page definitions and model decorations ...
  import: {
    contentFile: "sanity-export/export.tar.gz",
    datasetEnvVar: "SANITY_DATASET",
    deployGraphql: false,
    deployStudio: true,
    projectIdEnvVar: "SANITY_PROJECT_ID",
    sanityStudioPath: "studio",
    tokenEnvVar: "SANITY_ACCESS_TOKEN",
    type: "sanity"
  // other properties ...