DEV Community

Cover image for Sanity Studio v2 to v3 upgrade (and on to v6): what breaks and how to fix it
Nayan Kyada
Nayan Kyada

Posted on Originally published at nayankyada.com

Sanity Studio v2 to v3 upgrade (and on to v6): what breaks and how to fix it

If your team is still on Sanity Studio v2, you are running a legacy Studio that Sanity no longer develops. The Sanity Studio v2 to v3 upgrade is the hard part — the configuration model, plugin API, and custom input system were all rewritten — but in 2026 you should not stop at v3. The current major version is v6, and once you have done the v3 rewrite, the remaining steps are small. This post covers what breaks, what the risk of waiting is, how to approach the migration, and what to ask a developer before hiring someone to do it.

Why v2 is no longer safe to leave alone

Studio v2 no longer receives updates. It is a deployed web app — self-hosted or at yourproject.sanity.studio — built on an older React version and older build tooling, and those dependencies keep accumulating known vulnerabilities with nobody patching them. Your content is stored in Sanity's cloud and is not directly at risk, but the Studio is an authenticated surface: a vulnerability that allows script injection in the editor UI could let an attacker act as a logged-in editor.

Beyond security, everything new in Sanity is built for the modern Studio. AI Assist, the Presentation tool for live preview, Sanity TypeGen, auto-updating Studio deployments, and the improved search all require v3 or later. Every month on v2 is a month your editors go without them.

What actually breaks in the v2 to v3 upgrade

The v2 to v3 jump is a ground-up rewrite of the Studio. The Content Lake API did not change — your GROQ queries, your dataset, and your documents are untouched. What changed is everything from the configuration layer up.

Configuration format. v2 used a sanity.json manifest and a plugin-based folder structure. The modern Studio uses a single sanity.config.ts file with a defineConfig() call. There is no automatic converter from one to the other.

Desk structure. The v2 desk tool is now the Structure tool: structureTool() imported from sanity/structure. The structure builder (S.list(), S.documentTypeList(), .child()) will look familiar, but you register it through the plugin's structure option instead of a parts override, and any custom panes need testing. If you have a complex desk, my notes on custom ordering and grouping in Structure Builder apply directly.

Plugins. Every v2 plugin needs a modern equivalent. Common ones like Vision (@sanity/vision) have been rebuilt, but package names, import paths, and configuration options changed, and some community plugins were never ported. Audit your plugin list early — an abandoned plugin can be the biggest unknown in the estimate.

Custom inputs. This is the most common source of pain. v2 inputs used PatchEvent and withDocument from the old form builder parts. Modern inputs are plain React components that receive props, call props.onChange(set(value)) or unset(), read other fields with useFormValue, and can wrap the default input with props.renderDefault(props). Every custom input is a rewrite, not a re-import.

Parts system gone. v2's parts system for overriding Studio internals no longer exists. Logos, navbar tweaks, and custom document views move to explicit options and component overrides in defineConfig().

Schema helpers. The sanity package exports defineType, defineField, and defineArrayMember for type-safe schemas. Plain object schemas still work, so you can convert gradually — but it is worth doing during the rewrite, because TypeGen and editor autocomplete both benefit.

Don't stop at v3: what changes on the way to v6

Once your Studio runs on the v3 configuration model, the later majors are mostly about runtime requirements. If you bootstrap the new Studio with npm create sanity@latest, you start on the current version and skip these steps entirely. If you port an existing v3 codebase, here is what each major adds:

Major What changes Typical effort
v4 Node.js 20.19+ (or 22.12+) to run the CLI Minutes, if your Node.js is current
v5 React 19.2.2+ required; TypeGen renames result types for snake_case query names Hours — check custom inputs and plugins for React 19 compatibility
v6 Node.js 22.12+; React strict mode on in development; auth.providers arrays replace the defaults; search defaults to the groq2024 strategy; build moves to Vite 8 Hours, mostly testing custom inputs under strict mode

Your schemas, plugin configuration shape, and content APIs stay the same through all three. Sanity publishes a migration guide for each major, and the upgrade overview links them in order.

Upgrade path by Studio size

The effort scales with how much custom code sits on top of the default Studio.

Studio profile Custom inputs Custom structure Effort estimate
Default schemas, stock plugins 0 None 2–4 hours
Several document types, 1–2 custom inputs 1–3 Basic S.list() 1–2 days
Large schema set, multiple custom inputs, branded UI 4+ Complex nested structure 3–5 days
Multi-workspace, custom tools, unported plugins Many Multiple workspaces and tool tabs 1–2 weeks

Those estimates assume someone who has done the migration before, and they include landing on v6 rather than v3. If a developer is reading the migration guides for the first time on your project, add about half again.

The upgrade sequence that works

Do not upgrade in place on the Studio your editors use every day. This sequence keeps v2 working until the new Studio has proven itself:

  1. Branch the Studio codebase. Keep v2 deployed for editors while you work on a separate branch.
  2. Bootstrap a clean, current Studio. Run npm create sanity@latest in a scratch folder so you start on the latest major, then port your schemas into it one document type at a time.
  3. Port schemas first and check them with Vision. Get every schema loading and query real documents before touching any UI customisation. Schemas are the lowest-risk layer — and a good moment to prune document types nobody uses.
  4. Rebuild the structure. Recreate your desk with structureTool() and test each list and nested pane.
  5. Rewrite custom inputs one at a time. Each is a self-contained rewrite; test it under React strict mode, which v6 turns on in development.
  6. Replace parts overrides. Move logo, navbar, and document view customisations into defineConfig().
  7. Let editors use it before cutover. Deploy the new Studio to a separate URL against your production dataset — the content API is the same, so both Studios can run side by side — and give your content team a week or two of real use before switching the main URL.
// sanity.config.ts — modern Studio shape (v3 and later, including v6)
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
import { schemaTypes } from './schemaTypes'

export default defineConfig({
  name: 'default',
  title: 'My Studio',
  projectId: 'your-project-id',
  dataset: 'production',
  plugins: [
    structureTool(), // replaces the v2 desk tool
    visionTool(),
  ],
  schema: {
    types: schemaTypes,
  },
})
Enter fullscreen mode Exit fullscreen mode

The v2 equivalent was spread across sanity.json, a desk structure file, and parts declarations. One typed file is far easier to maintain.

What a rewritten custom input looks like

// schemaTypes/inputs/SlugPreviewInput.tsx — modern custom input pattern
import { useFormValue, type StringInputProps } from 'sanity'

export function SlugPreviewInput(props: StringInputProps) {
  const title = useFormValue(['title']) as string | undefined

  return (
    <div>
      {props.renderDefault(props)}
      {title && (
        <p style={{ fontSize: 12, color: '#888', marginTop: 4 }}>
          Slug preview: {title.toLowerCase().replace(/\s+/g, '-')}
        </p>
      )}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

The v2 version of this input would have reached for PatchEvent and a withDocument wrapper, neither of which exists in the modern Studio. For a fuller example, see how I build a custom input with a colour picker.

What to ask a developer before hiring

If you are scoping this work with a freelancer or agency, these questions separate someone who has done it from someone learning on your budget:

  • Will you land us on the current major version, or stop at v3 — and why?
  • Can you show me a modern sanity.config.ts from a project you have shipped?
  • How will you handle the custom input rewrite, and how will you test it?
  • Which of our plugins have no modern equivalent, and what is the plan for each?
  • Will editors use the new Studio against production content before cutover, and is v2 kept as a fallback?

A developer who has done this before will answer all five without hedging — especially the plugin question and the rollback plan.

The cost of another six months on v2

Every month on v2 is another month of unpatched dependencies, another month without AI Assist, Presentation, or TypeGen, and more schema debt to untangle later. The upgrade is not trivial, but it is bounded work — usually days, not months, even for a Studio with custom inputs and a structured desk.

This is work I do for teams on Sanity, from a quick performance and Sanity audit that maps your Studio and plugins to a full fixed-price migration. If you have a v2 Studio — or inherited one and are not sure what state it is in — that audit is the fastest way to get a real estimate.

Top comments (0)