Tool Plugins
Tool plugins allow you to extend Storyblok's Visual Editor by adding new tool windows with custom functionality. These are standalone applications that are embedded within iframes, which communicate with Storyblok by means of cross-window communication, and via the Management API.
Tools can contain any functionality, but they are most useful when they do things that relate to the story that is being edited in the same context. Some example areas of application are to:
- Analyze content
- Transform content
- Perform actions on the content
Some concrete examples are the following tools, which are to be found in the app directory:
Tool plugins are in principle very similar to custom sidebar applications. The difference is where in the application they are embedded, and what frontend features they have access to. For example, tools are embedded in the Visual Editor and can read the story that is currently being edited; while custom sidebar applications do not have such capability.
Create a Tool Plugin
To create a tool plugin, follow the tutorial on how to create a new plugin. When asked which type, select Tool.
When you have completed the entire tutorial and gotten the starter to run, enter the Visual Editor, and click open the tools tab to see the result.
The first time the tool is opened, an admin will need to approve it.
You may need to navigate back to the Visual Editor again, where you should see the plugin:
Integrate with the Visual Editor
At this point, the plugin that you have just created is just a standalone application that happens to be embedded within Storyblok. Next, you will connect it to the Storyblok frontend application by using window.postMessage
.
Setting the Height
All tools that are installed on a space appears in a vertical list–they are stacked on top of each other. The iframe windows that embed the tools have a height that is set in pixels. However, a tool will change its height during its lifecycle; for example, on the initial load. When that happens, the tool needs to notify the Visual Editor that the iframe element's height should be updated. Do this by sending a heightChanged
message to the Visual Editor:
window.parent.postMessage({ action: 'tool-changed', tool: 'my-tool-plugin-name', event: 'heightChange', height: 500 }, '*')
In the example above, the height is set to 500px
. The tool
property must match the slug that is defined in the plugin settings.
Since tools are stacked on top of each other, a tool that takes up a lot of vertical space might obfuscate tools that appear underneath it. It's not possible to decide which order tools appear in. Therefore, it is recommended to not use too much vertical room for tools.
Automatic Height
To automatically set the height of the tool plugin, register a ResizeObserver
that updates the iframe element's height whenever the tool plugin's document height is mutated:
First, ensure that the html
element's height is not set to 100vh
:
In one of your components, register the ResizeObserver
:
Remember to clean up the side-effect whenever the component unmounts:
Reading the Story
Tools can read the story object that is being edited in the Visual Editor.
In one of the components, set up an event listener:
Don't forget to also clean up the side effect (when the component unmounts):
After the event listener has been registered, send a message to request the context:
The Visual Editor will reply by sending the context in a message to the plugin application. This message includes the story and the language of the story. Following the example above, you will see a message of the following structure in the console:
{ "action": "get-context", "story": { "name": "hello444", "uuid": "45bbd2c4-b418-4737-8f4f-d893ec1f7f10", "content": { ... }, ... }, "language": "" }
Integrate with the Management API
Server-side code is able to send requests to the Management API. To do this, read the accessToken
and spaceId
from the http.IncomingMessage
:
Note that @storyblok/app-extension-auth
, which is included in all starters, appends the storyId
and spaceId
as query parameters whenever a page is loaded (in req.query
). These are used to read the accessToken
and region
from the session store.
Using these values, you can perform requests with the Management API; for example:
All starter projects include a similar example.
You can use the Management API to update the current story. However, this change will not automatically be reflected in the Visual Editor, so you will need to instruct the user to manually refresh the window.