diff --git a/frontend/js/i18n/en.js b/frontend/js/i18n/en.js
index 7dd03dc..2c3ad53 100644
--- a/frontend/js/i18n/en.js
+++ b/frontend/js/i18n/en.js
@@ -472,6 +472,7 @@ export default {
'device.info.size_free': '{size} free',
'device.info.player_type': 'Player Type',
'device.info.web_player': 'Web Player',
+ 'device.info.brightsign_player': 'BrightSign',
'device.info.wifi': 'WiFi',
'device.info.uptime': 'Uptime',
'device.info.android_version': 'Android Version',
diff --git a/frontend/js/views/device-detail.js b/frontend/js/views/device-detail.js
index fad4b94..231e938 100644
--- a/frontend/js/views/device-detail.js
+++ b/frontend/js/views/device-detail.js
@@ -83,6 +83,17 @@ function renderDeviceClock(device) {
return `${tz}${local ? `
${t('device.clock.reported', { time: local })}
` : ''}${warn}`;
}
+// A BrightSign runs the same web player, so client_type is 'player' and it would otherwise read as
+// "Web Player" — indistinguishable from a browser tab on someone's desk. The player reports
+// platform 'brightsign' (autorun.brs puts ?platform=brightsign on the URL); the user-agent check
+// covers panels paired before that existed, which registered as "Chrome 120" with a BrightSign UA.
+function isBrightSignDevice(device) {
+ if (!device) return false;
+ const platform = String(device.platform || '').toLowerCase();
+ if (platform.includes('brightsign')) return true;
+ return String(device.user_agent || '').toLowerCase().includes('brightsign');
+}
+
export function render(container, deviceId) {
container.innerHTML = `
@@ -341,7 +352,7 @@ async function loadDevice(deviceId, activeTab = null) {
` : `
${t('device.info.player_type')}
-
${t('device.info.web_player')}
+
${isBrightSignDevice(device) ? t('device.info.brightsign_player') : t('device.info.web_player')}
`}
${device.android_version && !device.android_version.startsWith('Web/') ? `