Watch a live product demo đź‘€ See how Sanity powers richer commerce experiences

Make a Field Read-Only After Publishing Once

By RD Pennell

Use a publishedOnce field to control other fields.


This schema is for an older version of Sanity Studio (v2), which is deprecated.

Learn how to migrate to the new Studio v3 →


  name: 'publishedOnce',
  type: 'boolean',
  hidden: true
  title: 'Read-only sometimes',
  name: 'readOnlySometimes',
  type: 'string',
  readOnly: ({ document }) => !document?.publishedOnce


"parts": [ 
    "implements": "part:@sanity/base/document-actions/resolver", 
    "path": "resolveDocumentActions.js" 


import {useState, useEffect} from 'react'
import {useDocumentOperation} from '@sanity/react-hooks'

export default function SetAndPublishAction(props) {
  const {patch, publish} = useDocumentOperation(, props.type)
  const [isPublishing, setIsPublishing] = useState(false)
  useEffect(() => {
    // if the isPublishing state was set to true and the draft has changed
    // to become `null` the document has been published
    if (isPublishing && !props.draft) {
  }, [props.draft])
  return {
    disabled: publish.disabled,
    label: isPublishing ? 'Publishing…' : 'Publish',
    onHandle: () => {
      // This will update the button text 
      // Set publishedAt to current date and time
      patch.execute([{set: {publishedOnce: true}}])
      // Perform the publish
      // Signal that the action is completed


import defaultResolve, { PublishAction } from 'part:@sanity/base/document-actions'
import SetAndPublishAction from './setAndPublishAction'

export default function resolveDocumentActions(props) {

  return defaultResolve(props)
    .map(Action =>
      Action === PublishAction ? SetAndPublishAction : Action

It can be pretty hard to use an existing field in your document to distinguish whether or not something has been published before. The simplest solution is to add a hidden publishedOnce boolean field that updates via a document action.


Other schemas by author