New! Deliver web projects 10x faster. Get the free enterprise paper

By Sarah Drasner in Guides & Tutorials

Creating and using your first Netlify Build Plugin

Have you ever felt like you weren’t sure if your boss really knew how productive you were? What if you could somehow automate this troublesome task? Have no fear! In this tutorial, we’ll learn how to text your boss every time your site deploys so they know you’re busy working!

We’ll walk through how to set this up with the brand new Netlify Build Plugins, starting with the very basics of how it works. We’ll go through a basic implementation using Twilio and some environment variables to text someone after a deploy has completed. Let’s get started!

What is a build plugin?

A Netlify Build Plugin allows you to write custom scripts that are invoked at particular points when Netlify is building and deploying your site. What’s nice about them is that they are just a regular JavaScript object, so the usage is fairly straightforward.

There are a number of events available:

  • init: when the build starts
  • getCache: fetch the last build’s cache
  • install: when the project’s dependencies are installing
  • preBuild: runs directly before building the functions and running the build commands
  • functionsBuild: runs when the serverless functions are building, if they exist on the site
  • build: when the build commands are executing
  • package: package it to be deployed
  • preDeploy: runs before the built package is deployed
  • saveCache: save cached assets
  • finally: build finished, site deployed 🚀

This can help automate workflows and tasks, manage notifications, and kick off events that can have a ton of different purposes! You can use what’s available from others in the community, share yours, or create your own. The sky’s the limit to what you can create, making your builds flexible to incorporate so much innovation.

We’re currently only opening it up to a private invite-only beta, but if you’d like an invite, you can apply here.

Writing a Build Plugin

If you look at the list above, you can imagine for a lot of scenarios, we’ll hook into init, or finally, depending on what we’re building. The simplest possible implementation would go like this:

function netlifyPlugin(conf) {
  return {
    // Plugin Name
    name: 'my-first-plugin',
    // Hook into lifecycle
    finally: () => {
      console.log("site build finished, site deployed! 🚀")
    }
  }
}

module.exports = netlifyPlugin

Then, if you want to run it in a local folder to test it, in your netlify config file add:

plugins:
  # Local plugin
  - type: ./plugins/exampleplugin

Your site directory would now look like this:

plugins
-- exampleplugin
---- index.js
---- package.json
-- src
---- index.html (or whatever your dev setup is)
netlify.yml (this could also be .toml or .json)

Here’s an example: https://github.com/netlify/build/tree/master/packages/netlify-plugin-twiliosms

Or, if you want to enable many people to use it, you can publish the package to NPM, install it normally: npm i netlify-plugin-examplename, and then your netlify config file would look like this:

plugins:
  # Plugin from NPM
  - type: netlify-plugin-examplename

Writing our Simple Twilio Build Plugin

First, we want to install the twillio package, and then require it in our plugins/netlify-plugin-twiliosms index file:

npm i twilio

In plugins/netlify-plugin-twiliosms/index.js:

const Twilio = require("twilio")

Then we want to provide our plugin with our Account SID and Auth token. We don’t want to commit these to GitHub, so we create environment variables to use them in the project. We also want to get the Twilio testing phone number from the dashboard:

Twilio dashboard

And then login to netlify, go to my site, and add them in Settings > Deploys > Environment (or go to this URL and replace the site ID: https://app.netlify.com/sites/YOUR-SITE-NAME/settings/deploys#environment

  • ACCOUNT_SID – Your Account SID from www.twilio.com/console
  • AUTH_TOKEN – Your Auth Token from www.twilio.com/console
  • TO_NUM – The number you’ll be texting, should be formatted like this: “+1650XXXXXXX”
  • FROM_NUM – The number you’ll be texting from, must be a valid Twilio number, should be formatted like this: “+1650XXXXXXX”

You can see I’ve also added that I want to use the lifecycle trial here, though this will probably be removed in the future.

Now, I’ll add those environment variables to my index file, this is how I can access them:

const {
  env: {
    // Your Account SID from www.twilio.com/console
    ACCOUNT_SID,
    // Your Auth Token from www.twilio.com/console
    AUTH_TOKEN,
    // Text this number
    TO_NUM,
    // From a valid Twilio number
    FROM_NUM
  }
} = require('process')

Great! Now we can kick off the plugin, using the finally hook. We’ll kick things off by passing our environment variables into the Twilio context:

module.exports = {
  name: 'twilio-notifier-plugin',
  async finally() {
    console.log('Finish the build up, prepping to text!')

    const client = new Twilio(ACCOUNT_SID, AUTH_TOKEN)
  }
}

We’ll add our message by giving it a body, and stating what number it goes to, and which it is from (this is your Twilio provided number).

module.exports = {
  name: 'twilio-notifier-plugin',
  async finally() {
    console.log('Finish the build up, prepping to text!')

    const client = new Twilio(ACCOUNT_SID, AUTH_TOKEN)

    const { sid } = await client.messages.create({
      body: 'Hi there, we just deployed the site successfully!',
      to: TO_NUM,
      from: FROM_NUM
    })
    console.log(sid)
  }
}

In this case, the TO_NUM is potentially the number of your boss. In my case, my boss is Netlify’s cofounder and as funny as this joke is I might not want to bother him too much 😳So instead, I’ll use this opportunity to text my colleague, Phil Hawksworth! I’m sure he likes that.

SMS notification of a successful deploy

Using the config

Not all build plugins are going to be sensitive enough to need environment variables, but you may still need to pass in some data to be used in the plugin that will change per site.

Check out this SVG optimizer I’m currently working on, complete with the demo and deploy site: https://svgoptimizer-build-plugin.netlify.com/, https://github.com/sdras/netlify-build-plugin-svgoptimizer

The asset folder will likely change depending on what kind of site you’re building- for instance, asset directories in Vue CLI are in a different location than an Eleventy site, and so on. Here, you can see in my netlify config file, I’m going to let the optimizer which directory to optimize assets in. The config options look like this in that netlify.yml file:

plugins:
  # svgOptimizer local plugin
  - type:./plugins/netlify-plugin-svg-optimizer
    config:
      src: /src/assets/

From a user perspective, passing in a different directory if this changes. From the perspective of developing the plugin itself, here’s how I’m able to use this in the optimizer:

function netlifyPlugin(config) {
  return {
    name: 'svg-optimizer',
    init: config => {
      const srcDirectory = config.pluginConfig.src.directory
      if (!srcDirectory)
        return console.log(`No src found in ${pkg.name} plugin config`)
      const directoryPath = path.join(__dirname, `../../${srcDirectory}`)

You can see how all of our config options will hang off config.pluginConfig, and we can designate the object or array traversal from there with how the yaml is formatted.

Using a Build Plugin

If you’re not interested in writing a build plugin but rather, using someone else’s, you can install it via NPM. We would do this like so:

npm i examplepluginname or yarn add examplepluginname

And then make reference to it in our netlify config as we did earlier:

plugins:
  # Path within node_modules
  - type: examplepluginname

Or if we had options we needed to pass in:

plugins:
  # Path within node_modules
  - type: examplepluginname
    config:
      tacos: pollo

As this capability is currently only available to those participating in our private beta, you’ll need to have applied, and been invited to the beta, before we enable this for your builds.

Wrapping up

Using build plugins to automate tasks can help us be more productive overall, and writing them can be an incredible amount of fun. (When I first started playing with them I wrote 3 in one night).

You can check out some of the plugins that have already been created so far, or if you’d like to write your own and open source it, let us know so we can check it out and perhaps feature you!