Tool Plugin

Tools are a different way to extend your visual editor. They allow you to improve your productivity by adding some functionality to the editor. Two examples of Tools are importing and exporting content or a custom clipboard.

Tools are specific to stories and will appear in your Visual Editor when editing a story.

Tool Plugin

Getting Started

To create a new tool you need to be signed up as a Partner. Head into the partner portal and click on Apps {1} and then the New button {2}. As App type select Tool {3} and click Create {4}.

Create new tool

To get started we will clone the tool plugin starter template: github.com/storyblok/storyblok-tool-example

$ git clone https://github.com/storyblok/storyblok-tool-example.git
$ cd storyblok-tool-example
$ npm install 

We will also need to install ngrok to create a tunnel to our local application. Once you installed ngrok, you can start the tunnel to port 3000.

$ npm i -g ngrok
$ ngrok http 3000

After starting the tunnel you will need to add the tunnel URL to the development settings in your tool settings, like in the image below. You need a URL to the app, e.g. the tunnel URL + auth/connect/storyblok{3} and an Oauth2 callback, e.g. the tunnel URL + auth/callback{4}.

Tool Settings

Inside the starter, you will find a .env-example file. Rename this file to .env and fill in the client id {1} and client secret {2} as well as the Oauth2 callback {4}.

.env.local

CONFIDENTIAL_CLIENT_ID="Id from Storyblok App"
CONFIDENTIAL_CLIENT_SECRET="Secret from Storyblok App"
CONFIDENTIAL_CLIENT_REDIRECT_URI=https://YOUR_ID.ngrok.io/auth/callback

Now we can start our development server:

npm run dev

Now if you open http://localhost:3000/ it should redirect to Storyblok, but nothing happens. In order to test it, we first need to install our tool plugin in a specific space. Open any space click on Apps {1}, My apps {2}, and then on the new tool {3}.

Install Plugin

Then click Install {1} and open a Story within that Space.

Plugin Install

Now go back into Content and open a Story, e.g. Home. The first time you should see a confirmation screen to authorize the application to have access to Storyblok. Click Approve {1}.

Storyblok App Confirmation

Once you authenticate your tool you should be able to see it {2} within the Tools {1} section in the editor.

Tool in Space

Reading the Story Context

Inside a tool, you can use the context to get the data of the current story. For that you have to use two window events: message and postMessage.

First, we let Storyblok know that there is a tool via the following event. Make sure that name of the tool you created matches the name in the tool parameter.

window.parent.postMessage({
  action: 'tool-changed', 
  tool: 'storyblok@first-tool', 
  event: 'getContext'
}, 'https://app.storyblok.com')

After that Storyblok will reply with the Story context, so we need to listen for that with the following listener:

 window.addEventListener('message', this.processMessage, false)

Finally, we need to connect everything and add the processMessage method to set our local component data:

export default {
  data() {
    return {
      story: {},
      loadingContext: true
    }
  },

  mounted() {
    // redirects you to Storyblok
    if (window.top === window.self) {
      window.location.assign('https://app.storyblok.com/oauth/tool_redirect')
    }
    // listens for Storyblok answer
    window.addEventListener('message', this.processMessage, false)
    // Use getContext to get the current story
    window.parent.postMessage({action: 'tool-changed', tool: 'storyblok@first-tool', event: 'getContext'}, 'https://app.storyblok.com')
  },
  methods: {
    processMessage(event) {
      // processes the event answer
      if (event.data && event.data.action == 'get-context') {
        this.loadingContext = false
        // get the context story
        this.story = event.data.story
        // get the context language
        this.language = event.data.language
      }
    }
  }
}

Changing the Height of the Tool

It's possible to change the height of the tool by sending an event with the name heightChange with a height parameter to the parent window

window.parent.postMessage({
  action: 'tool-changed',
  tool: 'storyblok@first-tool',
  event: 'heightChange',
  height: 500}, 
'https://app.storyblok.com')

Reading the Editor Language

It's possible to get the current language from the get-context event.

export default {

  mounted() {
    window.addEventListener('message', this.processMessage, false)
    window.parent.postMessage({action: 'tool-changed', tool: 'storyblok@first-tool', event: 'getContext'}, 'https://app.storyblok.com')
  },
  methods: {
    processMessage(event) {
      if (event.data && event.data.action == 'get-context') {
        this.language = event.data.language
      }
    }
  }
}

Changing Content via the API

Tools work with the storyblok-nuxt-auth module to retrieve and change data from Storyblok via the Storyblok Management API. Inside of a tool you can get for example the user information with the following request:

axios.get('/auth/user', {params: {space_id: this.$route.query.space_id}})
      .then((response) => {
        console.log(response.data)
      })

You can also change stories inside of Storyblok by making post or put requests. You can create for example a new story with the following code:

import axios from 'axios'

export default {
  data() {
    return {
      loading: false,
      story: {
        name: ''
      }
    }
  },
  methods: {
    createStory() {
      this.loading = true

      // The request body is the same from Management API
      // https://www.storyblok.com/docs/api/management#core-resources/stories/create-story
      const body = {
        story: { ...this.story }
      }

      // get the space id from URL and use it in requests
      return axios
        .post(`/auth/spaces/${this.$route.query.space_id}/stories`, body)
        .then((res) => {
          this.loading = false
        })
      }
  }
}