Sync your Gatsby Sanity Website on Content Change automatically with any hosting provider using GitHub Actions
Published: 2023-02-17 18:31:22

Skip to the **"How to"** section for the step by step guide.

<br>

# Preface

If you're like me and want a free way to quickly get started developing a website with a content management system (cms) in place with the best possible seo and performance and not be limited by the gatsby cloud free tier while also having the website automatically update when the content changes, this one is for you.

I spent a solid 9 hours on figuring this out so you hopefully can get started within, like, one.

### Why so long though

Most of the helpful threads online are outdated so this will serve as the most recent guide (Feburary 2023) for now.<br>

# How to

The starting point for my journey was [Gatsbys Sanity Starter Template](https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-sanity-homepage) so the specific commands might differ.

In this tutorial I'm going off of having the site hosted on GitHub Pages. What would need to be adjusted will be explained when it gets to that point.<br>

## Step 1: GitHub Actions
---

first you'll have to set up your GitHub Actions in the repository of your gatsby website.

for this you'll need to set up the following folder structure:<br>

`<root>/.github/workflows/` _(root is where the `src` folder is located)_<br>
in here you can use any file name ending in `.yml`<br>
let's say...<br>
`deploy.yml`<br>

In here you'll want to add<br>
```yml
name: GitHub Pages

on:
  push:
    branches:
      - master  # Set a branch name to trigger deployment
  pull_request:
  repository_dispatch:
    types: deploy
    
jobs:
  deploy:
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: true
          fetch-depth: 0

      - name: Set Node.js 18.x
        uses: actions/setup-node@v3
        with:
          node-version: 18.x   # whatever version your gatsby uses (you can find that in package.json under 'engine')

      - name: Run install
        uses: borales/actions-yarn@v4
        with:
          cmd: install # will run `yarn install` command
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # if needed

      - name: yarn
        env: # this stuff doesn't work but its a starting point
          SANITY_READ_TOKEN: ${{ env.SANITY_READ_TOKEN }}
          SANITY_PROJECT_ID: ${{ env.SANITY_PROJECT_ID }}
          SANITY_PROJECT_DATASET: ${{ env.SANITY_PROJECT_DATASET }}
          SANITY_LIVE_PREVIEW: ${{ env.SANITY_LIVE_PREVIEW }}
        run: yarn & yarn setup

      - name: Build
        run: yarn build

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        # If you're changing the branch from main,
        # also change the `main` in `refs/heads/main`
        # below accordingly. bump
        if: ${{ github.ref == 'refs/heads/master' }}
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public
```

This bad boy basically goes:<br>
Install node - Install yarn - Install all the dependencies with yarn - **run the custom yarn setup command** - run gatsby build through a custom command - **publish website from the generated `public` folder to the gh-pages branch**

The **yarn setup** command is specific to the gatsby sanity starter template and the **gh-pages** stuff is specific to publishing with GitHub Pages, so you may need to adjust that.

The more interesting part is the stuff at the top.<br>
By specifying <br>
```yml
    repository_dispatch:
        types: deploy
```
We tell GitHub actions that a specific request containing the "deploy" keyword (or any other keyword you choose) triggers that action.<br>

## Step 2: GitHub Authentication Token
---

For any request you send you'll need an authentication token. To acquire that token go to your profile icon and go to:<br>
`Settings -> Developer Settings (last link on the left) -> Personal Access Tokens -> Fine Grained Tokens (trust me, the other token type won't work)` and tap `Generate new token` <br>
select your repository and enable read/write permissions for Actions __and__ Contents.
Generate the token and save it somewhere safe.<br>

## Step 3: Sanity Webhooks
 ```Open your sanity dashboard``` (not sanity studio, your account dashboard) ```-> select your project -> click on API -> Click on create webhook```<br>
<br>
In here we enter the following data:<br>
- URL: `https://api.github.com/repos/<GitHub Acoount Name>/<GitHub Repository Name>/dispatches`
- Projection: `{"event_type":"deploy","client_payload":{"unit":false,"integration":true}}` _event_type matches whatever you put into repository_dispatch: types:_ <br>(This is the _body_ part of the request)
- HTTP Method: `POST`<br><br>
  In HTTP headers add the following fields with the following values
- Accept: `application/vnd.github+json`
- Authorization: `Bearer <Your generated GitHub Token from step 2>`
- X-GitHub-Api-Version: `2022-11-28`

## Done!
---
### Snippets/Summaries for the impatient
<br>

### __Step 1: GitHub Actions__
`<root>/.github/workflows/deploy.yml`

```yml
name: GitHub Pages

on:
  push:
    branches:
      - master  # Set a branch name to trigger deployment
  pull_request:
  repository_dispatch:
    types: deploy
    
jobs:
  deploy:
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: true
          fetch-depth: 0

      - name: Set Node.js 18.x
        uses: actions/setup-node@v3
        with:
          node-version: 18.x   # whatever version your gatsby uses (you can find that in package.json under 'engine')

      - name: Run install
        uses: borales/actions-yarn@v4
        with:
          cmd: install # will run `yarn install` command
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # if needed

      - name: yarn
        env: # this stuff doesn't work but its a starting point
          SANITY_READ_TOKEN: ${{ env.SANITY_READ_TOKEN }}
          SANITY_PROJECT_ID: ${{ env.SANITY_PROJECT_ID }}
          SANITY_PROJECT_DATASET: ${{ env.SANITY_PROJECT_DATASET }}
          SANITY_LIVE_PREVIEW: ${{ env.SANITY_LIVE_PREVIEW }}
        run: yarn & yarn setup

      - name: Build
        run: yarn build

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        # If you're changing the branch from main,
        # also change the `main` in `refs/heads/main`
        # below accordingly. bump
        if: ${{ github.ref == 'refs/heads/master' }}
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public
```
### __Step 2: GitHub Auth Token__
Generate the __granular controll token__ for your repo, the other expires when testing on non-ssl secured connections (and for other unknown reasons)
### __Step 3: Sanity Webhooks__
match the sanity config with this curl
```curl
curl --request POST \
  --url https://api.github.com/repos/<gh username>/<gh repo name>/dispatches \
  --header 'Accept: application/vnd.github+json' \
  --header 'Authorization: Bearer <gh access token>' \
  --header 'X-GitHub-Api-Version: 2022-11-28' \
  --data '{"event_type":"deploy","client_payload":{"unit":false,"integration":true}}'
```

## Done!
Now whenever the content changes your website will rebuild and reflect those changes within about two minutes. And completely free at that. If you find a hosting provider where i can host a development server for gatsby for free to reflect live changes instantly in a cloud setting send me a message!

Check out my github if you want to see what I'm up to: [DavidCks GitHub](https://github.com/DavidCks)
Everything I develop for myself is free and open-source forever, for everyone.