Can you bulk publish documents imported with sanity/client?

28 replies
Last updated: Nov 29, 2025
Hi there, I just want to confirm if I import lots of documents using sanity/client is there any way to publish them or we have to go into Sanity and update them individually?
AI Update

Good news! When you import documents using the Sanity client, they're automatically published by default - you don't need to manually publish them in the Studio unless they have a drafts. prefix in their _id.

Published vs Draft Documents

When importing documents, the publish state depends on the _id:

  • Without drafts. prefix (e.g., "_id": "abc-123") → Documents are published automatically
  • With drafts. prefix (e.g., "_id": "drafts.abc-123") → Documents remain as drafts

Publishing Imported Drafts Programmatically

If you did import documents as drafts (with the drafts. prefix), you can publish them programmatically without clicking through the Studio. Here are your options:

The simplest approach is to use createOrReplace to create published versions:

import {createClient} from '@sanity/client'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'your-dataset',
  token: 'your-token',
  apiVersion: '2024-01-01',
  useCdn: false
})

// Publish a draft by creating/replacing the published version
const draftId = 'drafts.abc-123'
const publishedId = draftId.replace('drafts.', '')

const draftDoc = await client.getDocument(draftId)

await client.createOrReplace({
  ...draftDoc,
  _id: publishedId
})

// Optionally delete the draft
await client.delete(draftId)

Option 2: Import Without Draft Prefix (Easiest)

The easiest approach is to import documents without the drafts. prefix in the first place:

const documents = [
  {
    _id: 'post-123', // No 'drafts.' prefix
    _type: 'post',
    title: 'My Post',
    // ... other fields
  }
]

documents.forEach(doc => {
  await client.createOrReplace(doc)
})

UI Behavior Note

There's a UI quirk that can be confusing: even for published documents, the Studio shows a "Publish" button (greyed out) rather than "Published" when you navigate back to a document. This is just a UI state - the document is still published. You can verify by querying without the previewDrafts perspective or checking if the document appears in your frontend.

As one community member discovered: "Maybe they are 'published' even though they say 'Publish' in localhost:3333 and not 'Published'. Because I can see them in graphql deploys playground"

Bulk Publishing All Drafts

For bulk operations, you can create a migration script:

npx sanity@latest migration create publishDrafts

Then implement the migration to publish all drafts:

import {defineMigration} from 'sanity/migrate'

export default defineMigration({
  title: 'Publish all draft documents',
  documentTypes: ['post'], // specify your types
  
  filter: '_id in path("drafts.**")',
  
  migrate: {
    document(doc, context) {
      // Create published version
      const publishedId = doc._id.replace('drafts.', '')
      return {
        ...doc,
        _id: publishedId
      }
    }
  }
})

Key Takeaway

Imported documents are published by default unless you explicitly add the drafts. prefix to their IDs. No manual Studio work required! If you need to publish drafts programmatically, use createOrReplace with the non-draft ID, or better yet, import without the draft prefix from the start.

Show original thread
28 replies

Sanity – Build the way you think, not the way your CMS thinks

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.

Was this answer helpful?