
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeYes! You can differentiate between an unpublished document and a published draft using perspectives and document IDs.
The key distinction is:
drafts.post-123 (no published version exists)post-123 (published) and drafts.post-123 (draft with changes)The most straightforward approach is to use the published perspective when querying. This returns only published documents:
const client = createClient({
// ... config
perspective: 'published'
})With this perspective:
You can also check programmatically by looking at the _id:
_id starts with drafts., it's a draft versiondrafts. prefix, it's a published document with draft changesdrafts.{id} exists (no corresponding published version), it's unpublishedTo find only unpublished documents (never been published):
*[_id in path("drafts.**") && count(*[^._id == "drafts." + _id]) == 0]To find published documents with draft changes:
*[count(*[_id in [^._id, "drafts." + ^._id]]) > 1]To exclude all drafts from production queries:
*[_type == 'post' && !(_id in path("drafts.**"))]The previewDrafts perspective is also useful for preview environments - it automatically prioritizes drafts over published versions when both exist, which is perfect for showing the latest changes before they go live.
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store