Guide

Getting started with initial values for new documents

Create the initial value for a new document in Sanity Studio. This guide takes you through simple and advanced use cases.

Knut Melvær

Knut runs developer relations at Sanity.io.

Sometimes you want to have a specific value in a new document. In the Sanity Studio, this is called "initial value". This guide covers how to get started with configuring initial values for a document type, from some very basic settings, to more advanced using external asynchronous APIs. It's also possible to create different initial value templates for the same document type, which you can learn more about here.

Gotcha

The initial value feature work only on documents created in the studio. If you create documents programmatically, you'll have to set up the same functionality in your script/application.

You configure initial values by adding the initialValue property to a document type. It can take a simple object with the field names as keys, and static values. It can also take a function or a promise.

Editor Experience

Setting the initial values for a document type works best when it's something editors shouldn't have to think about or explicitly wants. You should assume that editors may forget to look them over before publishing. Don't use an initial value as placeholder text, it's probably better to use the field’s description property.

Setting a “featured” boolean field to false

A common use case is setting a boolean field to either true or false as a new document initial value. The boolean is initially null, meaning that the editor hasn't interacted with it. Let's say we have a simple category type, and some of these can be featured.

export default {
  name: 'category',
  type: 'document',
  title: 'Category',
  fields: [
    {
      name: 'name',
      type: 'string',
      title: 'Category name'
    },
    {
      name: 'featured',
      type: 'boolean',
      title: 'Featured category'
    }
  ]
}

To set the featured field to false for new documents, add the initialValue property on the document type and set the field and value inside of it like this:

export default {
  name: 'category',
  type: 'document',
  title: 'Category',
initialValue: {
featured: false
},
fields: [ { name: 'name', type: 'string', title: 'Category name' }, { name: 'featured', type: 'boolean', title: 'Featured category' } ] }

If you have the studio running on local, you can now save your changes and test out if it works by creating a new category document. The featured field should now be set to the false position.

The featured boolean is set to false

Setting an initial date to the current time

Another common case for initial values is to automatically set a datetime field to the current time when creating a new document, keeping the possibility of setting the date manually to schedule it. Since we now don't just have static values, but need to run the new Date().toISOString() function, we have to also return a function to the initialValue property. In this example, we use an anonymous arrow function, but you can also use the function() {} syntax if you prefer that:

export default {
  name: 'post',
  type: 'document',
  title: 'Blog post',
initialValue: () => ({
publishedAt: new Date().toISOString()
}),
fields: [ { name: 'title', type: 'string', title: 'Title' }, { name: 'slug', type: 'slug', title: 'Slug' }, { name: 'publishedAt', type: 'datetime', title: 'Published at' }, // ... ] }
The publishedAt field with the current time preset on a new document

Setting an initial author reference

Often you have reference fields in your document types. In the blog starters on sanity.io/create the posts are set up with an array (because there always comes a time where you need more than one) of authors, which are references to the author document. Let's say you are mostly the only author, and it makes sense to have that as the initial value for a new blog post.

The way to do this is to set the author reference object as the initial value in an array on the post document. To find this data structure, you can open an existing blog post with the author that you want, go into the inspect view (the menu in the top right corner of the document form, or ctrl + alt + i) and copy the data from the JSON view.

Selecting the authors array in the JSON inspector

Protip

You may notice that there is a _key property in the array object. Sanity Studio uses this for the real-time editing. If you don't add the _key the Studio will prompt you to add it afterwards.

Now you can paste this into the initialValue property. Here we kept the publishedAt configuration from the last section.

export default {
  name: 'post',
  type: 'document',
  title: 'Blog post',
  initialValue: () => ({
    publishedAt: new Date().toISOString(),
authors: [
{
_type: "authorReference",
author: {
_ref: "1b1c7451-c976-48fd-b416-73bf5a356f10",
_type: "reference"
}
}
]
}),
fields: [ { name: 'title', type: 'string', title: 'Title' }, { name: 'slug', type: 'slug', title: 'Slug' }, { name: 'publishedAt', type: 'datetime', title: 'Published at' }, { name: 'authors', type: 'array', title: 'Authors', of: [ { type: 'authorReference' } ] } // ... ] }
The initial author reference in the authors array

Setting the initial value dynamically from a query

Let's say you have authors with different responsibilities expressed as strings in a responsibilities array field on the author document type, which can be the strings marketing, legal, or business. The content model looks something like this:

export default {
 name: 'author',
 type: 'document',
 title: 'Author',
 fields: [
   {
     name: 'name',
     type: 'string',
     title: 'Author name'
    },
    {
      name: 'responsibilities',
      type: 'array',
      title: 'Responsbilities',
      of: [{type: 'string' }],
      options: {
        list: [
          'marketing',
          'legal',
          'business'
        ]
      }
    }
  ]
}

Now you want to set all the authors with the marketing responsibility as the initial value for the authors array for new blog posts. You could take the approach in the last section and find all the _ids for the documents and put them in as the initial value, but it wouldn't work if you shifted the responsibilities around, or added new.

What's super cool (and powerful) with the initialValue property is that you can return an asynchronous function, i.e., a promise, which means you can run queries inside of it to construct your initial value. In this example, we import the built-in client that comes with the studio and use it to run a GROQ query that finds these authors, then project the correct data structure.

import client from 'part:@sanity/base/client'
export default { name: 'post', type: 'document', title: 'Blog post', initialValue: async () => ({ publishedAt: new Date().toISOString(),
authors: await client.fetch(` *[_type == "author" && "marketing" in responsbilities]{ "_type": "authorReference", "author": { "_type": "reference", "_ref": _id } } `)
}),
fields: [
{
name: 'title',
type: 'string',
title: 'Title'
},
{
name: 'slug',
type: 'slug', title: 'Slug' }, { name: 'publishedAt', type: 'datetime', title: 'Published at' }, { name: 'authors', type: 'array', title: 'Authors', of: [ { type: 'authorReference' } ] } // ... ] }

Here we're using the Sanity client to run queries on the Studio’s connected dataset, but you could of course run any async function here, including fetch to an external API endpoint (to get the current weather or something).

Gotcha

If you plan to query external API endpoints, you might hit problems with CORS since the request comes from your browser. Be careful with how you operate with secrets and tokens. If you put them into the schema code, they might be exposed.

Setting the browser’s current geolocation as the initial value

Since the Studio runs in the browser, it can also use its APIs to set some initial values. Let's say you want to record the geolocation of where a document was created (be mindful of privacy issues). We can use the navigator.geolocation API in the browser to get the position.

Running this code makes the Studio prompt the editor for permission to access the location. And for this to work, the editor has to allow the Studio getting the position. We also need to wrap the getCurrentPosition code in a promise to make it work with initialValue.

const getPosition = (options) => {
  if (navigator.geolocation) {
    return new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(resolve, reject, options)
    })
  }
}

export default {
  name: 'post',
  type: 'document',
  title: 'Blog Post',
  initialValue: async () => ({
    postedAt: await getPosition()
      .then(({coords}) => {
        const {latitude, longitude, altitude} = coords
        return {
          _type: 'geopoint',
          lat: latitude,
          lng: longitude,
          alt: altitude || undefined
        }
      })
      .catch(() => undefined)
  }),
  fields: [
    {
      name: 'title',
      type: 'string',
      title: 'Title',
      description: 'Titles should be catchy, descriptive, and not too long'
    },
    {
      name: 'postedAt',
      type: 'geopoint'
      title: 'Posted at location'
    }
  ]
}
A new blog post with geolocation coordinates

Protip

Install one of the maps input components (Mapbox or Google Maps) to get a nicer interface for location data.

Next steps…

We have now learned different ways of setting initial values for a document type. The next step is to explore how you can create templates for initial values to make it possible for editors to select between different sets of initial values for the same document type. Check out the documentation for more on this topic.