Sanity CMS Minimum Viable Build

Katie - Jul 9 '20 - - Dev Community

Now I’ll set up Sanity CMS instead of markdown as a data source for the “Hello World” in my Gatsby-generated index.html.

<html>
    <head></head>
    <body>
        <div>Hello World</div>
    </body>
</html>

The goal of this tutorial is to make a lovely CMS that looks like this for a content author:

Screenshot

And helps me generates output like this that I can plug into Gatsby:

Screenshot

{
    "message":"Hello World",
    "slug":{
        "_type":"slug",
        "current":"/"
    },
    "template":"xyzzy"
}


Prerequisites

  1. Sign up for a Sanity.io account at https://accounts.sanity.io/signup/.
  2. Install the Node.js JavaScript execution environment (here’s a Windows tutorial), being sure to include the npm package manager, on your computer.
    • Make sure that your “path” environment variable for your operating system ends up configured so that when you execute node -v and npm -v from a command line interface, they both work (that is, you get a message back saying what version of Node or NPM you’re on).
    • This is harder than it sounds if you’re new to installing command-line tools on your computer. Be patient.
  3. Install the Sanity CLI command-line tool using npm.
    • Make sure that your “path” environment variable for your operating system ends up configured so that when you execute sanity -v, you get a message back saying what version of “@sanity/cli” you’re on.
    • Did it take days to get this to work? Have a cupcake – you’ve earned it! It’ll be easier from here on out.
  4. Optional: Install a tool on your computer capable of helping you make HTTP requests, such as Postman, Curl, or a general-purpose programming language with a request-making library (such as Python), and learn how to use it to make a basic GET-typed HTTP request with customized headers.

Navigate the command line to an appropriate folder

I decided I wanted to work out of a folder on my hard drive called C:\example\mysite_sanity.

Therefore, after I brought up my operating system’s command prompt (I opened it with windows-key , cmd, and enter on Windows), I typed the following at the prompt:

cd C:\example\mysite_sanity


Log the Sanity CLI into Sanity.io

Once there, I type the following into my command line:

sanity login

Screenshot

I tap the down arrow on my keyboard until E-mail / password is highlighted in turquoise with a > to the left of it and hit enter.

Screenshot

Presuming that my computer’s default web browser is already logged into Sanity.io, I will see a confirmation screen in my web browser that I can close. (If I’m not logged in in my web browser, I might have to log into my sanity.io account.)

Screenshot


Initialize a new Sanity project

In my command line, I type:

Once there, I type the following into my command line:

sanity init

Screenshot

I use my keyboard’s up and down arrow keys to highlight Create new project in turquoise (which also puts a > to the left of it) and hit enter.

Screenshot

I backspace out the auto-suggested (My Sanity Project) and instead type a name I like for my project.

Screenshot

I personally decided upon Gatsby-02.

Screenshot

For demonstration purposes, I overrode the default dataset configuration by typing n when asked.

Screenshot

Instead, I decided to create a Sanity “dataset” called top_secret_stuff.

Screenshot

I arrowed up and down until Private (authenticated requests only) was highlighted turquoise and had a > to the left of it, then hit enter.

“Hello World” isn’t really going to be a big secret – it’s going right on my web site – but I want to show you how private data sets get used.

Screenshot

Since I had already navigated to C:\example\mysite_sanity before starting all this, I don’t have to backspace out and re-type the directory that I’d like to put my local “Sanity project” files in – so I just hit enter when Sanity suggests that I install my project there.

Screenshot

We’ll start with as few files as Sanity lets us – I’ll arrow down until I have Clean project with no predefined schemas selected and hit enter.

Screenshot

This is what Sanity looks like while initializing my project. It takes it a moment, because it’s downloading code from the internet.

Screenshot


Look around the project

Here’s what it looks like in the command line when it’s done:

Screenshot

And here’s what it looks like at https://manage.sanity.io when it’s done.

Screenshot

If I run this command, I can see it in the context of other projects I created earlier:

sanity projects list

Screenshot

If I click on my project itself, I’m taken to https://manage.sanity.io/projects/my-project-id/.

  • Here, my project ID starts with “z” and ends with “m.”
  • I don’t yet have a link next to studio, which will be my editor – I’ll make one soon enough.

Screenshot

Clicking on the “datasets” tab, I can see top_secret_stuff.

Screenshot

Clicking on the “settings” tab, I can change this project’s color theme to purple, just for fun.

Screenshot


Add an API key to the project

Clicking the “API” navigation item at left, I’ll find a page where I can click Add New Token.

Having a token is what will let computer systems read data out of my private dataset.

Screenshot

I’ll call mine Read-Only Token, set its rights to Read, and click Add New Token.

Screenshot

When the token pops up, I have to copy it to my password manager – I can’t get it back.

Screenshot

That said, I can easily delete this token and start over if I fail to copy/paste it properly.

Screenshot


Edit schema files on the hard drive

On my own hard drive at C:\example\mysite_sanity, I can see that Sanity installed a bunch of files.

Honestly, I only care about the ones in the schemas folder.

Screenshot

/schemas/schema.js

schema.js in the schemas folder is the master file defining my Sanity schema.

I’ll use it to tell Sanity about all the other “schema definition” files I create (which in this case, there will be just one of).

It comes like this:

// First, we must import the schema creator
import createSchema from 'part:@sanity/base/schema-creator'

// Then import schema types from any plugins that might expose them
import schemaTypes from 'all:part:@sanity/base/schema-type'

// Then we give our schema to the builder and provide the result to Sanity
export default createSchema({
  // We name our schema
  name: 'default',
  // Then proceed to concatenate our document type
  // to the ones provided by any plugins that are installed
  types: schemaTypes.concat([
    /* Your types here! */
  ])
})

I update it to say this:

// First, we must import the schema creator
import createSchema from 'part:@sanity/base/schema-creator'

// Then import schema types from any plugins that might expose them
import schemaTypes from 'all:part:@sanity/base/schema-type'

// We import object and document schemas
import xyzzy from './xyzzy'

// Then we give our schema to the builder and provide the result to Sanity
export default createSchema({
  // We name our schema
  name: 'default',
  // Then proceed to concatenate our document type
  // to the ones provided by any plugins that are installed
  types: schemaTypes.concat([
    // The following are document types which will appear
    // in the studio.
    xyzzy
    // When added to this list, object types can be used as
    // { type: 'typename' } in other document schemas
  ])
})

/schemas/xyzzy.js

I promised schema.js an “xyzzy” schema, so I also added a new file to the schemas folder and called it xyzzy.js.

Its contents are as follows:

import icon from 'react-icons/lib/md/note-add'

export default {
  name: 'xyzzy',
  title: 'X y zz y',
  type: 'document',
  icon,
  fields: [
    {
      name: 'template',
      title: 'Template',
      type: 'string'
    },
    {
      name: 'message',
      title: 'Message',
      type: 'string'
    },
    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      description: 'If not happy with what the system generated, you can hand-edit it here'
    }
  ],
  preview: {
    select: {
      slug: 'slug',
      template: 'template',
      message: 'message'
    },
    prepare(selection) {
      const {slug, template, message} = selection
      return {
        title: `${slug.current} [${template}]`,
        subtitle: message
      }
    }
  }
}

Since I intend to rebuild this Gatsby “Hello World” project using Sanity’s API instead of Markdown files as a data source, I’m sticking with the notion of each data item that needs to become a “page” having template and message properties into which I’ll type things like “xyzzy” and “message.”

(Maybe it’s a little confusing that I decided to name my Sanity object type xyzzy as well as that being the value I intend to type into template the first time I use it – sorry.)

Because there won’t be a folder-of-files structure like /src/pages/ from which Gatsby can infer what page URL I intend to translate a given piece of data into, I’ll also need to hand-type a URL suffix, or “slug.”

fields is where I set all that up.

The icon bit at the top just makes things pretty in “Sanity Studio,” as does the preview stuff at the bottom.

Screenshot

How to build files like xyzzy.js

  1. See Sanity's official schema documentation.
  2. Make a 2nd Sanity project on your hard drive where, instead of doing sanity init with Clean project with no predefined schemas, follow these instructions first with one of the sample options like Movie project, E-commerce, or Blog. Try to reverse-engineer what "schema" code seems to correspond to what user experiences you see in Sanity Studio. Personally, I learned a lot from Movie Project.

Build, deploy, build again, deploy again

To prepare this configuration of Sanity Studio, with my “schema” definitions and all, for deployment to Sanity’s cloud, I run the following command in my command line:

sanity build

Screenshot

Then I run this command:

sanity deploy

Screenshot

The command prompt asks me for a URL prefix at which I’d like to access my “Sanity Studio” for this project.

I chose gatsby-studio-002.

Screenshot

Then, the command line just sort of … does nothing. For 5 minutes. For me, anyway.

Screenshot

Eventually, refreshing https://manage.sanity.io/projects/my-project-id/ shows https://gatsby-studio-002.sanity.studio as my studio URL, but if I try to visit it, I get a “Studio not found” error as JSON-formatted text.

Screenshot

I gave it a couple more minutes, then hit “ Ctrl+Break ” on my keyboard and typed Y and hit enter to stop this deployment that clearly wasn’t going anywhere.

Screenshot

I ran sanity build again:

Screenshot

Then ran sanity deploy again:

Screenshot

And this time, in less than a minute, it worked.

That’s been my approach twice now, so hopefully it works for you if you run into trouble.

Screenshot


Log into Sanity Studio

Now, visiting https://gatsby-studio-002.sanity.studio from my project dashboard, I’m prompted to log in.

I click E-mail / password.

Screenshot

From there, I arrive at https://gatsby-studio-002.sanity.studio/desk, where I see a content type of X y zz y, just like I defined as the title property in xyzzy.js. Neat!

Screenshot

Clicking on X y zz y, I see a plus sign in the far right and click it.

Screenshot

I’m prompted to type in a template (I type xyzzy), message (I type Hello World), and slug (I type / to indicate that I’d like this content to serve as my web site’s home page).

Note that in the top center of the page, I see “/ [xyzzy]” in big text and “Hello World” in small text as a “preview” of this particular item in my data set, based on the way I’d asked for title (slug followed by the template in square brackets) and subtitle (message) to be rendered in the preview I defined in xyzzy.js.

It’s not a particularly attractive preview of my data, but it got the job done for demonstration purposes.

Screenshot


Test API access

To confirm that my data is really available to the outside world, I fire up Postman.

I set up an HTTP request with a method of GET, an endpoint of https://my-project-id.api.sanity.io/v1/data/export/top_secret_stuff, an Authorization header that starts with the phrase “Bearer” and ends with the secret token I saved earlier, and a Content-Type header of application/json, then hit Send.

At bottom, I can see traces of the data I entered in Sanity’s HTTP response body: part of it mentions Hello World, /, and xyzzy both as the template value I typed and, perhaps a bit confusingly – sorry – as the data type of the content itself (as defined in the name property from xyzzy.js).

Screenshot


Set up GraphQL API access

I also want Sanity to make my data available to the outside world in a way that accepts a data-querying language called GraphQL, since that's what a prebuilt plugin for Gatsby relies upon when connecting to Sanity to query my data.

If I build an HTTP request in Postman with a method of POST, an endpoint of https://my-project-id.api.sanity.io/v1/graphql/top_secret_stuff/default, an Authorization header that starts with the phrase "Bearer" and ends with the secret token I saved earlier, and a Body in GraphQL syntax with a blank "GraphQL Variables" section but a Query section containing the following code:

{
  allXyzzy {
    message
    template
    slug {
      current
    }
  }
}

Unfortunately, I get the following HTTP response body from Sanity:

{
    "statusCode": 404
    "error": "Not Found",
    "message": "GraphQL schema not found for dataset/tag"
}

Screenshot

Bummer.

It turns out that I have to explicitly tell Sanity that I'd like to enable GraphQL-based queries.

I do this by typing the following command into my computer's command prompt:

sanity graphql deploy --playground

Screenshot

Now when I re-run the same HTTP request that just failed on me, I get the following response body:

{
    "data": {
        "allXyzzy": [
            {
                "message": "Hello World",
                "template": "xyzzy",
                "slug": {
                    "current": "/"
                }
            }
        ]
    }
}

Screenshot

Much better!

If you're not used to writing GraphQL queries (I'm certainly not), visit https://your-project-id.api.sanity.io/v1/graphql/your-dataset-name/default, replacing your-project-id and your-dataset-name, of course, in a web browser while logged into Sanity.

That's the "playground" you set up by adding the --playground flag to your Sanity CLI command deploying a graphql interface for your dataset.

It comes with an editor and a big "run button" where you can make all the typos you want as you learn GraphQL. It also gives you some hints while you type.

Screenshot


Next steps

Stay tuned – next I’ll set up a Gatsby site that not only displays my “Hello World” on the home page, but has a “live preview” that changes as people edit the value of message in Sanity Studio.


Posts in this series

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .