Discussion on importing and publishing documents in Sanity, with some confusion around the "Publish" vs "Published" status.

28 replies
Last updated: Jun 8, 2021
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.

I think if you import them they’ll be published by default - unless they’re imported with the IDs having a
draft.*
prefix. Been a while since I’ve done it though so not 100% sure!
Thank you I'll look into what you are saying.
createOrReplace
also is there anything special i need to do to slug?
This is how I'm doing it `"slug": { "_type": "slug",
"_key": "nura-loop",
"title": "nura-loop",
"current": "nura-loop"
},
One more question I have I'll ask in the main channel since it's a bit different
Circling back to this, are the documents showing up as drafts in your studio or are they not being reflected in your frontend?
Circling back to this, are the documents showing up as drafts in your studio or are they not being reflected in your frontend?
Awww we don't have a frontend yet. They are showing up in the browser when you run
sanity start
and then look at localhost:3333, but they don't say 'published'. Sometimes they are green and say Publish (this I managed to have happen when I changed the slug code to the above (2 texts above this one). I will try to query them with graphql in a few hours. (it's early here I'm in Melbourne, Aus). And I just need to do a couple other things first.
It's not consistent though btw. I can't really figure out about why sometimes they are green with Publish and sometimes I have to click on Generate for the slug, even after doing the above code.
can you share some screen shots of what the different issues look like?
definitely. thanks for looking into this. I'll see if I can quickly do it now.
this is one that does not have a reference to anything else
{
  "_createdAt": "2021-06-07T09:59:21Z",
  "_id": "c9fa2207-99bc-4c57-9dbf-30181de81777",
  "_rev": "456kRT8Yu2eqQJttyIFwox",
  "_type": "quote",
  "_updatedAt": "2021-06-07T10:01:39Z",
  "author": "Sharon Stratsianis",
  "quote": "This is sound you can feel."
}

That is what I get when I use. your inspect tool
This is my data I am importing
[ {
"_id": "c9fa2207-99bc-4c57-9dbf-30181de81777",
"_type": "quote",
"author": "Sharon Stratsianis",
"quote": "This is sound you can feel.",
"_rev": "cmoitz-35m-soo-280-ijmk3acri",
"_updatedAt": "2021-06-07T08
:03:44.540Z" }
]
And lastly here is the schema
export default { name: 'quote',
title: 'Quote',
type: 'document',
hidden: true,
fields: [
{
name: 'author',
title: 'Author',
type: 'string',
validation: (Rule) => Rule.required()
},
{
name: 'quote',
title: 'Quote',
type: 'string',
validation: (Rule) => Rule.required()
}
]
}
It does have these 2 validation rules though. So potentially it has to do with the 'weak'/'strong' thing we were talking about.
Nah... I just took at the validation from our schema and reloaded and it still just says publish
and it's not green
Maybe they are "published" even though they say "Publish" in localhost:3333 and not "Published". Because I can see them in graphql deploys playground
Maybe they are "published" even though they say "Publish" in localhost:3333 and not "Published". Because I can see them in graphql deploys playground
When you are in Sanity Studio, imported data is showing up as "Publish" and grey. While if you enter the data yourself in Sanity Studio when you click on the green "Publish" button, it then greys out and says "Published"
Aww, my fault. I have solved my problem LOL. It was just confusing at first because when I was testing I would click on Publish and I would see it said "Published", but now after going through this I see that when you go back to that same document it says "Publish"
Aww, my fault. I have solved my problem LOL. It was just confusing at first because when I was testing I would click on Publish and I would see it said "Published", but now after going through this I see that when you go back to that same document it says "Publish"
Nice! Glad this one got sorted.

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?