Listeners shows what the active clients of an OpenWebRX+ receiver are listening to. It uses Supabase Realtime Presence directly from each browser, so the receiver administrator does not need to install or maintain a separate backend.
The plugin has its own native OpenWebRX+ floating window and does not use uikit.
LST plugin button.The plugin does not publish signal levels, scanner state, decoded messages, IP addresses, browser details or a persistent user identifier. Every browser tab receives a new random session identifier.
Loading the plugin opts that browser tab into publishing its selected profile, frequency, mode and filter to the configured public Presence channel. There is deliberately no client-side hide option: the listener counts and tuning details always describe the same participating clients.
.env.local tab under Add files. You do not need to install the package or add the files shown by Supabase; the plugin loads the browser library itself..env.local example into the plugin configuration:
SUPABASE_URL= goes into supabaseUrl. It must end immediately after .supabase.co.SUPABASE_KEY= goes into supabaseKey. It normally starts with sb_publishable_; a legacy anon key also works.service_role key.receiver/init.js.Do not use the REST endpoint from Integrations → Data API as the Project URL:
Project URL: https://abcdefgh.supabase.co ← use this
REST URL: https://abcdefgh.supabase.co/rest/v1/ ← not this
For convenience, the plugin recognizes and removes /rest/v1/ if it is pasted accidentally.
The publishable/anon key is designed to be used in browser code and is not a secret. Never put a Supabase service_role or secret key in init.js. The network name is a namespace, not an access-control boundary: a visitor can inspect the browser configuration and join the public channel. Use a dedicated Supabase project and do not publish sensitive information through it.
Load utils, wait for the receiver page, then load and configure Listeners:
await Plugins.load('https://0xaf.github.io/openwebrxplus-plugins/receiver/listeners/listeners.js');
await Plugins.listeners.setup({
supabaseUrl: 'https://YOUR-PROJECT.supabase.co',
supabaseKey: 'YOUR-PUBLISHABLE-KEY'
});
Alternatively, let visitors enable it through plugin_loader. Listeners is hidden from that window until its public Supabase settings are present:
await Plugins.load('https://0xaf.github.io/openwebrxplus-plugins/receiver/plugin_loader/plugin_loader.js');
await Plugins.plugin_loader.setup({
allowed: ['listeners'],
plugin_options: {
listeners: {
supabaseUrl: 'https://YOUR-PROJECT.supabase.co',
supabaseKey: 'YOUR-PUBLISHABLE-KEY'
}
}
});
The minimal setup groups clients from the current receiver only. To create an SDR network, use the same Supabase project, key and network value on every receiver:
await Plugins.listeners.setup({
supabaseUrl: 'https://YOUR-PROJECT.supabase.co',
supabaseKey: 'YOUR-PUBLISHABLE-KEY',
network: 'my-private-network-name',
receiverId: 'sdr-sofia',
receiverName: 'Sofia SDR',
receiverUrl: 'https://sdr.example.com/'
});
Available options:
| Option | Default | Description |
|---|---|---|
supabaseUrl |
empty | Supabase project URL. |
supabaseKey |
empty | Supabase Publishable key or legacy anon key. |
network |
empty | Shared channel name. Empty isolates presence to this receiver. |
receiverId |
current host | Stable unique ID inside a shared network. |
receiverName |
receiver title | Human-readable receiver name. |
receiverUrl |
current page | Link shown for a remote receiver. |
open |
false |
Open the Listeners window immediately after loading. |
sdkUrl |
jsDelivr | Alternate URL for the Supabase JavaScript SDK. |
Use the Project URL from the Connect → App Frameworks dialog. The plugin also strips common copied API endpoint suffixes automatically, but the root Project URL is the unambiguous value expected by Supabase.
Supabase free-plan quotas and Realtime limits apply. Each open receiver tab uses one Realtime connection and one Presence member.