Heroku live previews for Gatsby + Sanity sites
Tags: tutorial, webdev, heroku, gatsby
Published: 2020-08-19 11:59:09

---
title: Heroku live previews for Gatsby + Sanity sites
description: "Hosted Gatsby Develop"
published: true
date: 2020-08-17 15:00:00 UTC
tags: tutorial,webdev,heroku,gatsby
series: Playing With Gatsby
cover_image: https://katiekodes.com/images/header-gatsby-sanity-202007.png
canonical_url: https://katiekodes.com/gatsby-sanity-preview-heroku/
---

I [said previously](https://dev.to/katiekodes/gatsby-cloud-live-previews-for-sanity-based-sites-jj2#issues-with-gatsby-cloud) that I wouldn’t use Gatsby Cloud’s free tier for hosting the “live preview” instance of a Gatsby site coupled with Sanity CMS because I didn’t find its usage quotas generous enough for handing over to a content author.

{% link https://dev.to/katiekodes/gatsby-cloud-live-previews-for-sanity-based-sites-jj2 %}
  
Today I’ll show you how to deploy a Gatsby site in “`develop`” mode to **Heroku** so that you can host a lovely **real-time live preview site** at `https://preview.yoursite.com`.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-gatsby-sanity-2020-07/65-live-editing-animated.gif)

* * *

## Files

Pick a folder on your hard drive that will serve as your local copy of all the Gatsby-related files you need to put into your git repository on GitHub.

I chose `C:\example\mysite_gatsby`.

To make this Gatsby site, I started with the [files](https://github.com/kkgthb/web-site-gatsby-05-template-sanity-gatsbyhalf) from my “[Gatsby minimum viable Sanity template](https://dev.to/katiekodes/gatsby-minimum-viable-build-with-sanity-cms-bic)” tutorial.

{% link https://dev.to/katiekodes/gatsby-minimum-viable-build-with-sanity-cms-bic %}

I added 3 files _(`/Procfile`, `/app.json`, & `/static.json`)_ and changed 1 _(`package.json`)_ to support hosting on Heroku.

The file structure is as follows:

```
.
├── src
│ └── templates
│ └── xyzzy.js
├── Procfile
├── app.json
├── gatsby-config.js
├── gatsby-node.js
├── package.json
└── static.json

```

All I did to `package.json` was delete the lines of code representing the `"scripts"` object _(`Procfile` handles server instructions instead)_.

I won’t go into detail about the 3 Heroku-specific files, because the work I did is so simple:

- The single line of content in **[Procfile](https://github.com/kkgthb/web-site-gatsby-06-template-sanity-gatsbyhalf-heroku/blob/master/Procfile)** is from Andreas Keller’s blog post “[Custom Live Preview for Gatsby Sites with Heroku](https://awesomereact.com/articles/custom-gatsby-preview-with-heroku).    
  - `Procfile` tells Heroku how to behave when requested to put `https://YOUR_APP_NAME.herokuapp.com` onto the internet.
- **[app.json](https://github.com/kkgthb/web-site-gatsby-06-template-sanity-gatsbyhalf-heroku/blob/master/app.json)** and **[static.json](https://github.com/kkgthb/web-site-gatsby-06-template-sanity-gatsbyhalf-heroku/blob/master/static.json)** are copied and pasted straight out of the official Gatsby documentation “[Deploying to Heroku](https://www.gatsbyjs.com/docs/deploying-to-heroku/).”

I uploaded the these files into a GitHub repository under the username `gatsbyclouddemo`, for continuity with my last post on the subject.

* * *

## Prerequisites

If you’re just jumping in now, you’ll need a running Sanity project that matches the repository I’m demonstrating.

Go back to “[Sanity CMS minimum viable build](https://dev.to/katiekodes/sanity-cms-minimum-viable-build-4j7)” to make one, taking a moment to write down your project ID, API token, etc.

{% link https://dev.to/katiekodes/sanity-cms-minimum-viable-build-4j7 %}

* * *

## Heroku

### Set up Heroku

[Sign up for a free Heroku account](https://signup.heroku.com/) if you don’t have one and [log into Heroku](https://id.heroku.com/login).

Go to [https://dashboard.heroku.com/apps](https://dashboard.heroku.com/apps) and click “ **Create new app**.”

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/01-heroku-create-app.png)

Give your app a name _(you can’t have `gatsbysanitydemo` – I took it)_ and click “ **Create app**.”

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/02-heroku-app-name.png)

Under the **Deploy** tab, in the **Deployment method** section of the page, click **GitHub** as a way to deploy your Gatsby site to Heroku and click **Connect to GitHub**.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/03-heroku-github.png)

Log into GitHub with the account where you’ve stored the code for your Gatsby site.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/04-github-sign-in.png)

Give Heroku full permissions to your GitHub account.

I don’t normally like to give software this level of permission in my GitHub account, and there are alternative ways to get info from GitHub to Heroku that give Heroku a little less control over your GitHub account, but they’d be too tangential to cover right now.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/05-github-full-permissions.png)

Under the **Deploy** tab, in the **Connect to GitHub** section of the page, click **Search** without typing anything into the search prompt.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/06-search-github.png)

Click **Connect** next to the name of the repository that contains the code for your Gatsby site.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/07-github-connect.png)

Click **Enable Automatic Deploys**.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/08-enable-automatic-deploys.png)

Click the **Settings** tab toward the top of Heroku and, in the **Config Vars** section, click **Reveal Config Vars**.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/10-reveal-config-vars.png)

Add key-value pairs as follows:

- `NODE_ENV` = `development`
- `SANITY_PROJECT_ID` = _(your [Sanity project’s ID](https://katiekodes.com/sanity-minimum-viable-build/#look-around-the-project))_
- `SANITY_DATASET` = _(your [Sanity project’s dataset’s name](https://katiekodes.com/sanity-minimum-viable-build/#look-around-the-project))_
- `SANITY_READ_TOKEN` = _(whatever [API token](https://katiekodes.com/sanity-minimum-viable-build/#add-an-api-key-to-the-project) you set up in Sanity for your project’s dataset)_
- `SANITY_WATCH_MODE` = `true`
- `SANITY_OVERLAY_DRAFTS` = `true`
- `ENABLE_GATSBY_REFRESH_ENDPOINT` = `true`

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/11-config-vars.png)

* * *

### Force Heroku to build your site

I hadn’t yet committed my changes from the previous version of my Gatsby site to GitHub when I reached this point of taking screenshots, so I triggered a Heroku build simply by pushing my altered and new files from my computer to my GitHub repository.

If you need to force a manual Heroku site build from your GitHub repository, go back to Heroku’s **Deploy** tab and scroll to the bottom of the page. There should be a button.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/12-commit-new-stuff.png)

Heroku confirms that my site built:

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/13-heroku-built.png)

And sure enough, I’m live at `https://gatsbysanitydemo.herokuapp.com` with the last data I’d entered in to Sanity _(doodling around on July 31st)_.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/14-heroku-built-web.png)

Now I’ll put two web browsers side-by-side, one logged into “Sanity Studio” where I edit my data, and the other displaying `https://gatsbysanitydemo.herokuapp.com`.

I didn’t make any fresh animated GIFs for you this time, so you’ll just have to trust me when I say that data showed up as I typed.

First, I changed my hand-typed timestamp to something more current.

> The changes showed up **live, while I typed**.
> 
> Hooray! 🎉

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/15-draft-alive-33.png)

* * *

### Tidy up a Gatsby-Sanity bug

In fact, even after I hit **Publish** , the changes stick.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/16-so-far-so-good-33.png)

That’s a bit surprising – I’ve had problems with [involuntary content rollbacks](https://github.com/sanity-io/gatsby-source-sanity/issues/87) when using Gatsby and Sanity together for a live preview.

I don’t trust it.

Let me try again.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/17-draft-alive-40.png)

Here we go. Upon **publishing** the `40` change, my content reverted to ending with `33`.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/18-revert-bug-40.png)

Luckily, I have a fix for that.

Log into [https://manage.sanity.io/](https://manage.sanity.io/), find your project, go to the **Settings** tab, click **API** in the left nav, and click **Add New Webhook** at the bottom of the page.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/20-sanity-webhook.png)

Give your new webhook a **URL** of `https://APP_NAME.herokuapp.com/__refresh` _(replacing `APP_NAME` with your Heroku app’s name, of course)_ and click **Add New Webhook**.

Setting the `ENABLE_GATSBY_REFRESH_ENDPOINT` endpoint to `true` is what made Gatsby create this magic `/__refresh` web page as part of the site.

I wish it were a bit more … secret.

This seems like a decent way to get your Heroku app [DoSed](https://en.wikipedia.org/wiki/Denial-of-service_attack) by a teenager who thinks he’s being funny.

If you have suggestions in the comments about how to make Gatsby rebuild without having such an _obvious_ webhook endpoint, I’m all ears!

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/21-sanity-webhook-details.png)

The new webhook should appear in your Sanity management console.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/22-sanity-webhook-details.png)

Now you have to do one more thing – at least until Sanity [fixes a bug](https://github.com/sanity-io/gatsby-source-sanity/issues/87).

Go into your Sanity Studio and add a piece of draft content with _no template_ and _no slug_ _(such content will be ignored by the particular `gatsby-node.js` I wrote)_ and, in the message, type a note to yourself reminding yourself not to delete it.

For some reason, you need _a_ draft “alive” in Sanity for “publish” webhook-based builds to avoid “reverting” to old content.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/23-sanity-permanent-draft.png)

Now go back and make a change to your actual home page in Sanity and click **Publish**.

> It should stick!
> 
> Hooray! 🎉

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/24-much-better-41.png)

The only catch is that if Heroku falls asleep while you have content in “draft” status, and then you wake it up, and then you **revert changes** in Sanity Studio, Gatsby doesn’t seem to recognize that as either a “draft” or a “publication” and doesn’t update the page accordingly.

You may have to play around a bit, re-typing things and forcing fresh “publishes,” if this happens to you.

* * *

### Need geek proof?

If you really want proof that the `41` change stuck in response to Gatsby recognizing a webhook call to `/__refresh`, you can [install Heroku’s command-line interface tool](https://devcenter.heroku.com/articles/heroku-cli#download-and-install) on your computer and use it to read the server logs of your web site.

Once you have it installed, run `heroku login` and use your web browser to authenticate yourself to the CLI tool.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/25-heroku-login.png)

Then type `heroku logs app=APP_NAME --tail`, replacing `APP_NAME` with the name of your Heroku app.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/26-heroku-log.png)

Confirm that Heroku indicates it received a `POST` HTTP request to `https://APP_NAME.herokuapp.com/__refresh` and that Gatsby/Sanity reacted by `processing changed documents from webhook`.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/27-heroku-log-output.png)

When you’re done, you can exit with **Ctrl+C** if you’re on Windows and confirming that you’d like to terminate the “batch job.”

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/28-heroku-log-ctrl-c-exit.png)

It’s now safe to close your command prompt.

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/29-heroku-cli-close.png)

* * *

## Considerations

### Wake-up

Heroku will put `https://APP_NAME.herokuapp.com` to sleep 30 minutes after its last use if you’re on the free plan.

If your site’s non-technical content author tries to visit it, watches the page take a minute to load, and finally sees an error, Heroku was probably just waking up!

![Screenshot](https://katiekodes.com/images/screenshots/screenshot-heroku-gatsby-sanity-2020-08/30-heroku-asleep-error.png)

Gatsby builds aren’t known for their speed, so Heroku probably couldn’t roll out of bed quickly enough to answer the phone.

> Tell content authors to **reload the page** after they receive this message and see if it helps.

As long as they’re visiting the preview site frequently enough that your app doesn’t get _deleted_ off Heroku, reloading the page should work.

- **Q:** Afraid your content authors won’t visit frequently enough to keep the site from being deleted?
- **A:** Consider a weekly or nightly “cron job” running on a free server in the cloud to [visit your preview site](https://medium.com/better-programming/keeping-my-heroku-app-alive-b19f3a8c3a82) in the author’s place.

* * *

### Use your own domain

I promised you a lovely site at `https://preview.yoursite.com`.

Unfortunately, I’m going to leave it up to you to research “[custom domains](https://devcenter.heroku.com/articles/custom-domains)” so you can force Heroku to use `preview.yoursite.com` as a substitute for `APP_NAME.herokuapp.com`

I don’t feel like giving Heroku my credit card number and getting “verified” for the sake of a tutorial.

Alternatively, if you’re okay with content authors’ web browsers being _redirected_ to `https://APP_NAME.herokuapp.com` and just want to give them an easy-to-remember starting point, you can probably just set up a redirect with your DNS provider and never tell Heroku about `preview.yoursite.com`.

* * *

### Keep out unwanted visitors

Simeon Griggs makes an excellent point at “[Roll your own Gatsby live preview for Sanity](https://www.simeongriggs.dev/roll-your-own-gatsby-live-preview-for-sanity)” that you might want to further play with your Gatsby site’s codebase so that when in “develop” mode, it includes instructions that search engines should ignore it.

Maybe you also want to password-protect this whole site.

I haven’t tried, but a search for “[password protect heroku app](https://www.google.com/search?q=password+protect+heroku+app)” had some interesting results.

_(Don’t forget to let your content-publication Sanity webhook server and your “cron job” server into the site, not just your human content authors.)_

* * *

![](https://katiekodes.com/images/shoppingbags.jpg)

## Takeaways

I hope you were able to use this tutorial, combined with my previous ones, to stand up a working Gatsby live preview on Heroku.

The architecture should be similar for other [static site generators](https://www.staticgen.com/) whose non-production modes have some way of constantly fetching data from a “drafts” API endpoint within your CMS and updating the page in response, not just Gatsby.

- _(On a related note, although seemingly not leveraging a general-purpose Node.js server host like Heroku, it looks like Jérôme Pott just wrote “[How to handle content previews from Sanity in Nuxt](https://dev.to/mornir/how-to-handle-content-previews-from-sanity-in-nuxt-3127)” yesterday.)_

{% link https://dev.to/mornir/how-to-handle-content-previews-from-sanity-in-nuxt-3127 %}

Similarly, the idea of hosting a non-production static site generator on Heroku as a “live preview” should work for other [API-based content management systems](https://headlesscms.org/) with “draft” API endpoints, not just Sanity _(although Sanity might be a little special in literally updating its endpoint content with each letter you type)_.