API reference
Inside a bundle, your code talks to the app through window.DesktopOverlaysAPI. The API is split into namespaces. Each namespace is only present if you request its permission in the manifest. If you do not request a scope, the namespace is undefined, so guard for it or rely on your declared permissions.
const api = window.DesktopOverlaysAPI
if (api.audio) api.audio.onUpdate(frame => { /* ... */ })Methods that return data return a Promise. Methods named onUpdate (and similar) take a callback and keep calling it as the data changes.
Namespaces at a glance
| Namespace | Permission | Purpose |
|---|---|---|
audio | sdk.audio | System audio FFT frames. |
media | sdk.media | The now-playing track. |
windows | sdk.windows | Open windows and desktop state. |
app | sdk.app | Foreground app, fullscreen, display, desktop. |
notifications | sdk.notifications | Windows notifications. |
options | sdk.options | The user's settings for this overlay. |
content | sdk.content | Messages between the bundle's surfaces. |
size | sdk.size | Read and set the overlay size. |
audio
Requires sdk.audio. Provides frequency data captured from system audio output, suitable for visualizers.
audio.onUpdate(callback)
Calls callback(frame) for each new frame, where frame is a Uint8Array of FFT magnitudes. The byte values match the classic getByteFrequencyData output (dB range -100 to -30, smoothing 0.8). Capture starts when the first bundle subscribes and stops when the last one unsubscribes, so there is no cost when nobody is listening.
const bars = document.querySelectorAll('.bar')
api.audio.onUpdate((frame) => {
bars.forEach((bar, i) => {
bar.style.height = (frame[i] / 255 * 100) + '%'
})
})media
Requires sdk.media. Reports the Windows now-playing session.
media.get()
Returns a Promise of the current snapshot, or a snapshot with hasSession: false when nothing is playing.
media.onUpdate(callback)
Calls callback(info) whenever the now-playing session changes.
The snapshot shape:
| Field | Type | Notes |
|---|---|---|
hasSession | boolean | False when there is no media session. |
title | string | |
artist | string | |
albumTitle | string | |
albumArtist | string | |
trackNumber | number | |
albumTrackCount | number | |
genres | string[] | |
playbackStatus | string | |
isPlaying | boolean | |
appId | string | The source app. |
position | number | Playback position. |
duration | number | Track length. |
lastUpdatedMs | number | When position was last refreshed. |
thumbnail | string or null | A data:image/...;base64,... URI of the album art, or null. |
Position and timeline only refresh on a seek or a track change. For a live position, interpolate from lastUpdatedMs while isPlaying is true.
const snap = await api.media.get()
if (snap.hasSession) title.textContent = snap.title + ' - ' + snap.artistwindows
Requires sdk.windows. Reports open top-level windows and whether the desktop is showing. The app's own overlay windows are excluded from the list.
windows.get()
Returns a Promise of the currently visible top-level windows as WindowInfo[]. Visible means not minimized, not cloaked, and having a title.
windows.getForeground()
Returns a Promise of the current foreground window as WindowInfo, or null on the desktop.
windows.onUpdate(callback)
Calls callback({ windows, foreground, desktop }) whenever the set of windows or the foreground changes. desktop is the same boolean as $.app.desktop in conditions: true when no application window is visible.
WindowInfo shape:
| Field | Type |
|---|---|
title | string |
exe | string |
x | number |
y | number |
width | number |
height | number |
foreground | boolean |
app
Requires sdk.app. Gives you the same $.app state that conditions use, readable at runtime.
app.get()
Returns a Promise of { activeProcess, fullscreen, displayId, desktop }. activeProcess is the lowercase foreground executable name, or null on the desktop. displayId is the display this overlay sits on.
app.onUpdate(callback)
Calls callback(state) with the same shape whenever the foreground or desktop state changes, so the bundle can react to the same conditions it declares.
notifications
Requires sdk.notifications. Reports Windows notifications from the Action Center. On first use, Windows asks the user to allow reading notifications. If the user declines, the list comes back empty.
notifications.get()
Returns a Promise of the current notifications as NotificationInfo[], oldest first.
notifications.getLast()
Returns a Promise of the newest notification as NotificationInfo, or null.
notifications.onUpdate(callback)
Calls callback(list) with the full current list whenever a notification is added, updated, or removed.
NotificationInfo shape:
| Field | Type |
|---|---|
id | string |
appId | string |
appName | string |
title | string |
body | string |
timestamp | number |
options
Requires sdk.options. Reads the user's settings for this overlay instance and reacts to changes. See Options for how to define them.
options.get()
Returns a Promise of the current values, keyed by option key.
options.set(key, value)
Sets one option value.
options.update(values)
Sets several option values at once, given an object of key to value.
set and update cannot change shortcut or file options. Those are user-driven only, and writes to them are ignored.
options.onUpdate(callback)
Calls callback(event) when something changes. The event.action field tells you what happened:
action | Extra fields | Meaning |
|---|---|---|
value-change | values | One or more option values changed. values holds the changed keys. |
button-click | key | A button option was clicked. |
shortcut | key | A shortcut option's global key was pressed. |
editor-state | visible, editMode | The overlay's editor state changed. visible is whether the overlay is shown; editMode is whether the editor panel is open. |
The initial state is also sent once when the surface loads.
api.options.get().then(apply)
api.options.onUpdate((e) => {
if (e.action === 'value-change') apply(e.values)
else if (e.action === 'button-click') doAction(e.key)
})content
Requires sdk.content. Lets the bundle's own surfaces talk to each other. A message is delivered to every other open surface of the same bundle, but not back to the sender.
content.sendMessage(message)
Sends a message object to the bundle's other open surfaces.
content.onMessage(callback)
Calls callback(message) for messages from the bundle's other surfaces.
size
Requires sdk.size. Reads and changes the overlay's box size.
size.get()
Returns a Promise of { width, height } in pixels.
size.set(width, height)
Resizes the overlay. Expects positive integers. The change is saved and reflected everywhere. For fullscreen surfaces the effect is limited, since they cover the display.
const s = await api.size.get()
api.size.set(s.width, s.height + 40)