Dev Overlay Plugin API

The Astro Dev Overlay Plugin API allows you to create plugins that can be used to extend the Astro Dev Overlay. This allows you to add new features and integrations with third-party services.

Astro Integrations can add plugins in the astro:config:setup hook using the addDevOverlayPlugin method.

integrations.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "my-integration",
hooks: {
"astro:config:setup": ({ addDevOverlayPlugin }) => {
addDevOverlayPlugin("./my-plugin.js");
},
},
});

A plugin is a .js or .ts file that default exports an object with the following required properties:

src/my-plugin.js
export default {
id: 'super-plugin',
name: 'My Super Plugin',
icon: '<svg>...</svg>',
init(canvas, eventTarget) {
eventTarget.dispatchEvent(
new CustomEvent('plugin-notification', {
detail: {
state: true,
},
})
);
}
}

A unique identifier for the plugin. This will be used to uniquely identify the plugin in hooks and events.

src/my-plugin.js
export default {
id: 'my-plugin',
// ...
}

The name of the plugin. This will be shown to users whenever the plugin needs to be referenced using a human-readable name.

src/my-plugin.js
export default {
// ...
name: 'My Plugin',
// ...
}

The icon of the plugin. This will be used to display the plugin in the UI. This can either be an icon from the icon list, or a string containing the SVG markup of the icon.

src/my-plugin.js
export default {
// ...
icon: '<svg>...</svg>', // or 'astro:logo'
}

init: (canvas: ShadowRoot, eventTarget: EventTarget) => void

Section titled init: (canvas: ShadowRoot, eventTarget: EventTarget) =&gt; void

This is the core part of the plugin. This function will be called when the plugin is loaded, which will either be when the browser is idle or when the user clicks on the plugin in the UI.

The function receives two arguments:

A ShadowRoot that the plugin can use to render its UI. Every plugin receive its own dedicated ShadowRoot for rendering its UI. Additionally, the parent element is positioned using position: absolute; and as such, the plugin UI automatically won’t affect the layout of the page.

export default {
id: 'super-plugin',
name: 'My Super Plugin',
icon: '<svg>...</svg>',
init(canvas) {
canvas.appendChild(document.createTextNode('Hello World!'))
}
}

An EventTarget that can be used to send and receive events from the dev overlay.

This optional function will be called when the user clicks on the plugin icon in the UI to toggle off the plugin. This function can be used, for example, to perform cleanup operations, do an animation, or to ask the user for confirmation before toggling off the plugin.

If a falsy value is returned, the toggling off will be cancelled and the plugin will stay enabled.

src/my-plugin.js
export default {
// ...
beforeTogglingOff() {
const confirmation = window.confirm('Are you sure you want to disable this plugin?');
return confirmation;
}
}

The ShadowRoot of the plugin, can be used to render any UI needed.

Using the eventTarget argument on the init hook, plugins can send and receive events from the dev overlay. The following events are available:

This event is fired when the user clicks on the plugin icon in the dev overlay bar.

src/my-plugin.js
export default {
// ...
init(canvas, eventTarget) {
eventTarget.addEventListener('plugin-toggled', (event) => {
if (event.detail.state === true) {
console.log("The plugin is now enabled!")
}
})
}
}

Indicates whether or not the plugin is enabled after the user’s click.

This event can be sent to inform the user that the plugin requires attention.

src/my-plugin.js
export default {
// ...
init(canvas, eventTarget) {
eventTarget.dispatchEvent(
new CustomEvent('toggle-notification', {
detail: {
state: true,
},
})
);
}
}

Indicates whether or not the plugin has a notification for the user. When true, the plugin icon will be highlighted using a red dot. Conversely, when false, the highlight will be removed. If this property is not specified, true will be assumed.

This event can be sent from your plugin to change the state of your plugin. This can be useful, for instance, to implement a “Close” button in your plugin’s UI.

src/my-plugin.js
export default {
// ...
init(canvas, eventTarget) {
eventTarget.dispatchEvent(
new CustomEvent('toggle-plugin', {
detail: {
state: false,
},
})
);
}
}

Indicates whether or not the plugin should be enabled. When true, the plugin will be enabled. Conversely, when false, the plugin will be disabled. If this property is not specified, true will be assumed.

Using Vite’s methods for client-server communication, dev overlay plugins can communicate with the server.

In addition to being able to send and receive custom messages, the dev overlay also sends the following messages, where PLUGIN_ID is the plugin’s ID:

astro-dev-overlay:PLUGIN_ID:initialized

Section titled astro-dev-overlay:PLUGIN_ID:initialized

This message is sent when the plugin is initialized. The data for this message is empty.

integration.ts
{
// ...
"astro:server:setup": ({ server }) => {
server.ws.on("astro-dev-overlay:super-plugin:initialized", () => {
console.log("My plugin was initialized!");
});
},
// ...
}

astro-dev-overlay:PLUGIN_ID:toggled

Section titled astro-dev-overlay:PLUGIN_ID:toggled

This message is sent when the user clicks on the plugin icon in the UI. The data for this message is a boolean indicating whether the plugin is enabled or not.

integration.ts
{
// ...
"astro:server:setup": ({ server }) => {
server.ws.on("astro-dev-overlay:super-plugin:toggled", (data) => {
console.log(`My plugin is now ${data.state ? "enabled" : "disabled"}!`);
});
},
// ...
}

The dev overlay includes a set of web components that can be used to build plugins with a consistent look and feel.

Shows a window.

The slot of the component will be used as the content of the window.

<astro-dev-overlay-window>
<p>My content</p>
</astro-dev-overlay-window>

When building a window using JavaScript, remember that slotted content must go inside the light DOM of the component.

const myWindow = document.createElement('astro-dev-overlay-window');
const myContent = document.createElement('p');
myContent.textContent = 'My content';
// GOOD:
myWindow.appendChild(myContent);
// BAD:
myWindow.shadowRoot.appendChild(myContent);

Shows a button.

The slot of the component will be used as the content of the button.

const myButton = document.createElement('astro-dev-overlay-button');
myButton.textContent = 'Click me!';
myButton.buttonStyle = "purple";
myButton.size = "medium";
myButton.addEventListener('click', () => {
console.log('Clicked!');
});

The size of the button, possible values are small, medium and large.

The style of the button, possible values are ghost, outline, purple, gray, and red. When using ghost, only the content of the button will be shown.

In JavaScript, this property can be set using the buttonStyle property, as to avoid conflict with the native style property.

Shows a badge.

The slot of the component will be used as the content of the badge.

<astro-dev-overlay-badge>My badge</astro-dev-overlay-badge>

The size of the badge, possible values are small and large.

The style of the badge, possible values are purple, gray, red, green, and yellow.

In JavaScript, this property can be set using the badgeStyle property, as to avoid conflict with the native style property.

Shows a card. Optionally, a link attribute can be specified to make the card act like a a element.

When making a card using using JavaScript, a clickAction property can be specified to make the card act like a button element.

The slot of the component will be used as the content of the card.

<astro-dev-overlay-card link="https://github.com/withastro/astro/issues/new/choose">Report an issue</astro-dev-overlay-card>

Shows a toggle element, acting as a checkbox. This element internally is a simple wrapper around a native <input type="checkbox"> element. The checkbox element can be accessed using the input property.

const toggle = document.createElement('astro-dev-overlay-toggle');
toggle.input.addEventListener('change', (evt) => {
console.log(`The toggle is now ${evt.currentTarget.checked ? 'enabled' : 'disabled'}!`);
});

Can be used to highlight an element on the page. In most cases, you’ll want to position and resize this element using the top, left, width and height CSS properties to match the element you want to highlight. An icon can also be specified using the icon attribute and will be shown in the top right corner of the highlight.

<!-- Highlight the entire page -->
<astro-dev-overlay-highlight style="top: 0; left: 0; width: 100%; height: 100%;"></astro-dev-overlay-highlight>
const elementToHighlight = document.querySelector('h1');
const rect = elementToHighlight.getBoundingClientRect();
const highlight = document.createElement('astro-dev-overlay-highlight');
highlight.style.top = `${Math.max(rect.top + window.scrollY - 10, 0)}px`;
highlight.style.left = `${Math.max(rect.left + window.scrollX - 10, 0)}px`;
highlight.style.width = `${rect.width + 15}px`;
highlight.style.height = `${rect.height + 15}px`;
highlight.icon = 'astro:logo';

Shows a tooltip with different sections. This component is set to display: none; by default and can be made visible using a data-show="true" attribute.

Sections are defined using the sections property. This property is an array of objects with the following shape:

{
title?: string; // Title of the section
inlineTitle?: string; // Title of the section, shown inline next to the title
icon?: Icon; // Icon of the section
content?: string; // Content of the section
clickAction?: () => void | Promise<void>; // Action to perform when clicking on the section
clickDescription?: string; // Description of the action to perform when clicking on the section
}
const tooltip = document.createElement('astro-dev-overlay-tooltip');
tooltip.sections = [{
title: 'My section',
icon: 'astro:logo',
content: 'My content',
clickAction: () => {
console.log('Clicked!')
},
clickDescription: 'Click me!'
}]

This component is often combined with the astro-dev-overlay-highlight component to show a tooltip when hovering a highlighted element:

const highlight = document.createElement('astro-dev-overlay-highlight');
// Position the highlight...
const tooltip = document.createElement('astro-dev-overlay-tooltip');
// Add sections to the tooltip...
highlight.addEventListener('mouseover', () => {
tooltip.dataset.show = 'true';
});
highlight.addEventListener('mouseout', () => {
tooltip.dataset.show = 'false';
});

Shows an icon. An icon from the icon list can be specified using the icon attribute, or the SVG markup of the icon can be passed as a slot.

<astro-dev-overlay-icon icon="astro:logo" />
<astro-dev-overlay-icon>
<svg>...</svg>
</astro-dev-overlay-icon>

Currently, the following icons are available and can be used in any component that accepts an icon:

  • astro:logo
  • warning
  • arrow-down
  • bug
  • file-search
  • check-circle
  • gear
  • lightbulb
  • file-search
  • checkmark
  • dots-three
  • copy

All of those icons have fill="currentColor" set, which means that the color of the icon will be inherited from the parent element.