A Deep Dive into Sanity's Visual Editing and Presentation Tool: The developer view
Published: 2023-11-28 12:53:52

Hey there! Our colleagues over at [Sanity.io](http://sanity.io/), who are always at the forefront of structured content, have just rolled out two super cool features: **Visual Editing** and the **Presentation tool**. They announced these features at their online event on November 17th, 2023, and it was truly inspiring news in the headless CMS world!

Here at **FocusReactive**, we're like kids in a candy store when it comes to new tech goodies, especially if they can enhance our CMS and editing workflows. So, when Sanity dropped these new features, we were all over them, eager to see how they could make the content editing experience even better.

Being the tech enthusiasts we are, we couldn't resist putting together a demo project to test and show off Sanity's new features. We wanted to get a feel for how they work and see how handy they could be in real-world web development scenarios.
![Sanity's presentation tool demo by FocusReactive](https://cdn.sanity.io/images/vftxng62/production/7a53c5e84abb8b5e150459dcf0b49f6347cd35d2-1547x793.png)
Now, we've made this project available for all you curious folks out there at https://demo-visual-editing-sanity.vercel.app/. You will see overlays on mouse hover - this is only for demo of course.  But the real **magic** happens in the Sanity Studio. If you're as eager to dig in as we are and want to check out everything for yourself, don't hesitate to drop me a line for an **invite** to our demo Sanity Studio where we store all the content for this project.

## Table of Contents
- [Visual Editing and Presentation: An Overview](#visual-editing-and-presentation-an-overview)
- [The Presentation Tool: Ground-Breaking Features](#the-presentation-tool-ground-breaking-features)
- [The Magic of Overlays](#the-magic-of-overlays)
- [Setting Up the Presentation Tool](#setting-up-the-presentation-tool)
- [Configuring Document Locations](#configuring-document-locations)
- [Multiple Presentations: For Varied Purposes](#multiple-presentations-for-varied-purposes)
- [Conclusion](#conclusion)

## Visual Editing and Presentation: An Overview

The newly introduced **Visual Editing** feature provides an innovative approach to content editing in Sanity Studio. It's enabled by the **Presentation** tool which offers an interactive layout for live preview and visual editing within the studio. This tool complements the existing **Desk Structure** tool, providing editors with a more thorough understanding of content and its influence on the interface.
![Sanity's presentation tool interface](https://cdn.sanity.io/images/vftxng62/production/9580f0f1825ed388c79334ac478ffaab3f176724-2000x1458.png)
Contrary to the Structure tool, the primary emphasis here is on the page itself. This is highly beneficial as it allows for your content management to be streamlined, accommodating various content types and enhancing your content architecture. **Actual page** to be rendered by your application directly within the CMS. Furthermore, as will be demonstrated later, this presentation layer is smoothly integrated into numerous CMS actions, making it a primary component in your Sanity Studio.

On the right side, you will find **all documents** containing content for your previewing page. Selecting one of these documents will open a familiar editor form where you can interact with your document.

Significantly, any modifications made in the editor will be instantaneously **reflected** in the preview.

## The Presentation Tool: Ground-Breaking Features

The Presentation tool, your new best friend for visual editing and content authoring, comes packed with a plethora of awe-inspiring features. Nestled at the top panel of the tool, they're there to make your life as a content editor a touch more delightful and a whole lot easier, enabling real-time content updates and seamless collaboration. Let's embark on a journey through them:
![Sanity's presentation tool features](https://cdn.sanity.io/images/vftxng62/production/812b13129420956e4248ee84d49dc316b264244c-2000x1200.png)
### Mobile/Desktop View (1)

This feature allows you to flip between device views, giving you a clear understanding of how your content morphs to fit different screen sizes. In this digital age, it's absolutely vital to ensure both **mobile** and **desktop** versions are in tip-top shape - a key aspect of web development. Now, you, the editor, can effortlessly switch and monitor how the page appears on desktop and mobile devices. We've noticed there aren't any settings to specify a range of screen widths, but we're keeping our fingers crossed that this feature will be incorporated in upcoming versions.

### Published/Draft View (2)

Seamlessly transition between **published** and **draft** versions of your content, making the editing process a breeze. From my personal experience, this is the most sought-after feature, with numerous clients requesting its implementation on their projects. It's indeed crucial to have access to both - the version currently published on production and the one you're editing.

### Browse the Site and See Connected Documents (3)

This tool empowers you to view all documents linked to a specific page. For example, you can view the footer and header, which could be separate documents. We'll delve deeper into visual editing in subsequent sections. But for now, it's worth noting that the developers at Sanity were incredibly considerate and included this feature in the initial release. The fact that you can now **browse** your site directly through the Presentation window and as you navigate to a new page - you'll see all **related documents**. To avoid any confusion when clicking links, you can simply temporarily disable the overlay functionality.

## The Magic of Overlays

Remember those head-scratching moments when you couldn't find a specific piece of text in your CMS, even though it was staring right at you on the page? Well, those days are long gone! Now, all it takes is a simple click. When you hover your mouse over any piece of content - be it **plain text**, **formatted text**, or even an **image**, you'll see a box overlay pop up, introducing you to the world of visual and intuitive editing.
![Sanity visual editing overlays](https://cdn.sanity.io/images/vftxng62/production/1431676244d246ae0da52318b0bcbf051e27f49c-2000x1203.png)
This nifty overlay feature on preview pages is your new best friend in visual editing and content management. It's a super handy and efficient way for you to pick out a specific piece of content and then directly open the studio to edit that particular **field** in the document.
![Sanity visual editing overlays](https://cdn.sanity.io/images/vftxng62/production/c51b8542f24a09a1f8f2ab4475c1e07959200c5a-2000x1203.png)
And here's the cherry on top - it can even detect which document contains this content and which specific field in that document you need. It's like having your own personal content detective! Isn't it just magical, this new feature we've got, enhancing content management and content visualization?

This feature is a real lifesaver, especially when you're dealing with nested objects. In such cases, it can often feel like you're trying to find a needle in a haystack. But with the overlay feature, this task becomes a breeze, making your visual editing process and content management smoother and more efficient. So, go ahead and give it a try!

## Setting Up the Presentation Tool

Getting the Presentation tool up and running is a straightforward process. You need to:

1. Upgrade your Sanity Studio version to the latest
2. `import { presentationTool } from 'sanity/presentation';`
3. Insert `presentationTool` to plugins in your Sanity config
4. Connect your [frontend](https://github.com/focusreactive/Demo-VisualEditing-Sanity) to Sanity Headless CMS

```jsx
// sanity.config.ts

import { defineConfig } from 'sanity';
import { deskTool } from 'sanity/desk';
import { presentationTool } from 'sanity/presentation';

export default defineConfig({
    // ... your config,

    plugins: [
    presentationTool({
      previewUrl: {
        origin: typeof location === 'undefined' ? '<http://localhost:3000>' : location.origin,
        draftMode: {
          enable: '/api/draft',
        },
      },
      locate,
    }),
    deskTool({
      structure: deskStructure,
      defaultDocumentNode,
    }),
    // ... other plugins
  ],
});
```
- `presentationTool({ ... })`: This is the configuration object for the Presentation tool. Inside this object, the following properties are defined:
- `previewUrl`: This property defines the **preview** URL for the frontend application. It checks if the location is defined and sets the origin accordingly. It also enables **draft** mode by specifying the endpoint for draft content.
- `locate`: This property specifies the location of the documents used in the presentation. It is a function that takes the document ID and type and returns an array of objects containing the title and URL of the documents.

In order to enable previewing pages in a draft mode you have to provide this endpoint in your NextJS project integrated with Sanity. This is how this file looks in our project:

```jsx
// app/api/draft/route.ts

import { validatePreviewUrl } from '@sanity/preview-url-secret';
import { draftMode } from 'next/headers';
import { redirect } from 'next/navigation';
import { client } from '@/sanity/client';
import { sanityReadToken } from '@/environment';

const clientWithToken = client.withConfig({ token: sanityReadToken });

export async function GET(request: Request) {
  const { isValid, redirectTo = '/' } = await validatePreviewUrl(clientWithToken, request.url);
  if (!isValid) {
    return new Response('Invalid secret', { status: 401 });
  }

  draftMode().enable();

  redirect(redirectTo);
}
```

Here is an example of how to enable preview and draft mode for [Sanity](http://sanity.io/) using the Presentation tool. The `GET` function handles api requests to that endpoint. Inside the `GET` function, it performs the following steps:

1. It validates the preview URL using the `validatePreviewUrl` function from `@sanity/preview-url-secret` module. If the URL is not valid, it returns a response with a status of 401 (Unauthorized).
2. It enables draft mode using the `draftMode().enable()` function from the `next/headers` module.
3. It redirects the user to the specified `redirectTo` URL using the `redirect` function from the `next/navigation` module.

This code snippet is essential for enabling preview and draft mode in a Next.js project when integrating with Sanity for efficient content management.

## Configuring Document Locations

The Presentation tool introduces the concept of **Document Locations**. This feature shows where a document is used in different parts of your interface, helping editors understand the implications of a single document change.

The basic locate example can be found in the Sanity [documentation](https://www.sanity.io/docs/configuring-the-presentation-tool#a1dcd7c21042). However, I will show you what we finally achieved in our project. We simply imported the necessary modules and set up the necessary configurations.

```tsx
import { DocumentLocationResolver } from "sanity/presentation";
import { map } from "rxjs";

// Pass 'context' as the second argument
export const locate: DocumentLocationResolver = (params, context) => {
  // Set up locations for post documents
  if (params.type === "dynamicPage") {
    // Subscribe to the latest slug and title
    const doc$ = context.documentStore.listenQuery(
      `*[_id == $id][0]{slug,documentTitle}`,
      params,
      { perspective: "previewDrafts" } // returns a draft article if it exists
    );
    // Return a streaming list of locations
    return doc$.pipe(
      map((doc) => {
        // If the document doesn't exist or have a slug, return null
        if (!doc || !doc.slug?.current) {
          return null;
        }

        if (doc?.slug.current === "/") {
          return {
            locations: [
              {
                title: "Home Page",
                href: "/",
              },
            ],
          };
        }

        return {
          locations: [
            {
              title: doc?.documentTitle || "Untitled",
              href: `/${doc?.slug.current}`,
            },
          ],
        };
      })
    );
  }

  return null;
};
```

Well, it wasn't easy to set them up from the first attempt. But the result was more than exciting! After adding that code, a new dropdown appeared in the form editor.
![Sanity Studio 'used on page' references](https://cdn.sanity.io/images/vftxng62/production/b16c13ea5a7ca4a27548bf25a739ab70843de0b8-2000x1206.png)
From there, I can simply select any of the pages where the visual editing content is presented. With just one click, I can jump to the content management tool, observe the page, and preview all the changes I made.

## Multiple Presentations: For Varied Purposes

You have the freedom to improve your studio by incorporating **different** Presentation tools and using them for various content types. This enables you to streamline your content management workflow and meet the specific requirements of different frontends. By creating separate Presentations for each frontend, you can personalize and customize your content to provide a smooth and personalized user experience. This single source of truth approach is beneficial for all content creators.

## What is the underlying technology?

Several new technologies and methods were utilized to achieve the final result. A comprehensive explanation of these technologies would require a separate article, so we will briefly discuss the main points of how it operates here.

### Content Source Maps

This technology enhances the standard response from Headless CMS when content is requested. In this scenario, we receive **extra** data along with the content itself, providing information on how the content is **mapped** to the fields and paths in the document schema from which it was obtained. This is required to later open these fields in Sanity Studio for editing. Sanity has developed a complete [specification](https://github.com/sanity-io/content-source-maps) for the Content Source Maps format. It would be beneficial if this could be adopted by other Headless CMSs.

### Steganographic content appending

Having Content Source Maps on the front end is insufficient. It is necessary to link that data to specific content pieces that eventually appear on the page. Here, the library developed by Vercel in collaboration with Sanity, [@vercel/stega](https://www.npmjs.com/package/@vercel/stega), comes into play. It allows us to add to the standard text data containing page content, browser-unreadable characters that **encode** the needed information. Hence, every text piece or picture containing an alt, carries information about **where this data is stored** in the CMS. Alt tags are always added to images, correct?

### Overlays

Overlays consist of a small [library](https://github.com/sanity-io/visual-editing/blob/main/packages/overlays/README.md) that identifies all elements on a page **containing** steganographic inserts and renders them interactive. Hovering over such an element will display a pop-up rectangle suggesting **interaction** with this element. If this occurs on a separate page, such as a preview branch embedded in Vercel, clicking on this element will open Sanity Studio in a new tab, and the necessary document and the corresponding inserts within this document will be immediately accessible. If you are already within Sanity Studio - in the Presentation tool, clicking on the element will open the editor on the right side.

### Sanity Studio API

This is the final component that enables visual editing to fully function. Here we have two options. The first is not an API, but a URL **format** within Sanity Studio that allows the generation of links that open not just a specific document, but also a **field** within that document. 

Here's an example of such a URL: https://mvp-nextjs-sanity-git-feature-live-editing-focusreactive.vercel.app/admin/desk/dynamicPage;29d1e996-7d16-4fb7-94fa-ecb6674cf3e3,path=content[0].title. The key thing here is the **path** parameter, which defines the path to the field to be focused on. This is actually a simplified example, Sanity provides considerable flexibility, allowing for opening **multiple** panels in split view, specifying **different** views to open instead of a standard form, and more.

This is extremely useful for arranging easy access to data within a dataset. The second is **internal routing**, which allows the same thing, but within Sanity Studio.

Observe how these libraries are structured. Each has its own interaction interface. Each performs only its own necessary part of the task and is not dependent on other libraries and technologies. This provides a vast potential for expansion and redefinition. This could be the start of an interesting **new trend**, transforming Headless CMS into a mature and mainstream website building solution.

It is hoped that these technologies will gain popularity among other CMS and we will soon witness new impressive solutions in our field.

## Conclusion

Sanity has always been a superstar in the CMS world, thanks to its flexibility and extensibility. I'm a big fan of how they introduce new features as separate **customizable** blocks - it's a hit with me and I know a lot of developers feel the same way. Plus, it's super cool that everything works straight **out of the box**, no complicated customization needed in the basic version.
![Custom Sanity visual editing plugin by FocusReactive](https://cdn.sanity.io/images/vftxng62/production/9647efe6eccfbe09f18e4875dd42cd33ff5fc1e2-2000x1186.png)
What's got me really excited is that the new features we're talking about here are a big leap forward in making life easier for **content creators**. It's a fantastic new addition to the Headless CMSs that offer visual editing and live previews. We're a curious bunch at FocusReactive, always keen to explore this area. We've been keeping an eye on and playing around with similar features in Sanity Studio for quite some time. We're firm believers that creating a user-friendly environment for content development is just as important as being able to customize the CMS itself.

If you're on the same page, or if you need some expert advice on Headless CMS and the latest web technologies, don't be shy - get in touch [with us](https://focusreactive.com/#mail-us). I'm buzzing for you to try out these Visual Editing and Presentation tools. Trust me, they're going to take your content creation to a whole new level and help you create content that really stands out. We really value your thoughts and would love to hear what you think. Feel free to drop me a line on [Twitter](https://twitter.com/UsulPro) or the Sanity Community Slack at **@usulpro**. Can't wait to hear from you!