Live Dashboards

Build real-time dashboards that update instantly as data changes.

Overview

Real-time dashboards provide immediate visibility into your business metrics. With NoLag, you can push updates to dashboards the moment data changes, without polling or page refreshes.

Dashboard Setup

import { NoLag } from '@nolag/js-sdk'

const client = NoLag('your_access_token')
await client.connect()

const dashboard = client.setApp('analytics').setRoom('live')

// Subscribe to real-time metrics
dashboard.subscribe('page-views')
dashboard.subscribe('active-users')
dashboard.subscribe('sales')

// Update charts in real-time
dashboard.on('page-views', (data) => {
  pageViewsChart.update(data.count, data.timestamp)
})

dashboard.on('active-users', (data) => {
  activeUsersGauge.setValue(data.count)
})

dashboard.on('sales', (data) => {
  salesChart.addDataPoint(data.amount, data.timestamp)
  totalSales.increment(data.amount)
})

Filtering Dashboard Updates

Most dashboards show a subset of data — a few bookings, specific orders, or selected devices. Without filters, every update on the topic is delivered to every subscriber, even if they're only watching 3 items out of thousands.

Topic filters solve this at the infrastructure level. Subscribe with the IDs of the entities currently visible on screen, and only updates for those entities are delivered. When the user navigates, swap filters dynamically — no resubscribe needed.

import { NoLag } from '@nolag/js-sdk'

const client = NoLag('your_access_token')
await client.connect()

const dashboard = client.setApp('booking-system').setRoom('ops')

// User is viewing 3 specific bookings on their dashboard
const visibleBookings = ['booking_42', 'booking_87', 'booking_153']

// Subscribe with filters — only receive updates for these bookings
dashboard.subscribe('bookings', {
  filters: visibleBookings
})

dashboard.on('bookings', (data, meta) => {
  // meta.filter tells you which booking was updated
  updateBookingCard(meta.filter, data)
})

// User navigates to a different page — swap filters instantly
function onPageChange(newBookingIds: string[]) {
  dashboard.setFilters('bookings', newBookingIds)
}

// User opens a booking detail — add it to filters
function onBookingOpen(bookingId: string) {
  dashboard.addFilters('bookings', [bookingId])
}

// User closes a booking detail — remove it
function onBookingClose(bookingId: string) {
  dashboard.removeFilters('bookings', [bookingId])
}

Publishing Filtered Updates

On the backend, publish with a filter to target specific entities. Only dashboard clients watching that entity receive the update:

// Backend service publishes updates with filters
// Only dashboard users watching this specific booking receive it
room.emit('bookings', {
  status: 'confirmed',
  guest: 'John Smith',
  checkIn: '2026-03-15'
}, {
  filter: 'booking_42'  // Target a specific booking
})

// Publish a different booking update
room.emit('bookings', {
  status: 'cancelled',
  reason: 'Guest request'
}, {
  filter: 'booking_87'
})
Tip: Filtering happens at the infrastructure level — no payload inspection, no wasted bandwidth. See Topic Filters for full details.

Use Cases

  • Analytics dashboards - Page views, user sessions, conversion rates
  • Sales dashboards - Revenue, orders, inventory levels
  • Operations dashboards - Server health, error rates, response times
  • Trading dashboards - Stock prices, market data, portfolio values

Architecture

  1. Backend services publish metrics to NoLag topics
  2. Dashboard clients subscribe to relevant topics
  3. Charts and gauges update in real-time as data arrives

Best Practices

  • Use filters to subscribe only to entities visible on screen — avoid receiving thousands of irrelevant updates
  • Use setFilters when the user navigates — it swaps filters atomically with minimal message gaps
  • Use separate topics for different metric types
  • Batch updates for high-frequency data to reduce rendering overhead
  • Use hydration webhooks to load initial dashboard state
  • Consider data retention and historical data storage separately

Next Steps