Write a theme without a build step
A theme can be a single index.html with inline script, using the native bridge window.fb2k that the component injects into every page. Nothing has to be installed or built.
Write the page
Save this as index.html in a template folder (Install a theme shows how to create one and make it active):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My foobar2000 UI</title>
</head>
<body>
<h1 id="track">Waiting for playback...</h1>
<button id="play">▶ Play</button>
<button id="prev">⏮ Previous</button>
<button id="next">⏭ Next</button>
<script>
document.getElementById('play').onclick = () => fb2k.invoke('playback.playOrPause');
document.getElementById('prev').onclick = () => fb2k.invoke('playback.previous');
document.getElementById('next').onclick = () => fb2k.invoke('playback.next');
fb2k.on('playback:trackChanged', (data) => {
document.getElementById('track').textContent = data.artist + ' - ' + data.title;
});
</script>
</body>
</html>Press Apply on the preferences page, or reload the window, to see it.
Call the host from the page
fb2k.invoke(method, params) calls a host method and resolves with its result; fb2k.on(event, handler) subscribes to an event and returns a function that unsubscribes.
// Every call is asynchronous
await fb2k.invoke('playback.play');
// A result carries success; check it before reading the fields
const current = await fb2k.invoke('playback.getCurrentTrack');
if (current.success === false) throw new Error(current.error);
if (current.track) console.log(current.track.title, current.track.artist);
// Parameters go in an object (volume is 0-100)
await fb2k.invoke('playback.setVolume', { volume: 80 });
// Subscribe, and unsubscribe later
const unsubscribe = fb2k.on('playback:trackChanged', (data) => {
console.log('Now playing:', data.title);
});
unsubscribe();Method names use a dot (playback.play) and event names a colon (playback:trackChanged). The low-level API reference lists every method and event, and Bridge protocol describes the message format.
Use the SDK without a bundler
To use the fb.* wrappers and the fb-* components in such a page, copy the SDK's global bundles into the template folder and load them before your script:
<script src="./sdk/bridge.global.js"></script>
<script src="./sdk/components.global.js"></script>
<fb-play-button></fb-play-button>
<script>
fb.on('playback:trackChanged', (track) => {
document.title = `${track.title} - ${track.artist}`;
});
</script>Load the SDK in a theme says where the files come from.