Storyblok
Search Storyblok's Documentation
  1. @storyblok/preview-bridge

@storyblok/preview-bridge

@storyblok/preview-bridge is Storyblok's official JavaScript bridge, enabling communication between your iframe-embedded website preview and the Visual Editor.

Requirements

StoryblokBridge can only be used in a browser environment.

  • Modern web browser (e.g., Chrome, Firefox, Safari, Edge – latest versions)

Installation

Add the package to a project by running this command in the terminal:

npm install @storyblok/preview-bridge@latest

Access StoryblokBridge in the global scope, either directly or as a property of window:

<body>
  <script>
    const storyblokBridge = new StoryblokBridge()
  </script>
</body>

Example

Here is a minimal implementation of the StoryblokBridge class. When this webpage is appears in the iframe in the Storyblok editor, it will log the current (unsaved) state of the story on every input change in the Visual Editor.

<!DOCTYPE html>
<html>

<body>
  <script>
    const storyblokBridge = new StoryblokBridge()

    storyblokBridge.on("input", ({story}) => {
      console.log(story)
    })
  </script>
</body>

</html>

Usage

StoryblokBridge()

StoryblokBridge(parameters)

The StoryblokBridge() constructor creates a bridge client to facilitate communication between the Visual Editor and an iframe-embedded website inside the editor. The constructor accepts the following optional parameters:

ParameterDescription
resolveRelations (array of strings)Accepts an array of strings representing schema relationships (e.g. ["article.author"]) to populate those relationships in data updates. Relations resolved in the API client must also be resolved in StoryblokBridge.
resolveLinks (string)Accepts "url", "link", or "story" as a string to populate those fields in data updates. Links resolved in the API client must also be resolved in StoryblokBridge.
preventClicks (boolean)Enable or prevent interactions within the preview area. Pass true (boolean) to allow normal click behavior for your project, like allowing links to navigate. Default: false.
customParent (string)Accepts a string to define the parent app for the bridge. Default: "app.storyblok.com"
fallbackLang (string)Accepts a string to correctly set the fallback language in data updates.

Example:

const storyblokBridge = new StoryblokBridge({
  resolveRelations: ["article.author", "article.category"],
  resolveLinks: "url",
  preventClicks: true,
  customParent: "https://your-storyblok-domain.com",
  fallbackLang: "de"
})

StoryblokBridge has three prototype methods, which are available on all instances:

  • on()
  • pingEditor()
  • isInEditor()

StoryblokBridge.prototype.on()

StoryblokBridge.prototype.on(event, callback)
StoryblokBridge.prototype.on(arrayOfEvents, callback)

Creates a listener to subscribe to editor events. The callback receives an event object.

StoryblokBridge.prototype.on() can listen for the following events:

  • "published" - A story is published
  • "change" - A story is saved
  • "input" - A field value is changed (returns the complete, unsaved story)
  • "enterEditMode" - Visual Editor is initialized

The shape of the event object depends on the event type. Here are example event objects for each type:

// published
{
  "reload": true,
  "action": "published",
  "slug": "home",
  "storyId": 24840769,
  "slugChanged": true
}

// change
{
  "reload": true,
  "action": "change",
  "slug": "new-article",
  "storyId": 24840764,
  "slugChanged": false
}

// input
{
  "action": "input",
  "story":  { ... }
}

// enterEditMode
{
  "action": "enterEditmode",
  "appVersion": "v2",
  "blockId": "2bc131ea-fac2-4210-b92d-c481f7f4d75b",
  "componentNames": {
    "feature": "Feature",
    "grid": "Grid",
    "page": "Page",
    "teaser": "Teaser",
  },
  "reload": true,
  "storyId": "24840769",
}

The method accepts either a single event as a string or an array of multiple events.

Here is an example that will update the DOM with the raw JSON of the story on each input:

storyblokBridge.on('input', ({ story }) => {
  document.getElementById("app").innerHTML = `
	  <pre>
		  ${JSON.stringify(story, null, 2)}
	  </pre>
  `
})

The following example will reload the page when the story is saved or published in the Visual Editor:

storyblokBridge.on(['change', 'published'], () => {
	location.reload(true)
})

StoryblokBridge.prototype.pingEditor()

StoryblokBridge.prototype.pingEditor(callback)

Returns the full StoryblokBridge instance if the preview environment is being viewed in the Visual Editor.

pingEditor() accepts a callback function, which receives a payload parameter that contains information about the state of the preview within the editor.

storyblokBridge.pingEditor((payload) => {
  console.log(payload)
})

StoryblokBridge.prototype.isInEditor()

StoryblokBridge.prototype.isInEditor(callback)

Returns true if the preview environment is viewed within the Visual Editor and false if not. This method can only run in the callback function of pingEditor().

storyblokBridge.pingEditor(() => {
  if (storyblokBridge.isInEditor()) {
    // for example: fetch draft content
  } else {
    // for example: fetch published content
  }
})