Sidekick for Developers

The goal of this document is to explain how developers can interact with the sidekick, and how it can be customized at a project level.

Events

The sidekick emits the following events:

Event Name Target Element Payload Description
sidekick-ready document - The sidekick element has been added to the DOM and is ready for use.
previewed helix-sidekick (string) The path(s) of the previewed resource The Preview button has been clicked.
updated helix-sidekick (string) The path of the updated resource The Reload button has been clicked.
published helix-sidekick (string) The path of the published resource The Publish button has been clicked.
deleted helix-sidekick (string) The path of the deleted resource The Delete button has been clicked.
unpublished helix-sidekick (string) The path of the unpublished resource The Unpublish button has been clicked.
envswitched helix-sidekick

(object) An object with the following properties:

  • (string) sourceUrl: The source URL
  • (string) targetUrl: The target URL
The user has switched the environment.
pluginused helix-sidekick (string) The plugin ID A plugin button has been clicked
loggedin helix-sidekick (object) The profile object The user has signed in.
loggedout helix-sidekick (object) The profile object The user has signed out.
statusfetched helix-sidekick (object) The status object The status for a resource has been fetched from the Admin API
contextloaded helix-sidekick

(object) An object with the following properties:

  • (object) location: The location object
  • (object) config: The sidekick configuration
The location and configuration have been loaded.

An event’s payload can be found in the event.detail property.

Listening for Events

In your project code (e.g. in /scripts/scripts.js), you can react to sidekick events as follows (replace foo with the name of the event you want to listen for):

const doFoo = ({ detail: payload }) => {
  console.log('something happened', payload);
  // your custom code goes here
};

const sk = document.querySelector('helix-sidekick');
if (sk) {
  // sidekick already loaded
  sk.addEventListener('foo', doFoo);
} else {
  // wait for sidekick to be loaded
  document.addEventListener('sidekick-ready', () => {
    // sidekick now loaded
    document.querySelector('helix-sidekick')
      .addEventListener('foo', doFoo);
  }, { once: true });
}

Customizing the Sidekick

You can customize the sidekick for your project. You can add a /tools/sidekick/config.json configuration file to your project's GitHub repository or use the configuration service.

{
  "project": "My project",
  "host": "www.mymydomain.prod",
  "plugins": []
}

For all available configuration options, see the config schema. Here are some basics to get you started:

Plugins

Plugins allow you to add custom functionality to the sidekick, enhancing your users’ experience.

Common Plugin Properties

URL-based Plugins

You can specify a url that will be opened in a new tab when the plugin button is clicked:

{
  "plugins": [
    {
      "id": "foo",
      "title": "Foo",
      "url": "/tools/sidekick/foo.html"
    }
  ]
}

Event-based Plugins

Alternatively, you can specify the name of an event to be fired when the plugin button is clicked. This allows the execution of custom JavaScript code in the context of your page by listening for the event on the sidekick element. Custom events will have a custom: prefix. For your convenience, the custom event dispatched contains a copy of the current sidekick state.

Note: Event-based plugins can only be used in the following environments: Development, Preview, Live and Production. Executing custom code is not possible in Edit or Admin.

{
  "plugins": [
    {
      "id": "foo",
      "title": "Foo",
      "event": "foo"
    }
  ]
}

In your project code (e.g. in /scripts/scripts.js), you can react to the event as follows:

const doFoo = ({ detail: payload }) => {
  console.log('a custom event happened', payload);
  // your custom code goes here
};

const sk = document.querySelector('helix-sidekick');
if (sk) {
  // sidekick already loaded
    sk.addEventListener('custom:foo', doFoo);
} else {
  // wait for sidekick to be loaded
  document.addEventListener('sidekick-ready', () => {
    // sidekick now loaded
    document.querySelector('helix-sidekick')
      .addEventListener('custom:foo', doFoo);
  }, { once: true });
}

Special Plugin Types

Palette Plugins

Palettes are variants of URL-based plugins which load the configured URL inline instead of opening a new tab.

The following example creates a standard palette placed at the bottom left of the window:

{
  "plugins": [
    {
      "id": "tools",
      "title": "Tools",
      "url": "/tools/sidekick/foo-palette.html",
      "isPalette": true
    }
  ]
}

If you wish to change the size and positioning of your palette, use paletteRect:

{
  "plugins": [
    {
      "id": "tools",
      "title": "Tools",
      "url": "/tools/sidekick/foo-palette.html",
      "isPalette": true,
      "paletteRect": "top:150px;left:7%;height:675px;width:85vw;"
    }
  ]
}

Container Plugins

Containers allow you grouping plugins together and help save space in the toolbar. Clicking a container plugin simply toggles its dropdown, it can’t have its own URL or event action.

The following example creates a container named “Tools” and places a plugin “Foo” in it:

{
  "plugins": [
    {
      "id": "tools",
      "title": "Tools",
      "isContainer": true
    },
    {
      "id": "foo",
      "containerId": "tools",
      "title": "Foo",
      "event": "foo"
    }
  ]
}

Badge Plugins

Badges allow you to add labels to the sidekick under certain conditions. They will be rendered on the right hand side of the toolbar. Badges have a merley decorative purpose and can’t be clicked.

The following example adds a “Stage” badge to the sidekick in the preview environment:

{
  "plugins": [
    {
      "id": "stage",
      "title": "Stage",
      "isBadge": true,
      "environments": ["preview"]
    }
  ]
}

Special Views

You can specify a special view for the sidekick to redirect to when the current tab’s URL matches a certain pattern. This can help you provide a seamless user experience across different media types, and also enables the execution of custom code (event-based plugins). The original resource URL will be available in a url query parameter.

The properties path and viewer are mandatory. Optionally, you can specify a title that will be shown at the top, and you can provide localized titles in a titleI18n object:

{
  "specialViews": [
    {
      "title": "Custom JSON Viewer",
      "path" : "**.json",
      "viewer": "/tools/sidekick/custom-json-viewer/index.html"
    }
  ]
}


At the path specified by viewer, add an HTML file to your GitHub repository, for example:

<html>
<head>
  <title>Custom JSON Viewer</title>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- inherit base styles from sidekick (if desired) -->
  <link rel="stylesheet" href="chrome-extension://ccfggkjabjahcjoljmgmklhpaccedipo/app.css">
  <!-- add your own styles -->
  <link rel="stylesheet" href="./custom-json-viewer.css">
  <!-- add your custom code -->
  <script src="./custom-json-viewer.js"></script>
</head>
  <body>
  </body>
</html>

Add an optional CSS file in the same directory, and a JS file with your custom logic, for example:

try {
  // get the resource URL from the url query parameter
  const url = new URL(window.location.href).searchParams.get('url');
  if (url) {
    const res = await fetch(url);
    if (res.ok) {
      const text = await res.text();
      const data = JSON.parse(text);
      // do something with the data, e.g.
      document.body.innerHTML = `
        <pre>
          ${JSON.stringify(data, null, 2)}
        </pre>
       `;
    } else {
      throw new Error(`failed to load ${url}: ${res.status}`);
    }
  }
} catch (e) {
  console.error('error rendering custom json view', e);
}