How To Build A Plugin With Gridsome
Tags: jamstack, vue, cms
Published: 2020-02-26 07:10:36

> This article was originally published on [ButterCMS Blog](https://buttercms.com/blog/how-to-build-a-plugin-with-gridsome) 

1. [What is Gridsome?](## What is Gridsome?)
2. [Creating Gridsome Source Plugin](## Creating Gridsome Source Plugin)
3. [Plugging in the Butter CMS](## **Plugging In ButterCMS**)
4. [Using the ButterCMS Plugin in a Gridsome App](## Using the ButterCMS Plugin in a Gridsome App
)
5. [Wrapping Up](## Wrapping Up)

[ButterCMS](https://buttercms.com/) is a headless CMS that lets you manage content using the dashboard and integrate it into your tech stack of choice with the available content APIs. In this tutorial, We are going to go through the process of building a Gridsome Source Plugin for ButterCMS from scratch.

## What is Gridsome?
![Gridsome Landing Page](https://paper-attachments.dropbox.com/s_245C3D024B659F0B91AE94F53E4F0847FADEBC961C647B3D9F1D3B7CC9C096BA_1578673956055_Screenshot+2020-01-10+at+5.32.24+PM.png)


[Gridsome](https://gridsome.org/) is a Vue-powered static site generator that enables you to build blazing fast web applications and websites. Gridsome has a central data layer that uses GraphQL to plug in data from different sources i.e. Headless CMS, Local Files, and Traditional API’s. Gridsome is the direct equivalent of [Gatsby](https://gatsbyjs.org/), which is used in React applications.
Gridsome allows us to fetch data from local files or external APIs and headless CMS and store the data in a GraphQL layer that lets us extract only the data we need and use it our Vue.js components.

## Creating Gridsome Source Plugin

Now we know what Gridsome entails and what we need it for, we can go ahead and create our source plugin, and for this, we’ll be creating a source plugin for ButterCMS. The reason behind creating this plugin is to manage the content used in Gridsome website or web application with ButterCMS this way we’ll be handling all our content on ButterCMS and using the butter source- plugin to consume the data in our Gridsome website through the GraphQL layer. [**Gridsome Data Store API**](https://gridsome.org/docs/data-store-api/) lets you insert your data into the GraphQL data layer. You will then be able to access it through GraphQL in your components. That is the idea we want to be able to achieve, and by the end of this tutorial, we’ll have a source plugin ready for use. To get more information on how to create Gridsome plugins the [documentation](https://gridsome.org/docs/how-to-create-a-plugin/) covers it.

**Setting Up The Plugin Environment** 
The first step to take when building a Plugin with Gridsome is to set up the environment and to do this we’ll need to set up our project by first creating a folder for this project called `gridsome-source-buttercms` and then running the `npm init` command to initialize a new project this will create a `package.json` file in our root directory.

```json

{
      "name": "gridsome-source-buttercms",
      "version": "1.0.0",
      "description": "Source plugin for pulling blog posts, authors, categories, tags, and content fields into Gridsome from ButterCMS.",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "repository": {
        "type": "git",
        "url": "git+https://github.com/lauragift21/gridsome-source-buttercms.git"
      },
      "author": "Gift Egwuenu <laurandidi21@gmail.com>",
      "license": "MIT",
      "keywords": [
        "gridsome",
        "gridsome-plugin",
        "buttercms",
        "vuejs",
        "gridsome-source-plugin"
      ],
      "bugs": {
        "url": "https://github.com/lauragift21/gridsome-source-buttercms/issues"
      },
      "homepage": "https://github.com/lauragift21/gridsome-source-buttercms#readme",
      "dependencies": {
    
      }
    }
```

Note that for your plugin to get picked by [Gridsome Plugins](https://gridsome.org/plugins) you need to add the `gridsome-plugin` keyword to your `package.json.` Right after creating our package.json file, we will need to add the project directory to GitHub so we can easily sync and track changes. Go ahead and create a new repository for this project with the latest changes added and pushed to Github.

## **Plugging In ButterCMS**
Now we have that setup, the next step is to start building the plugin, we’ll be required to install the `buttercms` npm package with the command:


  ```
    npm install buttercms
  ```

Right after installing ButterCMS, Go ahead and create an `index.js` file this is where all the functionality for the plugin will be located. Note that you can also create a source plugin within a `gridsome.server.js`  file but for the sake of this tutorial I’ll be sticking to the `index.js`. Now within the `index.js` file, import `buttercms` package.


```js     
const buttercms = require('buttercms')
```

When creating a source plugin it is required that we use the [Data Store API](https://gridsome.org/docs/data-store-api) from Gridsome that allows us to plug our own external data into GraphQL data layer. We will be working with the following APIs from ButterCMS: [Pages](https://buttercms.com/docs/api/?javascript#pages), [Collections](https://buttercms.com/docs/api/?javascript#collections) and [Blog Engine](https://buttercms.com/docs/api/?javascript#blog-engine).
Let’s go ahead and add the following to our `index.js` as a base for the plugin functionality we are going to create.


```js
    const ButterCMS = require('buttercms');
    
    class ButterSource {
     static defaultOptions() {
        return {
          authToken: process.env.GRIDSOME_BUTTER_AUTHTOKEN || process.env.BUTTER_AUTHTOKEN,
          collections: [''],
          pages: '',
          pageTypes: '',
          typeName: 'Butter'
        };
      }
      constructor(api, options = ButterSource.defaultOptions()) {
        this.api = api;
        this.options = options;
        this.client = ButterCMS(options.authToken, false, 20000);
        if (!options.authToken) throw new Error('ButterSource: Missing API Key');
        api.loadSource(async actions => {
          console.log('Processing data...');
          await this.allButterPosts(actions);
          await this.allButterCollections(actions);
          await this.allButterPages(actions);
        });
      }
    }
```

I understand a lot is going on in the code block above but I will go ahead and explain what’s going on to you so you understand where we are at.


1. First, install `buttercms` and import it within the `index.js` file.
2. Next, create a Class method called `ButterSource`  where we’ll be defining all the functionality for this plugin.
3. In order to gain access to `ButterCMS API` we need an **API key** which can be found in your ButterCMS Dashboard. Store the API key in a `.env` file with `BUTTER_AUTHTOKEN` variable. [Gridsome](https://gridsome.org/docs/environment-variables/) suggests we keep variables prefixed with `GRIDSOME_` so they are available in the browser for security reasons.
4. Create a method called `defaultOptions` which we use to configure the plugin.
5. We define a function and pass `api` and `defaultOptions` as parameters and then initialize ButterCMS and also include a check to make sure the `API key` is present.
6. Then we map our data from the API to GraphQL we need to use the `api.loadSource()` hook
7. Finally, we have three methods `allButterPost()`, `allButterCollections`, and `allButterPages`. These method will be the source where we’ll be adding functionality from ButterCMS API.

**Add Butter Posts**
Here what we are trying to achieve is to create a query where we can view a full list of all posts created using ButterCMS.  The first step is query the REST API and return the posts, then call `actions.addCollection` method which is used to add a collection to the GraphQL schema. In this case, `allButterPosts` and `butterPosts` respectively.

```js
      async allButterPosts(actions) {
        const post = await this.client.post.list()
        const  { data } = post.data;
        const contentType = actions.addCollection({
          typeName: this.createTypeName("posts")
        });
        for (const item of data) {
          contentType.addNode({
            ...item
          });
        }
      }
```
**Adding Butter Collections**
Collections are tables of data to be referenced by Pages, we use `allButterCollections` to retrieve collections.

```js
     async allButterCollections(actions) {
        const collection = await this.client.content.retrieve(this.options.collections)
        const { data } = collection.data;
        const contentType = actions.addCollection({
          typeName: this.createTypeName('collection')
        });
        contentType.addNode({
          data
        })
      }
```
**Adding Butter Pages**
ButterCMS allows you to create pages. The fields of a page are defined by you, they are customizable. We can retrieve a single page or multiple pages using Page Types depending on how it is setup. Here `allButterPages` is configured in a way that you can retrieve either single or multiple pages by checking the options provided in the config.

```js
    async allButterPages(actions) {
        if (this.options.pages || this.options.pageTypes) {
          if (this.options.pages) {
            const page = await this.client.page.retrieve('*', this.options.pages)
            const { data } = page.data;
            const contentType = actions.addCollection({
              typeName: this.createTypeName('pages')
            });
            contentType.addNode({
              slug: data.slug,
              page_type: data.page_type,
              data: data.fields
            })
          }
          if (this.options.pageTypes) {
            const page = await this.client.page.list(this.options.pageTypes)
            const { data } = page.data;
            const pageTypeName = data.map(pages => {
              return pages.page_type
            })
             const contentType = actions.addCollection({
              typeName: this.createTypeName(pageTypeName[0])
            });
            for (const item of data) {
              contentType.addNode({
                slug: item.slug,
                page_type: item.page_type,
                data: item.fields
              })
            }
          }
        }
      }
```
## Publishing ButterCMS Plugin

Now that we have successfully built the plugin, it’s time to publish to [npm](https://www.npmjs.com/).  Remember the first step we took in building out this plugin was to initialize a new project using `npm init`. Right, so now that we have to publish this package we need to run through the following to make sure everything looks great and is available as a public npm package. If you have never used [npm CLI](https://docs.npmjs.com/cli-documentation/) before you can run the `[npm adduser](https://docs.npmjs.com/cli/adduser.html)` command to add a registry user account. But if you already completed that step, you can move to the next which is to ensure you are logged in using this command.

```bash
    npm login
```
You will be prompted to enter your username, password and email address. Once you are logged in you can confirm using the command `npm whoami`. The last step is to publish the plugin using the command:

```bash
    npm publish
```
This command publishes the buttercms package to the registry and it can be installed by the package used `gridsome-source-buttercms`.

```bash
    npm install gridsome-source-buttercms
```

## Using the ButterCMS Plugin in a Gridsome App

We now have a published plugin we can use within our Gridsome app, let’s take a look at how to go about setting it up when we need to use it. First, we need to install the plugin with this command
```bash

    npm install gridsome-source-buttercms
    or 
    yarn add gridsome-source-buttercms
```
After installing the plugin, we can go ahead and configure it within the `gridsome.config.js` file.

```js
    module.exports = {
      siteName: 'Gridsome',
      plugins: [
        {
          use: "gridsome-source-buttercms",
          options: {
            authToken: process.env.GRIDSOME_BUTTER_AUTHTOKEN || process.env.BUTTER_AUTHTOKEN,
            collections: [''],
            pages: '',
            page_type: ''
          }
        }
      ]
    }
```
With that configured, we can now have our content from buttercms in our GraphQL layer. Go ahead and run `gridsome develop` to start the server and navigate to GraphQL playground, you should be able to run queries from buttercms in the documentation section.


![](https://paper-attachments.dropbox.com/s_245C3D024B659F0B91AE94F53E4F0847FADEBC961C647B3D9F1D3B7CC9C096BA_1562942669041_dz2vBHjJQH.gif)

## Wrapping Up

In this article, we walked through how to create a [source plugin for Gridsome](https://github.com/ButterCMS/gridsome-source-buttercms) and outlined steps to take when we want to publish the plugin for final use. The benefits of using modern, headless CMS over having our website content within the main application is vital and in general, it improves the workflow and performance of the application. 


> You can [add ButterCMS to your Gridsome App in minutes](https://buttercms.com/gridsome-cms/)