Skip to main content

Sidekick & Sidekick Library

The AEM Sidekick is a browser extension that turns any open document or rendered page into an EDS authoring console. It exposes Preview / Publish / Bulk actions and -- via the Sidekick Library - a plugin surface for project-specific tooling.

Sidekick: the core extension​

Install from the Chrome Web Store. After installation the Sidekick toolbar appears on any URL configured in the extension's project list.

ActionDescription
PreviewRenders the current document on *.aem.page
PublishPushes content to *.aem.live (production)
EditOpens the document source (SharePoint / Google Drive / AEM author)
DeleteRemoves the page from the Content Bus
Bulk Preview / PublishFrom a SharePoint / Drive folder, operate on many pages at once
PluginsProject-specific actions, including the Sidekick Library

Project config: tools/sidekick/config.json​

A site can configure Sidekick plugins through the Admin API Configuration Service (.../config/{org}/sites/{site}/sidekick.json) or an equivalent project setup. A typical config registers custom plugins, changes the icon, or restricts the toolbar to specific URL patterns:

tools/sidekick/config.json
{
"project": "Example",
"host": "www.example.com",
"previewHost": "main--example--example.aem.page",
"liveHost": "main--example--example.aem.live",
"plugins": [
{
"id": "library",
"title": "Library",
"environments": ["edit"],
"url": "/tools/sidekick/library.html",
"includePaths": ["**.docx**"]
},
{
"id": "tags",
"title": "Tags",
"environments": ["edit"],
"url": "/tools/sidekick/tags.html"
},
{
"id": "publish-bulk",
"title": "Publish all",
"environments": ["preview"],
"event": "publish-bulk"
}
]
}

environments controls when the plugin is shown: edit (when authoring a doc), preview (on a *.aem.page URL), live (on the live URL), or prod (on the custom domain).

Sidekick Library​

The Sidekick Library is a plugin that displays a side-panel of project-specific authoring assets - typically a block library (copy-paste examples of every block your project ships) and a tag library (the controlled vocabulary). Authors browse the library, click an item, and have it copied for pasting into their document.

The library is just an HTML page that EDS hosts at /tools/sidekick/library.html and that the Sidekick loads in a side panel.

Wiring the library​

tools/sidekick/library.html
<!doctype html>
<html>
<head>
<title>Library</title>
<script type="module" src="https://www.aem.live/tools/sidekick/library/index.js"></script>
</head>
<body>
<script>
const library = document.createElement('sidekick-library');
library.config = {
base: '/tools/sidekick/library.json',
};
document.body.prepend(library);
</script>
</body>
</html>

The library element loads library.json, commonly generated from a library.xlsx workbook under /tools/sidekick. Each sheet that starts with helix- represents a library plugin tab.

library.json - the manifest​

library.json is the JSON rendition of the Sidekick Library workbook. Configure the library page with its base path instead of hand-writing a separate manifest unless your project has a custom library loader.

A blocks source​

The helix-blocks sheet lists each block's name and the path of a document with its variations; the library renders that document and copies a variation to the clipboard.

| name | path |
|-----------|--------------------------|
| Hero | /library/blocks/hero |
| Cards | /library/blocks/cards |
| Carousel | /library/blocks/carousel |

The path column points at a Word / Docs file whose body contains the block markup and variations the library renders.

A tags source​

A tags library requires a custom plugin implementation (plugins.tags.src). With a tags plugin configured, authors can browse a controlled vocabulary sheet:

| key | value |
|-----------------|-----------------|
| topic/cloud | Cloud |
| topic/security | Security |
| audience/dev | Developers |

Authors browse and insert tags into the page metadata table without typos.

Building a custom plugin​

Beyond the library, you can ship arbitrary tools. A plugin is just an HTML page; the Sidekick opens it in a new tab (or a palette with isPalette) and, with passReferrer/passConfig, passes the page context as query parameters:

tools/sidekick/screenshot.html
<!doctype html>
<html>
<body>
<button id="capture">Screenshot this page</button>
<script type="module">
document.getElementById('capture').addEventListener('click', async () => {
// Sidekick plugins run in a separate, often cross-origin context, so
// window.parent.location is not readable directly. Register the plugin
// with passReferrer: true instead - Sidekick appends the host page's URL
// as a ?referrer= query param. Treat it as untrusted input: it is only
// ever read here, never used for redirects or filesystem paths, and the
// backend must independently validate the path it receives.
let path = '';
try {
const referrer = new URLSearchParams(location.search).get('referrer');
const referrerUrl = new URL(referrer);
if (referrerUrl.protocol === 'https:' && referrerUrl.hostname === location.hostname) {
path = referrerUrl.pathname;
}
} catch {
// Malformed or missing referrer - fall back to no path
}
const res = await fetch(`/api/screenshot?path=${encodeURIComponent(path)}`);
const blob = await res.blob();
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'screenshot.png';
a.click();
});
</script>
</body>
</html>

Register it in config.json with "url": "/tools/sidekick/screenshot.html", "passReferrer": true, "isPalette": true (so it opens in a panel instead of a new tab), and an appropriate environments list. On the backend, /api/screenshot must independently validate the path query parameter (reject anything that is not a same-site path) rather than trusting the client.

Tips​

  • Theme the library to match the project. The custom element accepts CSS variables
    • override them in library.html.
  • Restrict environments - a destructive plugin (e.g. "Delete all") should be confined to specific environments and ideally guarded by a confirm dialog.
  • Use the Admin API (helix5) for plugin actions that must affect the Content Bus rather than the document source.

See also​