DEV Community

Jamie Barton for GraphCMS

Posted on • Updated on

Build your own granular webhooks with GraphCMS and Zeit Now

GraphCMS, a GraphQL Content Management System, has a powerful events system that can trigger webhooks to perform various external tasks. I previously wrote how you could use GraphCMS webhooks to sync content from GraphCMS to Algolia.

Redeploying websites is another great webhook use case. Since GraphCMS webhooks trigger on any change in your project, it's often a scenario many static site users face.

GraphCMS webhooks come in a variety of shapes: NOPAYLOAD, MINIMAL and EXTENDED. You'd be right in thinking NOPAYLOAD is a great webhook type to trigger a static site build, as we don't really care about the content of the webhook, but we'd probably exceed our build hours or concurrent builds quickly, as we have no way of checking if the content is externally facing.

Since we want to have granular control when a webhook is triggered, we can use the MINIMAL scope to grab the stage and fieldName values from the payload.

I've gone ahead and created a few environment variables (or secrets) for use inside my serverless function.

  • BUILD_HOOK: The build hook endpoint from Zeit or Netlify.

  • STAGE_TRIGGER: If you use different stages at GraphCMS, you might want to set this to master.

  • BUILD_TRIGGERS: The mutation names you want to trigger a build on, comma separated. E.g. createProduct, updateProduct, deleteProduct.

This function has been designed to work with Zeit Now, where we get some helpful Node helpers built-in, such as JSON.parse is automatic with req.body.

You'll need to update the function if you want to deploy it to Netlify, AWS, GCP, etc.

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

const BUILD_HOOK = process.env.BUILD_HOOK;

const STAGE_TRIGGER = process.env.STAGE_TRIGGER;

const BUILD_TRIGGERS = process.env.BUILD_TRIGGERS.split(", ");

module.exports = async (req, res) => {
  if (!req.body) return res.status(401).end();

  const {
    info: { fieldName }
  } = req.body;

  if (stageName === STAGE_TRIGGER && BUILD_TRIGGERS.includes(fieldName)) {
    await fetch(BUILD_HOOK, {
      method: "post"

    return res.status(200).end();

  return res.status(401).end();

Enter fullscreen mode Exit fullscreen mode

The function is successful if there is a req.body provided or stageName and fieldName matches our configuration.

🚀 You could extend this function by optionally checking if the content status is set to PUBLISHED.

Discussion (0)