Skip to content

Theme Sync

Embedded notebooks support runtime theme switching via the browser’s postMessage API. This lets the parent page keep the embed’s appearance in sync with its own dark/light mode toggle.

Use the theme query parameter on the embed URL:

https://spicebook.warehack.ing/embed/{id}?theme=light

This sets the theme when the iframe first loads. To change it after load, use postMessage.

Send a message to the iframe’s content window:

const iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage(
{ type: 'spicebook-theme', theme: 'light' },
'*'
);
FieldTypeValuesDescription
typestring"spicebook-theme"Message identifier (required)
themestring"dark", "light"Target theme

Messages with any other type value are ignored by the embed.

A common pattern is to listen for your page’s theme change and forward it to the embed:

// Assuming your page toggles a data-theme attribute on <html>
const observer = new MutationObserver(() => {
const theme = document.documentElement.dataset.theme || 'dark';
iframe.contentWindow.postMessage(
{ type: 'spicebook-theme', theme },
'*'
);
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme'],
});

The postMessage call uses '*' as the target origin for simplicity. If you want stricter security, specify the SpiceBook origin:

iframe.contentWindow.postMessage(
{ type: 'spicebook-theme', theme: 'dark' },
'https://spicebook.warehack.ing'
);

The embed only acts on messages with type: 'spicebook-theme' — all other messages are silently ignored.