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:
|
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:
|
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
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.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('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.
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"]
}
]
}
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);
}