DisplaySync

Monitoring & health

A sign is healthy when the kiosk is connected, the assigned URL is reachable, and the device telemetry is within normal ranges. The dashboard surfaces all three on every sign detail page; this page is the reference for what each indicator means.

Heartbeats

Every claimed sign sends a heartbeat to the backend over the WebSocket every 5 seconds. Each heartbeat carries:

  • status — online / offline / error / maintenance
  • currentUrl — what the kiosk is currently displaying
  • deviceInfo — platform, OS, MAC, IP, Tailscale IP, hostname, screen resolution, free disk, RAM, CPU
  • appVersion — desktop sign version
  • uptime — seconds since the kiosk booted
  • cacheState — whether content is cached locally for offline operation

The backend keeps the latest heartbeat for live status and a rolling history for the uptime timeline.

Online / offline transitions

The dashboard transitions a sign between Online and Offline based on heartbeat freshness:

StateTrigger
OnlineHeartbeat received within the last 15 seconds
OfflineNo heartbeat for 15+ seconds (3 missed in a row)
Online (recovered)Was offline, now received a heartbeat — flagged briefly as "recently reconnected"

Why 15 seconds? Heartbeats fire every 5 seconds, so 15 seconds is exactly 3 missed in a row — strong enough to filter transient packet loss, fast enough that you find out about a real disconnect within the venue's typical "is something wrong?" reaction time.

The backend keeps each heartbeat for 30 seconds and runs a background sweep every 10 s to mark expired sign records offline. So a true offline transition can take up to ~25 s to surface — heartbeat goes silent at T=0, the record expires at T+15 s, the sweep next runs by T+25 s. Notifications are deferred a further 60 seconds to give the sign a chance to reconnect — see Notifications for why.

Sign states

A sign is in exactly one state at a time. The dashboard renders each with a consistent color:

StateColorMeaning
OnlineGreenConnected, heartbeating, content displaying
OfflineYellowHeartbeat is stale (no signal for 30+ s) — likely a network or kiosk problem
ErrorRedSign reported an explicit failure (e.g., couldn't load assigned URL)
MaintenanceBlueOperator-controlled state. Ctrl+Shift+Q on the kiosk exits the sign app for maintenance (the watchdog won't relaunch while the .maintenance sentinel is present). The maintenance state on the dashboard is set by the dashboard itself, not by the kiosk's heartbeat. See Crash recovery.
UnlinkedGreySign record exists but no physical device is linked yet

The color is consistent across the dashboard sign grid, the sign detail page, the mobile app, and notification badges.

State transitions are written to the Audit tab so you can answer "when did this sign go offline?" without grepping logs.

The "Background" badge

A sign in background mode shows a Background badge on its dashboard card alongside the state color. The orthogonal mode field on the heartbeat carries 'background' or 'active' — see Sign states → Orthogonal mode field. When the badge is showing:

  • The sign is healthy (heartbeat is current; sign is online)
  • The wall is intentionally dark — display hidden, audio muted
  • This is not a failure to escalate; the operator put the sign in this mode

Toggle off via the dashboard's Exit Background button or Ctrl+Shift+B at the kiosk. See Remote control → Background mode and Hotkeys.

Uptime tracking

A sign's uptime is the share of time it was connected, shown two ways on the sign detail page:

  • Since joined — measured from when the sign was first linked to now. Always available.
  • This event — scoped to the current event's window. Shown during a live event, and frozen as This event (final) once the event ends.

Only sustained dropouts count against uptime — brief reconnects shorter than the notification-deferral window are treated as blips and don't subtract. So the figure agrees with when you'd actually have been paged, and it reads honestly high for a stable sign. A sign that's online but has no history yet (just claimed) shows an honest number immediately rather than a misleading zero.

A few patterns worth recognizing:

  • >99% is normal for a properly-deployed event
  • 95-99% typically reflects venue Wi-Fi flapping rather than kiosk failure — the wall is up, the dashboard just saw the connection drop briefly
  • Below 95% suggests genuine trouble — either a network problem you can fix or a sign in a flaky state

Device info

Every heartbeat carries device telemetry. The dashboard surfaces it on the Device Information card on the sign's Overview tab:

FieldSource
Platform / OS versionos.platform() + os.release()
Hostnameos.hostname() — useful when you set custom names like LOBBY-SIGN-01
MACFirst non-internal NIC at first boot (stored, doesn't change)
Local IPCurrent primary interface IP
Tailscale IPtailscale ip -4 if installed, blank otherwise
Screen resolutionPer the primary display
CPU / RAM / Free diskSnapshot at heartbeat time
App VersionBuild version of the desktop sign
System TimeThe sign's own clock, live — see Clock and displayed time
UptimeSeconds since the sign app launched (reset by Restart App or Reboot Device)

Telemetry is for triage, not surveillance — use it to answer "is this sign stuck?" or "did somebody reboot the device an hour ago?" not for performance dashboards.

Clock and displayed time

Kiosk hardware loses time. A dead CMOS battery, a venue network with no NTP, a machine that sat in a crate for six months — any of these leaves a sign convinced it's 4:12 AM on a Tuesday in 2019. If your content shows a schedule, a countdown, or a clock, that's a visible failure on the wall.

DisplaySync handles this in two parts: the sign corrects the time it displays using the event's timezone, and the dashboard tells you the underlying clock is wrong anyway so you can fix the hardware at teardown.

The System Time row

On the sign's Overview tab, the Device Information card carries a single live System Time row. It ticks once a second, and it always shows the raw, uncorrected clock the device itself believes, rendered in the device's own timezone:

System Time   Mar 13, 2026, 4:12:07 AM PDT   ⚠ off by 6h 43m

The value is deliberately never "fixed up" before you see it. Correction status lives in the badge beside it, so a wrong clock and a green badge can sit next to each other — which is exactly the honest picture when correction is doing its job.

BadgeWhen it appearsWhat it means
✓ Corrected (green)The sign is applying the event's timezone, and its own clock is off by a meaningful amountContent on the wall shows the right time. Hover for the raw skew and the time actually on screen.
⚠ off by 6h 43m (amber)The clock is off by a minute or more and is not being correctedDisplayed content may show the wrong time. Fix the device clock.
(no badge)The clock is close enough to correctNothing to say.

A sign that only reports a timezone and no clock reading — older builds — shows a plain Device Timezone row instead. DisplaySync won't invent a time from a timezone alone.

If the device's own timezone disagrees with the event's, the System Time value renders amber and the hover text names the event's zone. That isn't an error on its own: it usually means the OS zone is wrong and the correction is quietly covering for it.

The Clock card

The sign's Analytics tab carries a Clock card in the health strip alongside Uptime, Content, Errors, and Connection:

  • ✓ synced — the device clock is close enough that there's nothing to report
  • ✓ Corrected — the clock is off, but the sign is showing the right time anyway. The subtitle names the real skew ("OS clock 6h 43m behind").
  • +3m 12s off — the clock is off and uncorrected

The Clock card is passive. It never flips a sign's health verdict and never sends a notification — a wrong clock on a corrected sign is a maintenance note, not an incident.

Note it at teardown, not mid-show

A ✓ Corrected sign is fine to leave alone during a live event — the wall is right. Log the device for a CMOS battery swap during teardown instead of pulling a working sign off the floor.

Why the event's timezone matters

The zone a sign corrects to is the event's timezone, not the device's own. That's the single field on the event that makes all of this work — set it when you create the event (Your first event). It's also what scheduled refreshes are evaluated in.

Content reachability

Independent of the kiosk's connection to us, the kiosk monitors whether the assigned URL is reachable by doing an HTTP HEAD every 60 seconds. The dashboard reports this on a per-sign and per-event basis:

  • Reachable — last HEAD succeeded (2xx or 3xx)
  • Unreachable — last HEAD failed (timeout, 4xx, 5xx, DNS failure)

Reachability state is independent of the sign's online/offline state:

  • A sign can be Online but with Unreachable content — the kiosk reaches us, but its content origin is down
  • A sign can be Offline with Reachable content (last known) — the kiosk lost its WebSocket but the content URL was working at last check

When content goes Unreachable, the kiosk continues displaying the cached version and notifies subscribers (see Notifications). The wall doesn't blank — you have time to fix the content side without an audience seeing the failure.

Local diagnostics on the kiosk

Sometimes you want to look at health from the sign's side rather than the dashboard's. With keyboard access to the kiosk, press Ctrl + Shift + S to open the Status Dashboard overlay on the kiosk itself:

  • Connection status (WebSocket state, last heartbeat sent, last command received)
  • Sign ID, short code, MAC
  • Backend URL, WebSocket URL
  • IP addresses (LAN + Tailscale)
  • Cache status (items cached, size, last sync)
  • Recent error count

Press Esc to dismiss. This overlay is also what techs press when triaging a misbehaving sign in person — answers "is this device even reaching the backend?" without leaving the venue.

When to escalate

A few patterns and what to do about them:

PatternWhat it meansAction
One sign offline for >2 minutesKiosk-specific — the others are fineTroubleshoot offline
Multiple signs offline at onceNetwork or backend issueCheck venue Wi-Fi first. Multiple signs across multiple venues going offline at the same time usually means a backend incident — we'll email an alert if so
All signs online, content unreachableYour content URL is downFix content side, or assign a fallback URL
Sign cycling online/offline rapidlyWi-Fi flapping or kiosk DNS issuesNetwork resilience
Sign in Error stateContent failed to loadFetch logs, look for the failed URL or HTTP error

Reach for Troubleshooting for symptom-by-symptom playbooks.

What's next