Developing for the Sidekick

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 aem-sidekick (string) The path(s) of the previewed resource The Preview button has been clicked.
updated aem-sidekick (string) The path of the updated resource The Reload button has been clicked.
published aem-sidekick (string) The path of the published resource The Publish button has been clicked.
deleted aem-sidekick (string) The path of the deleted resource The Delete button has been clicked.
unpublished aem-sidekick (string) The path of the unpublished resource The Unpublish button has been clicked.
env-switched aem-sidekick

(object) An object with the following properties:

  • (string) sourceUrl: The source URL
  • (string) targetUrl: The target URL
The user has switched the environment.
plugin-used aem-sidekick (string) The plugin ID A plugin button has been clicked
logged-in aem-sidekick (object) The profile object The user has signed in.
logged-out aem-sidekick (object) The profile object The user has signed out.
status-fetched aem-sidekick (object) The status object The status for a resource has been fetched from the Admin API
custom:<name> aem-sidekick

(object) An object with the following properties:

  • (object) config: The sidekick configuration
  • (object) location: The location object
  • (object) status: The status object
A custom event-based plugin button has been clicked.

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('aem-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('aem-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.mydomain.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

The following properties are applicable to all plugin types:

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('aem-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('aem-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"]
    }
  ]
}

Custom Edit URLs

If your project does not use SharePoint or Google Drive as content source, you can tell the sidekick how to link to your custom editing environment when the user clicks Edit.

The following two config options are available:

{
  "editUrlLabel": "Your Editor",
  "editUrlPattern": "{{contentSourceUrl}}{{pathname}}?cmd=open"
}

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">
  <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);
}

Development Workflow

The following workflows are designed for detached sidekick development to prevent unintentional disruptions for the authors on your production site:

Using a Site Copy

If your site’s configuration is stored in the Configuration Service, you can use temporary site copies for sidekick development:

  1. Create a copy of your site in the Configuration Service. For example, if the name of your original site is site1, you could create a site1-dev, reusing the same code and content.
  2. Open the preview URL for site1-dev in your browser: https://main--site1-dev--org.aem.page.
  3. Make your desired changes to the sidekick object in the site1-dev configuration.
  4. Refresh the browser tab after each change to test your changes.
  5. When done, copy the sidekick object from site1-dev to the site1 configuration to roll your changes out to all authors.

Note: When using the sidekick in an editor environment (Google Drive or Microsoft Sharepoint), it will load the config from the original site by default. If you want the sidekick to let you choose which configuration to load, first add the new site to your sidekick from the preview or live URL. Now the sidekick will display a picker with all matching sites.

Using a Repository Branch

If your site’s configuration is not stored in the Configuration Service, you can use a branch in GitHub for sidekick development:

  1. On your site’s GitHub repository, create a branch from main. For this example, we’ll use dev as the branch name.
  2. Open the preview URL for the dev branch in your browser: https://dev--site1--org.aem.page.
  3. Open or create the following file in your repository: /tools/sidekick/config.json.
  4. Make your desired changes to the sidekick configuration file and push changes to the dev branch.
  5. Refresh the browser tab after each change to test your changes.
  6. When done, create a pull request and merge the changes to the main branch of your repository.

Caution: Never commit directly to the main branch in your original repository. Always create a branch and ask for a review of your changes via pull request before merging into main.

Note: When using the sidekick in an editor environment (Google Drive or Microsoft Sharepoint), it will load the config from the original site by default. If you want the sidekick to let you choose which configuration to load, first add the new site to your sidekick from the preview or live URL. Now the sidekick will display a picker with all matching sites.