Skip to main content

Empower Sanity Content Preview With Really Powerful New Perspectives Feature

The quickest explanation of Sanity's Perspectives feature and the understanding of why we were so badly waiting for it

Empower Sanity Content Preview With Really Powerful New Perspectives Feature

With the rapid evolution of Content Management Systems, the industry has witnessed an increasing demand for headless CMS, such as Sanity. As a leading headless CMS, Sanity has gained a reputation for its flexible and robust features.

However, Sanity did not include certain essential features by default. We had to incorporate them into our projects. One of the most requested features was the ability to automatically select the correct version of a document (draft or published) - whether it was fetched from the production or the preview environment.

Let's take a closer look at that question from the viewpoint of a developer and discover the problem that this new feature can address, as well as how we can incorporate Sanity's Perspectives into our projects.

So what is the problem with picking the draft or published version of documents?

Before answering this, let's state some basic points usually present in our projects:

Preview Environment

To begin with, let's agree on the significance of having a preview environment to establish a dependable and convenient publishing flow. The ability for the Content Editor to preview how a page will appear before it is published to production, rather than afterward, is crucial.

In the preview environment, which document version should we display? Clearly, it should be the draft version. Our goal is to create a page using the most recent content that the editor was working on. Therefore, in this scenario, we should choose the draft document even if there is also a published version available.

Document lists

A pretty common scenario is when we have a list of documents of a certain type and we use all of them to generate a single page that contains information from all of them. For example, it could be a main blog page that shows previews of all available articles.

In most situations, these documents may be at various stages in the publishing flow. This implies that we can anticipate the following scenarios:

  • A document has just been created and has not yet been published. In this case, it will only have a draft version.
  • A document has been published and has never undergone any edits since then. Such a document only exists in its published form.
  • A document was already published but has also undergone subsequent edits, resulting in unpublished changes. This particular document will have both draft and published versions.

So our task is to select draft versions when documents have them and published ones if it's the only version that a document has.

References

Almost every content model includes references to other documents. For instance, an article may reference its author. In Sanity, a reference is a field that stores the ID of the document being referred to. Sanity Studio works in a way that it always puts the ID of the published version of the referenced document. Even if it was never actually published.

So as developers, we have to take a published ID, construct the draft ID base on it, and check if a draft version exists.

Same code for all environments

Furthermore, it is quite evident that our preference lies in avoiding the use of distinct logic for published and preview environments. Instead, we strive to have consistent and dependable code deployed universally. And the only way to modify its behavior is solely through the provision of specific environment variables.

With these statements in hand, we need to implement a logic of how we pick document versions on our environments. Imagine a scenario where we only have two environments at our disposal - production and preview. So in this case we can specify rules based on the following tables:

Table 1. For preview env

draft existpublished existshow
yesyesdraft
yesnodraft
noyespublished

Table 2. For production env

draft existpublished existshow
yesyespublished
yesnonothing
noyespublished

Where should we incorporate this logic? It's not ideal to have it in the code of the frontend application. We would end up retrieving more documents than necessary, and we would need to remember to include this postprocessing step every time we fetch data. In the best case you should be able to move this logic into a build step if you utilize the Static Site Generation approach like NextJS offers. But even this wouldn't solve all the problems.

What about implementing this logic right in the GROQ queries? Yes, it's possible and we can implement it utilizing relatively the same pattern in each query. But it causes queries to become too massive and heavily maintainable. Especially if we need to support references. With the last ones, you have to write giant GROQ constructions to resolve the referred document in the correct version.

I'm thrilled to share that we now have a fantastic built-in Sanity solution for solving this, so I won't delve into the details of using GROQ queries. However, if you're curious about the historical perspective, there's an article available that provides a comprehensive guide on how to master GROQ queries.

I just mention here that when you query documents this way:


* [_type == 'post']

you will typically receive published and draft document versions all together in a plain array. So you can't say what to use without an additional processing step where you compare published and draft IDs. The only way we could solve it in a simple way with GROQ functionality is to exclude draft versions at all on the production environment:


* [_type == 'post' & !(_id in path('drafts.**'))]

But this works only for the production environment and we can't reuse it in the preview mode even if we change the filter to the opposite (_id in path('drafts.**')). That's all because the logic for the preview is much more complicated.

Sanity's perspectives come into a scene

Obviously, this post is about how to have a simple and confident preview setup without pain and struggle. Let's see how the game was changed with the new Sanity's Perspectives feature.

Let's start with how to enable perspectives when you fetching documents. When you prepare a Sanity client in your application (for example in the NextJS SSG app), you can now specify the additional parameter perspective. It accepts raw, previewDrafts, and published values.


// Example JS/TS client configuration
import {createClient} from '@sanity/client'

const client = createClient({
...config,
useCdn: false, // must be false when using 'previewDrafts'
perspective: 'previewDrafts', // 'raw' | 'previewDrafts' | 'published'
})

Additionally, you can play with perspectives in the GROQ playground which comes with the Sanity Studio.

sanity vision

What benefits give us the perspectives feature? Let's start with the same query for getting all blog posts. Let's say we are previewing a main blog page where we want to check how new and edited articles appear.


* [_type == 'post']

With perspective set to raw we still have the mixed published and draft list of documents. Magic happens when we set perspective to previewDrafts. Now we get a list of documents that contain a draft version of a document if it exists and a published version if for that document there are no draft versions. Exactly as we specified in Table 1.

But the miracles are just beginning. Let's say we also need to output author information under each blog preview. So our query could look like this:


* [_type == 'post'] {

...,

author->

}

Once again, we will be provided with the appropriate versions of the author's documents - drafts if they exist or published ones if not. Isn't it amazing? You should definitely check out the article I mentioned earlier and compare it to the approaches we had to use just a few months ago!

What is nice about this approach - is that for production we can have exactly the same queries and specify published for perspective.

Voila, what we've been waiting for! Our queries have been simplified, making it easy for us to develop them right in the Sanity Studio. With all the complex logic of selecting hidden under the hood of the Sanity Content Lake, we can confidently say that Sanity provides the exciting ability to work in full preview mode. No more guessing or second-guessing - now we can see exactly how our content will look and feel before it goes live. Say goodbye to those last-minute changes and hello to a smoother, more efficient workflow. It's time to get excited about seamless content creation with Sanity!

Conclusion

Sanity's new Perspectives feature offers an elegant solution to the discussed problem by automating the selection of documents, regardless of whether they are in draft or published form.

This opens up a world of possibilities for content creators, developers, and marketers alike. Not only does it make the content creation process smoother and more efficient, but it also eliminates the guesswork usually associated with previewing drafts and other unpublished content. With Sanity's Perspectives feature, you can rest assured that your content will look exactly as intended before it goes live. So why wait? Get creative and take control of your content workflow with Sanity's Perspectives feature!

If you need help with your current project or are having trouble beginning an exhilarating new project using a Headless CMS, don't hesitate to contact us. We offer our expertise and experience in cutting-edge web development.

WRITTEN BY

Oleg Proskurin

Oleg Proskurin

TechLead at FocusReactive