The Definitive Guide to Setting up Sanity.io with GatsbyJS

You've spent some time researching different CMS's and static site generator's and you've decided you want to use sanity.io and Gatsbyjs. But all the resources out there are either how to setup a pre-exisiting project or don't go far enough. Well in this guide we are going to get a HomePage with content outputting to a page, and a functional blog from scratch. With deployment to Netlify and a preview instance which you can live edit with Gatsby Cloud so you don't have to deploy your site to show some minor changes or have clients preview the changes before deploying.

The first move in this piece is to install Gatsby and Sanity, order does not matter. I will include a repo here with branches based on where we are in the guide. If you don't want to do this all from scratch Sanity has a great article here with a repo to clone just to see how the two work together. If you are still hesitant I would try that first to see if you even like the environment. Lastly another great start would be a article from dev.to about the process we are going to do next, it just doesn't go as far as seeing your content, building a blog and deployment to gatsby cloud. Lets Go!

In order to install Gatsby and Sanity, you need Node installed. For more information on how to set that up with something called nvm read our Node setup for Linux, Mac & Windows basic guide. If you are familiar with terminal, & git feel free to do step #1 however you like, the only arcitecture is having a studio and web folder in a git repo called gatsby-sanity-tutorial. If you wanted to you could seperate them, I keep them together for simplicity.

Step #1 Create a directory and Initialize git

Create a directory called gatsby-sanity with the following commands you can run these separate removing the && or you can run it all at once.

mkdir gatsby-sanity-tutorial && cd gatsby-sanity-tutorial && git init

Now that you are inside the folder and you have initialized a git repo create a studio folder and a web folder with the following command.

mkdir web && mkdir studio

Next up create a git repo called gatsby-sanity-tutorial on your platform of choice I recommend Github for github you can follow there guide after creation, you can choose private or public and leave everything else as is. But I will put the code here as well.

First create a README.md file for instructions to keep track of for later the hash tag then gatsby-sanity-tutorial is creating that line inside the readme you can open it in your code editor to check. I use visual studio code. You can see our Basic Terminal & Code Editor Guide for more.

echo "# gatsby-sanity-tutorial" >> README.md

Next add either the readme to the repository or everything I will give the command for both, you can do either or no need to do both, however git will ignored the empty folders for now, so don't worry if they dont show up when we push up to github.

git add .

git add README.md

Next create a descriptive commit message

git commit -m "created readme - initial commit"

Next add the github remote origin, so git knows where to push the repositiory code to. For this one copy and paste the instruction line number 5 in the github instructions mine looks like this.

git remote add origin https://github.com/wispyco/gatsby-sanity-tutorial.git

Lastly in this first step push the code up with the following command.

git push -u origin master

You should get the following in your terminal and you can refresh the github page and see the readme with your title. It will probably ask for your username and password. If you have two factor auth setup you need to do the following If you are stuck on getting errors, feel free to comment below.

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 247 bytes | 247.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/wispyco/gatsby-sanity-tutorial.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

That concludes step 1

Step #2 Setup Sanity CLI and initialize studio

Ok first go into the studio folder we are going to install sanity next and inititalize it after that.

cd studio

Install the Sanity CLI globally this needs node installed to run. This will allow us to run sanity commands and get our cms studio up and running.

npm install -g @sanity/cli

Next we are going to initialized sanity studio You should get a response asking you to create new project, hit enter, then it will ask for a project name you can call it whatever you like, for these purposed I wrote gatsby-sanity-tutorial. It will give your a project outputpath, just hit enter. It will ask for a project template navigate down to clean and hit enter.

sanity init

Lets see what it generate type the following command

ls

you shoul get the following returned

config  node_modules  package.json  plugins  README.md  sanity.json  schemas  static  tsconfig.json  yarn.lock

open this folder up in your favourite code editor, I use vscode, so this command works for me. Take a look around, we are going to be working in the schemas folder. This is where you define the content model's for Sanity (what you edit in the cms)

code .

Lastly start Sanity and view it in the browser.

sanity start

You should get the following response and you can now vist http://localhost:3333 Yahoo! the build number will be different

Checking configuration files...Compiling...webpack built 7a358a2982976ebf6d6d in 10576ms
✔ Compiling...
Content Studio successfully compiled! Go to http://localhost:3333

Open up that link and login with any provider you prefer, it should look like this

Login with your chosen provider and you should now see the following. It will say empty schema, that's what we need to build next so Sanity knows what types of content inputs you want.

Make a commit

Before we go onto step 3 we should make a commit and before we make a commit we should make sure we are not including files we dont wont, so create a .gitignore at the in gatsby-sanity-tutorial/studio and add the following line in it

node_modules

Now cd in sudio in your terminal in tha and run the following commands in order to add your studio folder and everything in it to the repo and push it up to git. You can see my commit here to see how it should look.

cd studio
git add .
git commit -m "step 2 completed sanity studio running"
git push

Step #3 Part A Creating Schema for content inputs

Schemas are a way for you to define Sanity's models, that also generate a graphQL api that can be accessed by Gatsby. Lets start with something very simple first create the following file inside of gatsby-sanity-tutorial/studio/schemas or where you should be in your code editor. Create a file called home.js with the following schema.

export default {
    name: 'homePage',
    title: 'Home Page',
    type: 'document',
    fields: [
      {
        title: 'Intro Title', 
        name: 'intro',
        type: 'text', 
      },
    ]
  }

The above is fairly simple we are creating a object that sanity can read and output a model and input field for you to type in. For more details on Sanity Schema click here. Now you also need to include this file in your schema.js file you can import it there, open up schema.js located in gatsby-sanity-tutorial/studio/schema/schema.js. Add in the import home line and the home variable in the types section. I commented Add This where you should add. Remember that it helps to type this vs just copying and pasting.

// 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'

import home from './home' //Add This

// 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([
    home //Add This
  ])
})

Now lets check it in sanity studio after running sanity start, it should look like the following. You may have to hit the plus sign at the right in order to open this view. Now this is good, however we can create multiple HomePage document's which is good if you want a blog, but we are not quite there yet. We dont want to have to click the plus jst the title and have only one input for a home page title.

Make a commit

Right before starting part B lets make another commit, and push up to git hub with the following. You can see my commit here

git add .
git commit -m "Step #3 Part A completed"
git push

Step #3 Part B Making schema document a singleton

In order to make the document a singleton you have one title for your website and dont have the option to create more, which makes the UI better for a client and it's easier to query a single document to start with. No need for mapping of an arry. So first create a file called deskStructure.js located at the root of the studio folder so it should be gatsby-sanity-tutorial/studio/deskStructure.js Use the following code below

import S from "@sanity/desk-tool/structure-builder";

export default () =>
  S.list()
    .title('Content')
    .items([
      S.listItem()
        .title('Home Page')
        .child(
          S.document()
            .schemaType('homePage')
            .documentId('homePage')
            .title('Enter your home page details')
        ),
      // Add a visual divider (optional)
      S.divider(),
      // List out the rest of the document types, but filter out the config type
      ...S.documentTypeListItems()
        .filter(listItem => !['homePage'].includes(listItem.getId()))
    ])

The above looks rather confusing but it's just a chain of options, applying to the panels filtering out the listItem type. Next up you need to add a line referencing this file in your sanity.json file. I am going to stop giving exact paths except when something may be confusing. It is located at the root. In that file you need to ammend it to look like the following.

{
  "root": true,
  "project": {
    "name": "gatsby-sanity-tutorial"
  },
  "api": {
    "projectId": "62e5xzju",
    "dataset": "production"
  },
  "plugins": [
    "@sanity/base",
    "@sanity/components",
    "@sanity/default-layout",
    "@sanity/default-login",
    "@sanity/desk-tool"
  ],
  "env": {
    "development": {
      "plugins": [
        "@sanity/vision"
      ]
    }
  },
  "parts": [
    {
      "name": "part:@sanity/base/schema",
      "path": "./schemas/schema"
    },
    {
      "name": "part:@sanity/desk-tool/structure",
      "path": "./deskStructure.js"
    }
  ]
}

you can copy and paste the following and place it in your file to match the above

{
  "name": "part:@sanity/desk-tool/structure",
  "path": "./deskStructure.js"
}

Once your done there you can visit http://localhost:3333 and see the difference, you will have to stop sanity and start sanity again in order for the change to show up. Write some content in there, and lets go to step #4 and setup Gatsby. It should look like below. It's a slight difference, but it makes a huge help down the road. You'll notice you can't make multiple documents the plus sign is gone, this is good for what we want to achieve.

Make a commit

Right before starting step 4 lets make a commit with the following, like always you can see my commit here to match it up

git add .
git commit -m "Step #3 Part B finished Making schema document a singleton"
git push

Step #4 Part A Setting up Gatsby to pull data from Sanity Woot!

Next up, is the fun part in my opinion it's actually getting your data into the cms. Fisrt open a new terminal tab leaving sanity running and navigate to the web folder in your terminal. Run the following command to install Gatsby.

npm install -g gatsby-cli

Then you can run gatsby commands, we are going to create a new gatsby project inside the web folder run the following, the . at the end is important it is saying put everything inside this folder.

gatsby new .

now open up the web folder I run code . to do so. Then run the following in order to start Gatsby's development environment.

gatsby develop

After running that you should get the following output in your terminal. You can visit the url and you should see your Gatsby Site up and running.

You can now view gatsby-starter-default in the browser.

  http://localhost:8000/View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
  http://localhost:8000/___graphql
⠀
Note that the development build is not optimized.
To create a production build, use gatsby build
⠀
success Building development bundle - 3.370s

When you visit the http://localhost:8000 you should see the following below

Make a commit

Right before starting step 4 part b lets make a commit with the following command, and you can view my commit to compare here

git add .
git commit -m "step 4 part completed setting up gatsby"
git push

Step #4 Part B Setting up Gatsby to pull data from Sanity Woot

Now we need to install the the gatsby-soruce-sanity plugin this will allow us to write GraphQL queries and output the data in Gatsby. First stop Gatsby and run this command.

npm install gatsby-source-sanity

Once that is succesfull go into your code editor and open up your gatsby-config.js file modify it to look like the following

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
    description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
    author: `@gatsbyjs`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
    {
      resolve: `gatsby-source-sanity`,
      options: {
        projectId: `62e5xzju`,
        dataset: `production`,
        watchMode:true,
        // a token with read permissions is required
        // if you have a private dataset
        token: process.env.SANITY_TOKEN,
        // If the Sanity GraphQL API was deployed using `--tag <name>`,
        // use `graphqlTag` to specify the tag name. Defaults to `default`.
        graphqlTag: 'default',
      },
    },
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
  ],
}

The part you are adding is this, now login into sanity.io and grab the projectId and replace it. Change the data set to production. You can also find your projectId and dataSet in your sanity.json file in your studio folder. watchMode is key because it allows you to hit publish in Sanity and see the data live in development mode refresh without having to stop and start gatsby. I will show you in graphQL playground how to query it first to test.

{
  resolve: `gatsby-source-sanity`,
  options: {
    projectId: `62e5xzju`,
    dataset: `production`,
    watchMode:true,
    // a token with read permissions is required
    // if you have a private dataset
    token: process.env.SANITY_TOKEN,
    // If the Sanity GraphQL API was deployed using `--tag <name>`,
    // use `graphqlTag` to specify the tag name. Defaults to `default`.
    graphqlTag: 'default',
  },
},

After any gatsby config change you need to stop and start it so do so, and open up the second link in the console http://localhost:8000/___graphql it should look like the following

Click on the sanityHomePage, then click the intro box, and as long as your text is published in sanity when you click the play button your data will show up as an object. We are going to repeat this query in Gatsby and get some content on the page Yes! Your graphQL should look like the following.

Query and pull the data into Gatsby

Lastly open up src/pages/index.js in your web folder. Add the following code, open up gatsby website and you should see the text from sanity appear as long as it is published.

import React from "react"
import { Link } from "gatsby"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

const IndexPage = ({data}) => (
  <Layout>
    <SEO title="Home" />
    <h1>{data.sanityHomePage.intro}</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

export default IndexPage

export const query = graphql`
  query {
    sanityHomePage {
      intro
    }
  }
`

The key pieces are the query variable at the bottom, the data prop being bassed into the component the import graphql at the top and the {data.sanityHomePage.intro} jsx to traverse the object passed into the component from graphQL. You should see the following.

Make a commit

Now lets make a commit with the following command, you can view my commit here for comparison, feel files we have been working on and campare if your are stuck.

git add .
git commit -m "step#4 part b completed setting up gatsby to pull data from sanity"
git push

Step #5 deploy to Gatsby Cloud for development server

First go and visit Gatsby Cloud signup for an account with the same github account your are making these commits and pushing up to. Once you are logged into Gatsby Cloud you can clikc the new site button and you should be presented with two options. I dont have a gatsby site yet & I already have a Gatsby site, choose the latter, since we do have a Gatsby site. The next page you should see an option to search for your repository type gatsby-sanity-tutorial, choose it from the list and leave the Production branch to master and the Base Directory to /web/ It should look like the following below.

Next click connect to sanity in the next step, then click Authorize with Sanity, a window should popup asking yout to authorize. You may need to create an account on sanity.io. Once you are authorized you should see a page like this hit continue with your project selected.

Dont hit Create site just yet (it's ok if you have)

Click continue, then click Set up your site, you can scroll and see all the environmental variables gatsby setup automatically with its authorization from Sanity. These are setup in the gatsby-config.js now before we create the site we could just go ahead but its best to setup our envrionment variables in that file first it will look like the following. You also need to include dot-env so gatsby can in the background pass those variables to the site without the client reading them.

require('dotenv').config();

module.exports = {
  //...
  plugins: [
    //...
    {
      resolve: `gatsby-source-sanity`,
      options: {
        projectId: process.env.SANITY_PROJECT_ID,
        dataset: process.env.SANITY_PROJECT_DATASET,
        watchMode:true,
        // a token with read permissions is required
        // if you have a private dataset
        token: process.env.SANITY_TOKEN,
        // If the Sanity GraphQL API was deployed using `--tag <name>`,
        // use `graphqlTag` to specify the tag name. Defaults to `default`.
        graphqlTag: 'default',
      },
    },
  ]
}

Where I have put //... just means leave that section as is. Next we need to create a .env file and place our variables in there based off of the ones sanity generate for us. It will look like this, replacing your projectID and dataset with whats in Gatsby.

SANITY_PROJECT_ID=62e5xzju
SANITY_PROJECT_DATASET=production

Make a commit

Make sure Gatsby is running, if it's running you know you have set it up correct, lets make a commit and push up before we create the site. WIth the following commands, you can view my commit here

git add .
git commit -m "setup environment variables"
git push

Then click Create site and watch Gatsby Cloud do its magic. You should see a page like this.

You will eventually get a build-random-random-random.gtsb.io url, click on that and you will see you gatsby site live on the web. Woot! We still got lots to do, but were getting close to having a dev site setup with live editing. Now if you go back into your sanity studio locally at http://localhost:3333 and change the intro text hit publish and go back to Gatsby Cloud, you can do one of two things, you can trigger a build manually to see the change, or you can click on the preview button text on the right and you will have a running gatsby development server that pulls in changes live, there should be a link like this gatsby-sanity-tutorial-random-gtsb.io for you to click on it will look like this page below. When you click on that link you will see your published changes. Now try and make some more changes publish them and see the site change with a hot reload.