Skip to content

User Interface with Webviews

Building rich interfaces using web technologies

Extensions can display custom user interfaces using Webviews. This allows you to use standard HTML, CSS, and JavaScript to build specialized tools, editors, or dashboards that integrate directly with Ableton Live.

In the Extensions SDK, Webviews are displayed using Modal Dialogs. A Modal Dialog opens a separate window that loads a URL and displays it to the user.

A common pattern is to import an HTML file (which your bundler can inline) and pass it as a Data URL:

// interface.html will be inlined as a string by your bundler
import modalInterface from "./interface.html"
// Show the dialog with a specific width and height
const result = await context.ui.showModalDialog(
`data:text/html,${encodeURIComponent(modalInterface)}`,
640,
240
);
// Process the result returned from the Webview
const data = JSON.parse(result);

The Webview runs in a separate environment from your extension. To communicate back to Ableton Live, you must use the host’s message handler.

The following boilerplate includes the necessary logic to communicate with the extension on both macOS and Windows, along with basic Ableton-style CSS variables to match the host’s aesthetic.

interface.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Extension Dialog</title>
<script>
const isWebKit = window.webkit?.messageHandlers?.live;
const isWebView2 = window.chrome?.webview;
function sendMessage(message) {
if (isWebKit) {
window.webkit.messageHandlers.live.postMessage(message);
} else if (isWebView2) {
window.chrome.webview.postMessage(message);
}
}
function closeWithResult(result) {
// The SDK expects this specific message structure to close the dialog
sendMessage({
method: "close_and_send",
params: [JSON.stringify(result)]
});
}
</script>
<style>
:root {
--ableton-bg: #383838;
--ableton-panel: #4E4E4E;
--ableton-button: #FFA500;
--ableton-text: #FFFFFF;
--ableton-border: #2C2C2C;
--ableton-input-bg: #2C2C2C;
}
body {
background-color: var(--ableton-panel);
color: var(--ableton-text);
font-family: sans-serif;
margin: 0;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
button {
background-color: var(--ableton-button);
border: none;
padding: 8px 16px;
cursor: pointer;
color: #000;
}
</style>
</head>
<body>
<h1>Extension UI</h1>
<button onclick="closeWithResult({ status: 'success' })">
Close and Return Data
</button>
</body>
</html>

Communication between the Extension and the Webview is handled via message passing.

To return data and close the dialog, your HTML must send a message with the name close_and_send. The arguments must be an array containing a single string (usually stringified JSON).

function closeWithResult(result) {
const message = {
method: "close_and_send",
params: [JSON.stringify(result)]
};
// Check for platform-specific handlers
if (window.webkit?.messageHandlers?.live) {
window.webkit.messageHandlers.live.postMessage(message);
} else if (window.chrome?.webview) {
window.chrome.webview.postMessage(message);
}
}

The most common way to pass data to a Webview is by inlining it directly into the HTML string before encoding it, or by appending query parameters to the Data URL and consuming that inside the HTML.