Backup Sanity with Cloud Firestore

https://youtu.be/ea1-Dv4z2nI

New Firebase Project

In order to accept webhooks from Sanity you will need to have a firebase project setup, you can search this site for many examples. But most simply run firebase init on your command line and select Functions and Firestore, you can keep all other defaults.

TODO_UPLOAD

After selecting an existing or creating a new project make sure to select TypeScript

TODO_UPLOAD

Cloud Firestore

If you run into any issues on the command line, you can open the console and validate your Firestore database has been created.

The main thing that needs to happen in firestore is to make sure that your rules will allow you to write to the database. Make sure in firestore.rules, you have something similar to this based on the content that you are bringing over. Realisticly we are using the the admin functions so you don't need these rules to write, but it is nice to remember if you are getting blocked in your site for read access.


rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
    match /sanity/{sanityId} {
        allow read: if true;
        allow write: if false;

      match /courses/{courseId} {
        allow read: if true;
        allow write: if false;
      }
      match /sections/{sectionId} {
        allow read: if true;
        allow write: if false;
      }
      match /modules/{moduleId} {
        allow read: if true;
        allow write: if false;
      }
    }
  }
}

Firebase Cloud Function WebHook

Within the directory functions->src_index.ts you can now update this file with the below code. Making sure to replace 'YOURKEY' with the key from your sanity project id found in settings.

import * as admin from 'firebase-admin';
admin.initializeApp();

import * as functions from 'firebase-functions';
export const db = admin.firestore();
const settings = { timestampsInSnapshots: true };
db.settings(settings);

const fetch = require('node-fetch');

export const sanityWebhookHandler = functions.https.onRequest(async (req, res) => {
  if (req.body.projectId !== 'YOURKEY') {
    res.status(500).send();
  }
  try {
    console.log(JSON.stringify(req.body));
    await getSanityData(req.body);
    res.status(200).send();
  } catch (err) {
    console.log(JSON.stringify(err));
    res.status(400).send(err);
  }
}
);

const getSanityData = async (body) => {
  console.log('Setting up client', body.projectId, );

  for(const id of body.ids.all){
    const url = https://${body.projectId}.api.sanity.io/v1/data/query/${body.dataset}?query=*[_id%20==%20$id]&$id=%22${id}%22;
    console.log(url);
    const resp = await (await fetch(url)).json();
    const {result} = resp;

    for(const item of result){
      console.log('Updating', ${item._type}/${item._id});
      await db.doc(sanity/docs/${item._type}/${item._id}).set(item, { merge: true });
    }
  }
}

Once this is complete you can run command firebase deploy.

You can then go to the Firebase Console and copy your url, you will need this later for the sanity webhook url.

TODO_UPLOAD

Sanity Setup

https://www.sanity.io/docs/webhooks

In your Sanity Console you can edit webhooks in your settings https://manage.sanity.io/projects/<your-projectid>/settings/api

You can then add your Firebase Cloud Function URL and select the dataset you would like to get updates from.

TODO_UPLOAD

Now anytime you make a change in your

Sanity Pro Tip

If you already have data in Sanity and would like to trigger all of your documents to update you can export and then import your entire dataset. Run the below commands inside of a project running sanity.

sanity dataset export something.tar.gzsanity dataset import something.tar.gz --replace

Related Articles