👀 See Sanity in action: Watch product demo now →

Embedding Sanity Studio

Sanity Studio is a React application distributed as a single dependency on npm. The application bundle is also ESM-compatible, meaning that it can be imported directly into browsers as a dependency on an URL. In principle, this means you can embed the Studio in any web application, as long as you can control the routing to redirect all Studio URLs to the page it‘s hosted.

Adding the Studio as a dependency with npm

If you work on a project where node package manager is supported, you can add the Studio as a dependency using the following command:

npm install sanity@latest

Protip

If you plan to do Studio customization, then it can be useful to install @sanity/ui and @sanity/icons as well.

Accommodating the Studio

Gotcha

It's easy to forget, but you will always have to add the domain where you host your Studio to your project's CORS origins settings with authenticated requests enabled.

Styling

The Studio is built as a responsive web app. For the best editor experience, it should take the full width and height of the browser window. This means that you have to make sure that the DOM node that the Studio is mounted on is styled accordingly:

/* This assumes no margin or padding on #app's parent(s) */
#app {
  height: 100vh;
  max-height: 100dvh;
  overscroll-behavior: none;
  -webkit-font-smoothing: antialiased;
  overflow: auto;
}

/* Fix if you're using Tailwind.css */
*:not([data-ui='Popover__arrow']):not([data-ui='Tooltip__arrow']) > svg {
  display: inline;
}

Routing

If you embed the Studio inside of another app, it's likely you want to access it on a sub-route, e.g /studio or /admin. This means that you have to:

  1. Add this route to basePath in the Studio‘s configuration object
  2. Make sure that the app's routing redirects all the Studio's sub routes to the page/view where the Studio is mounted.

Frontend frameworks with file-based routing like Next.js, Nuxt.js, Svelte, Remix, Astro, and others, have conventions for “catch-all”, “rest”, or “splat” routes. These can be used to make sure that all routes under the Studio‘s basePath will be redirected and resolved by the Studio application.

If you are embedding the Studio outside of a framework like this, then you need to control the redirects on the server or hosting level. For example, if you host with Netlify, then you need to add a setting like this:

# netlify.toml
[[redirects]]
  from = "/admin/*"
  to = "/admin"
  status = 301
  force = true

Embedding Sanity Studio in a Next.js app

If you want to embed Sanity Studio in a Next.js project, then you can use the official next-sanity library. In addition to making embedding the studio easier, it also comes with tools for live preview and other useful things.

Rendering the Studio in non-React applications

If you aren't in a React project, then you can use the renderStudio function to mount it on a DOM node:

import { renderStudio,defineConfig } from "sanity";
import { deskTool } from "sanity/desk";
      
const config = defineConfig({
  plugins: [deskTool()],
  name: "Sanity Studio",
  projectId: "your-project-id",
  dataset: "production",
  schema: {
    types: [
      {
        type: "document",
        name: "post",
        title: "Post",
        fields: [
          {
            type: "string",
            name: "title",
            title: "Title"
          }
        ]
      }
    ]
  }
});

// This assumes that there is a <div id="app"></div> node in the HTML structure where this code is executed.
renderStudio(document.getElementById("app"), config);

Importing the Studio with URL imports

You can also import the Studio dependency using a URL import. This is possible because the Studio is ESM-ready. The following code will work in most modern browsers:

<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>
  <body>
    <div id="app"></div> 
    <script type="module">
      import { defineConfig, renderStudio } from "https://esm.sh/sanity?alias=lodash:lodash-es"
      import { deskTool } from "https://esm.sh/sanity/desk?alias=lodash:lodash-es"

      const config = defineConfig({
        plugins: [deskTool()],
        projectId: "your-project-id",
        dataset: "production",
        schema: {
          types: [
            {
              type: "document",
              name: "post",
              title: "Post",
              fields: [
                {
                  type: "string",
                  name: "title",
                  title: "Title"
                }
              ]
            }
          ]
        }
      });
      renderStudio(document.getElementById("app"), config);
    </script>
  </body>
</html>

Was this article helpful?