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:
|
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:
|
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:
id
(string) is mandatory and must be unique within a sidekick configuration.title
(string) will be shown on the plugin button.titleI18n
(object<string, string>) defines optionally translated titles.pinned
(boolean) determines if the plugin is pinned to the toolbar (default) or folded into the … menu.environments
(string[]) specifies where the plugin should appear (dev, edit, admin, preview, live, or prod).exclude_paths
(string[]) defines patterns to exclude the plugin based on the path in the current tab’s URL.include_paths
(string[]) defines patterns to include the plugin based on the path in the current tab’s URL.
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.
isPalette
(boolean) opens the target of a URL-based plugin in a palette instead of a new tab.paletteRect
(string) optionally defines the size and position of the palette in the format of a DOMRect.
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.
isContainer
(boolean) renders a plugin as a dropdown instead of a button.containerId
(string) adds a plugin to a container plugin with the specified ID.
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.
isBadge
(boolean) renders a plugin as a badge instead of a button.badgeVariant
(string) optionally determines the badge’s color scheme (gray, red, orange, yellow, chartreuse, celery, green, seafoam, cyan, blue, indigo, purple, fuchsia, or magenta)
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
(string) set the label visible to the usereditUrlPattern
(string) defines an URL pattern for the custom editing environment. Supports placeholders like{{contentSourceUrl}}
or{{pathname}}
.
{
"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:
- Create a copy of your site in the Configuration Service. For example, if the name of your original site is
site1
, you could create asite1-dev
, reusing the same code and content. - Open the preview URL for
site1-dev
in your browser:https://main--site1-dev--org.aem.page
. - Make your desired changes to the sidekick object in the
site1-dev
configuration. - Refresh the browser tab after each change to test your changes.
- When done, copy the sidekick object from
site1-dev
to thesite1
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:
- On your site’s GitHub repository, create a branch from
main
. For this example, we’ll usedev
as the branch name. - Open the preview URL for the
dev
branch in your browser:https://dev--site1--org.aem.page
. - Open or create the following file in your repository:
/tools/sidekick/config.json
. - Make your desired changes to the sidekick configuration file and push changes to the
dev
branch. - Refresh the browser tab after each change to test your changes.
- 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.