[{"data":1,"prerenderedAt":1639},["ShallowReactive",2],{"docs:/docs/guides/dashboards":3},{"id":4,"title":5,"body":6,"description":1632,"extension":1633,"meta":1634,"navigation":68,"path":1635,"seo":1636,"stem":1637,"__hash__":1638},"docs/docs/guides/dashboards.md","Live Dashboards",{"type":7,"value":8,"toc":1621},"minimark",[9,13,17,22,25,29,626,630,633,640,1232,1237,1244,1500,1516,1520,1548,1552,1564,1568,1594,1598,1617],[10,11,5],"h1",{"id":12},"live-dashboards",[14,15,16],"p",{},"Build real-time dashboards that update instantly as data changes.",[18,19,21],"h2",{"id":20},"overview","Overview",[14,23,24],{},"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.",[18,26,28],{"id":27},"dashboard-setup","Dashboard Setup",[30,31,32,360,492],"code-tabs",{},[33,34,40],"pre",{"className":35,"code":36,"filename":37,"language":38,"meta":39,"style":39},"language-typescript shiki shiki-themes github-light github-dark","import { NoLag } from '@nolag/js-sdk'\n\nconst client = NoLag('your_access_token')\nawait client.connect()\n\nconst dashboard = client.setApp('analytics').setRoom('live')\n\n// Subscribe to real-time metrics\ndashboard.subscribe('page-views')\ndashboard.subscribe('active-users')\ndashboard.subscribe('sales')\n\n// Update charts in real-time\ndashboard.on('page-views', (data) => {\n  pageViewsChart.update(data.count, data.timestamp)\n})\n\ndashboard.on('active-users', (data) => {\n  activeUsersGauge.setValue(data.count)\n})\n\ndashboard.on('sales', (data) => {\n  salesChart.addDataPoint(data.amount, data.timestamp)\n  totalSales.increment(data.amount)\n})\n","TypeScript","typescript","",[41,42,43,63,70,96,111,116,149,154,161,177,191,205,210,216,244,256,262,267,288,300,305,310,331,343,355],"code",{"__ignoreMap":39},[44,45,48,52,56,59],"span",{"class":46,"line":47},"line",1,[44,49,51],{"class":50},"szBVR","import",[44,53,55],{"class":54},"sVt8B"," { NoLag } ",[44,57,58],{"class":50},"from",[44,60,62],{"class":61},"sZZnC"," '@nolag/js-sdk'\n",[44,64,66],{"class":46,"line":65},2,[44,67,69],{"emptyLinePlaceholder":68},true,"\n",[44,71,73,76,80,83,87,90,93],{"class":46,"line":72},3,[44,74,75],{"class":50},"const",[44,77,79],{"class":78},"sj4cs"," client",[44,81,82],{"class":50}," =",[44,84,86],{"class":85},"sScJk"," NoLag",[44,88,89],{"class":54},"(",[44,91,92],{"class":61},"'your_access_token'",[44,94,95],{"class":54},")\n",[44,97,99,102,105,108],{"class":46,"line":98},4,[44,100,101],{"class":50},"await",[44,103,104],{"class":54}," client.",[44,106,107],{"class":85},"connect",[44,109,110],{"class":54},"()\n",[44,112,114],{"class":46,"line":113},5,[44,115,69],{"emptyLinePlaceholder":68},[44,117,119,121,124,126,128,131,133,136,139,142,144,147],{"class":46,"line":118},6,[44,120,75],{"class":50},[44,122,123],{"class":78}," dashboard",[44,125,82],{"class":50},[44,127,104],{"class":54},[44,129,130],{"class":85},"setApp",[44,132,89],{"class":54},[44,134,135],{"class":61},"'analytics'",[44,137,138],{"class":54},").",[44,140,141],{"class":85},"setRoom",[44,143,89],{"class":54},[44,145,146],{"class":61},"'live'",[44,148,95],{"class":54},[44,150,152],{"class":46,"line":151},7,[44,153,69],{"emptyLinePlaceholder":68},[44,155,157],{"class":46,"line":156},8,[44,158,160],{"class":159},"sJ8bj","// Subscribe to real-time metrics\n",[44,162,164,167,170,172,175],{"class":46,"line":163},9,[44,165,166],{"class":54},"dashboard.",[44,168,169],{"class":85},"subscribe",[44,171,89],{"class":54},[44,173,174],{"class":61},"'page-views'",[44,176,95],{"class":54},[44,178,180,182,184,186,189],{"class":46,"line":179},10,[44,181,166],{"class":54},[44,183,169],{"class":85},[44,185,89],{"class":54},[44,187,188],{"class":61},"'active-users'",[44,190,95],{"class":54},[44,192,194,196,198,200,203],{"class":46,"line":193},11,[44,195,166],{"class":54},[44,197,169],{"class":85},[44,199,89],{"class":54},[44,201,202],{"class":61},"'sales'",[44,204,95],{"class":54},[44,206,208],{"class":46,"line":207},12,[44,209,69],{"emptyLinePlaceholder":68},[44,211,213],{"class":46,"line":212},13,[44,214,215],{"class":159},"// Update charts in real-time\n",[44,217,219,221,224,226,228,231,235,238,241],{"class":46,"line":218},14,[44,220,166],{"class":54},[44,222,223],{"class":85},"on",[44,225,89],{"class":54},[44,227,174],{"class":61},[44,229,230],{"class":54},", (",[44,232,234],{"class":233},"s4XuR","data",[44,236,237],{"class":54},") ",[44,239,240],{"class":50},"=>",[44,242,243],{"class":54}," {\n",[44,245,247,250,253],{"class":46,"line":246},15,[44,248,249],{"class":54},"  pageViewsChart.",[44,251,252],{"class":85},"update",[44,254,255],{"class":54},"(data.count, data.timestamp)\n",[44,257,259],{"class":46,"line":258},16,[44,260,261],{"class":54},"})\n",[44,263,265],{"class":46,"line":264},17,[44,266,69],{"emptyLinePlaceholder":68},[44,268,270,272,274,276,278,280,282,284,286],{"class":46,"line":269},18,[44,271,166],{"class":54},[44,273,223],{"class":85},[44,275,89],{"class":54},[44,277,188],{"class":61},[44,279,230],{"class":54},[44,281,234],{"class":233},[44,283,237],{"class":54},[44,285,240],{"class":50},[44,287,243],{"class":54},[44,289,291,294,297],{"class":46,"line":290},19,[44,292,293],{"class":54},"  activeUsersGauge.",[44,295,296],{"class":85},"setValue",[44,298,299],{"class":54},"(data.count)\n",[44,301,303],{"class":46,"line":302},20,[44,304,261],{"class":54},[44,306,308],{"class":46,"line":307},21,[44,309,69],{"emptyLinePlaceholder":68},[44,311,313,315,317,319,321,323,325,327,329],{"class":46,"line":312},22,[44,314,166],{"class":54},[44,316,223],{"class":85},[44,318,89],{"class":54},[44,320,202],{"class":61},[44,322,230],{"class":54},[44,324,234],{"class":233},[44,326,237],{"class":54},[44,328,240],{"class":50},[44,330,243],{"class":54},[44,332,334,337,340],{"class":46,"line":333},23,[44,335,336],{"class":54},"  salesChart.",[44,338,339],{"class":85},"addDataPoint",[44,341,342],{"class":54},"(data.amount, data.timestamp)\n",[44,344,346,349,352],{"class":46,"line":345},24,[44,347,348],{"class":54},"  totalSales.",[44,350,351],{"class":85},"increment",[44,353,354],{"class":54},"(data.amount)\n",[44,356,358],{"class":46,"line":357},25,[44,359,261],{"class":54},[33,361,366],{"className":362,"code":363,"filename":364,"language":365,"meta":39,"style":39},"language-python shiki shiki-themes github-light github-dark","from nolag import NoLag\n\nclient = NoLag('your_access_token')\nawait client.connect()\n\ndashboard = client.set_app('analytics').set_room('live')\n\n# Subscribe to real-time metrics\nawait dashboard.subscribe('page-views')\nawait dashboard.subscribe('active-users')\nawait dashboard.subscribe('sales')\n\n# Update charts in real-time\ndef on_page_views(data, meta):\n    page_views_chart.update(data['count'], data['timestamp'])\n\ndef on_active_users(data, meta):\n    active_users_gauge.set_value(data['count'])\n\ndef on_sales(data, meta):\n    sales_chart.add_data_point(data['amount'], data['timestamp'])\n    total_sales.increment(data['amount'])\n\ndashboard.on('page-views', on_page_views)\ndashboard.on('active-users', on_active_users)\ndashboard.on('sales', on_sales)\n","Python","python",[41,367,368,373,377,382,387,391,396,400,405,410,415,420,424,429,434,439,443,448,453,457,462,467,472,476,481,486],{"__ignoreMap":39},[44,369,370],{"class":46,"line":47},[44,371,372],{},"from nolag import NoLag\n",[44,374,375],{"class":46,"line":65},[44,376,69],{"emptyLinePlaceholder":68},[44,378,379],{"class":46,"line":72},[44,380,381],{},"client = NoLag('your_access_token')\n",[44,383,384],{"class":46,"line":98},[44,385,386],{},"await client.connect()\n",[44,388,389],{"class":46,"line":113},[44,390,69],{"emptyLinePlaceholder":68},[44,392,393],{"class":46,"line":118},[44,394,395],{},"dashboard = client.set_app('analytics').set_room('live')\n",[44,397,398],{"class":46,"line":151},[44,399,69],{"emptyLinePlaceholder":68},[44,401,402],{"class":46,"line":156},[44,403,404],{},"# Subscribe to real-time metrics\n",[44,406,407],{"class":46,"line":163},[44,408,409],{},"await dashboard.subscribe('page-views')\n",[44,411,412],{"class":46,"line":179},[44,413,414],{},"await dashboard.subscribe('active-users')\n",[44,416,417],{"class":46,"line":193},[44,418,419],{},"await dashboard.subscribe('sales')\n",[44,421,422],{"class":46,"line":207},[44,423,69],{"emptyLinePlaceholder":68},[44,425,426],{"class":46,"line":212},[44,427,428],{},"# Update charts in real-time\n",[44,430,431],{"class":46,"line":218},[44,432,433],{},"def on_page_views(data, meta):\n",[44,435,436],{"class":46,"line":246},[44,437,438],{},"    page_views_chart.update(data['count'], data['timestamp'])\n",[44,440,441],{"class":46,"line":258},[44,442,69],{"emptyLinePlaceholder":68},[44,444,445],{"class":46,"line":264},[44,446,447],{},"def on_active_users(data, meta):\n",[44,449,450],{"class":46,"line":269},[44,451,452],{},"    active_users_gauge.set_value(data['count'])\n",[44,454,455],{"class":46,"line":290},[44,456,69],{"emptyLinePlaceholder":68},[44,458,459],{"class":46,"line":302},[44,460,461],{},"def on_sales(data, meta):\n",[44,463,464],{"class":46,"line":307},[44,465,466],{},"    sales_chart.add_data_point(data['amount'], data['timestamp'])\n",[44,468,469],{"class":46,"line":312},[44,470,471],{},"    total_sales.increment(data['amount'])\n",[44,473,474],{"class":46,"line":333},[44,475,69],{"emptyLinePlaceholder":68},[44,477,478],{"class":46,"line":345},[44,479,480],{},"dashboard.on('page-views', on_page_views)\n",[44,482,483],{"class":46,"line":357},[44,484,485],{},"dashboard.on('active-users', on_active_users)\n",[44,487,489],{"class":46,"line":488},26,[44,490,491],{},"dashboard.on('sales', on_sales)\n",[33,493,498],{"className":494,"code":495,"filename":496,"language":497,"meta":39,"style":39},"language-go shiki shiki-themes github-light github-dark","package main\n\nimport nolag \"github.com/NoLagApp/go-sdk\"\n\nfunc main() {\n    client := nolag.New(\"your_access_token\")\n    client.Connect()\n\n    dashboard := client.SetApp(\"analytics\").SetRoom(\"live\")\n\n    // Subscribe to real-time metrics with handlers\n    dashboard.Subscribe(\"page-views\", func(data any, meta nolag.MessageMeta) {\n        d, _ := data.(map[string]any)\n        pageViewsChart.Update(d[\"count\"], d[\"timestamp\"])\n    })\n\n    dashboard.Subscribe(\"active-users\", func(data any, meta nolag.MessageMeta) {\n        d, _ := data.(map[string]any)\n        activeUsersGauge.SetValue(d[\"count\"].(int))\n    })\n\n    dashboard.Subscribe(\"sales\", func(data any, meta nolag.MessageMeta) {\n        d, _ := data.(map[string]any)\n        salesChart.AddDataPoint(d[\"amount\"], d[\"timestamp\"])\n        totalSales.Increment(d[\"amount\"].(float64))\n    })\n}\n","Go","go",[41,499,500,505,509,514,518,523,528,533,537,542,546,551,556,561,566,571,575,580,584,589,593,597,602,606,611,616,620],{"__ignoreMap":39},[44,501,502],{"class":46,"line":47},[44,503,504],{},"package main\n",[44,506,507],{"class":46,"line":65},[44,508,69],{"emptyLinePlaceholder":68},[44,510,511],{"class":46,"line":72},[44,512,513],{},"import nolag \"github.com/NoLagApp/go-sdk\"\n",[44,515,516],{"class":46,"line":98},[44,517,69],{"emptyLinePlaceholder":68},[44,519,520],{"class":46,"line":113},[44,521,522],{},"func main() {\n",[44,524,525],{"class":46,"line":118},[44,526,527],{},"    client := nolag.New(\"your_access_token\")\n",[44,529,530],{"class":46,"line":151},[44,531,532],{},"    client.Connect()\n",[44,534,535],{"class":46,"line":156},[44,536,69],{"emptyLinePlaceholder":68},[44,538,539],{"class":46,"line":163},[44,540,541],{},"    dashboard := client.SetApp(\"analytics\").SetRoom(\"live\")\n",[44,543,544],{"class":46,"line":179},[44,545,69],{"emptyLinePlaceholder":68},[44,547,548],{"class":46,"line":193},[44,549,550],{},"    // Subscribe to real-time metrics with handlers\n",[44,552,553],{"class":46,"line":207},[44,554,555],{},"    dashboard.Subscribe(\"page-views\", func(data any, meta nolag.MessageMeta) {\n",[44,557,558],{"class":46,"line":212},[44,559,560],{},"        d, _ := data.(map[string]any)\n",[44,562,563],{"class":46,"line":218},[44,564,565],{},"        pageViewsChart.Update(d[\"count\"], d[\"timestamp\"])\n",[44,567,568],{"class":46,"line":246},[44,569,570],{},"    })\n",[44,572,573],{"class":46,"line":258},[44,574,69],{"emptyLinePlaceholder":68},[44,576,577],{"class":46,"line":264},[44,578,579],{},"    dashboard.Subscribe(\"active-users\", func(data any, meta nolag.MessageMeta) {\n",[44,581,582],{"class":46,"line":269},[44,583,560],{},[44,585,586],{"class":46,"line":290},[44,587,588],{},"        activeUsersGauge.SetValue(d[\"count\"].(int))\n",[44,590,591],{"class":46,"line":302},[44,592,570],{},[44,594,595],{"class":46,"line":307},[44,596,69],{"emptyLinePlaceholder":68},[44,598,599],{"class":46,"line":312},[44,600,601],{},"    dashboard.Subscribe(\"sales\", func(data any, meta nolag.MessageMeta) {\n",[44,603,604],{"class":46,"line":333},[44,605,560],{},[44,607,608],{"class":46,"line":345},[44,609,610],{},"        salesChart.AddDataPoint(d[\"amount\"], d[\"timestamp\"])\n",[44,612,613],{"class":46,"line":357},[44,614,615],{},"        totalSales.Increment(d[\"amount\"].(float64))\n",[44,617,618],{"class":46,"line":488},[44,619,570],{},[44,621,623],{"class":46,"line":622},27,[44,624,625],{},"}\n",[18,627,629],{"id":628},"filtering-dashboard-updates","Filtering Dashboard Updates",[14,631,632],{},"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.",[14,634,635,639],{},[636,637,638],"strong",{},"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.",[30,641,642,981,1125],{},[33,643,645],{"className":35,"code":644,"filename":37,"language":38,"meta":39,"style":39},"import { NoLag } from '@nolag/js-sdk'\n\nconst client = NoLag('your_access_token')\nawait client.connect()\n\nconst dashboard = client.setApp('booking-system').setRoom('ops')\n\n// User is viewing 3 specific bookings on their dashboard\nconst visibleBookings = ['booking_42', 'booking_87', 'booking_153']\n\n// Subscribe with filters: only receive updates for these bookings\ndashboard.subscribe('bookings', {\n  filters: visibleBookings\n})\n\ndashboard.on('bookings', (data, meta) => {\n  // meta.filter tells you which booking was updated\n  updateBookingCard(meta.filter, data)\n})\n\n// User navigates to a different page, swap filters instantly\nfunction onPageChange(newBookingIds: string[]) {\n  dashboard.setFilters('bookings', newBookingIds)\n}\n\n// User opens a booking detail, add it to filters\nfunction onBookingOpen(bookingId: string) {\n  dashboard.addFilters('bookings', [bookingId])\n}\n\n// User closes a booking detail, remove it\nfunction onBookingClose(bookingId: string) {\n  dashboard.removeFilters('bookings', [bookingId])\n}\n",[41,646,647,657,661,677,687,691,719,723,728,757,761,766,780,785,789,793,818,823,831,835,839,844,866,881,885,889,894,913,928,933,938,944,962,976],{"__ignoreMap":39},[44,648,649,651,653,655],{"class":46,"line":47},[44,650,51],{"class":50},[44,652,55],{"class":54},[44,654,58],{"class":50},[44,656,62],{"class":61},[44,658,659],{"class":46,"line":65},[44,660,69],{"emptyLinePlaceholder":68},[44,662,663,665,667,669,671,673,675],{"class":46,"line":72},[44,664,75],{"class":50},[44,666,79],{"class":78},[44,668,82],{"class":50},[44,670,86],{"class":85},[44,672,89],{"class":54},[44,674,92],{"class":61},[44,676,95],{"class":54},[44,678,679,681,683,685],{"class":46,"line":98},[44,680,101],{"class":50},[44,682,104],{"class":54},[44,684,107],{"class":85},[44,686,110],{"class":54},[44,688,689],{"class":46,"line":113},[44,690,69],{"emptyLinePlaceholder":68},[44,692,693,695,697,699,701,703,705,708,710,712,714,717],{"class":46,"line":118},[44,694,75],{"class":50},[44,696,123],{"class":78},[44,698,82],{"class":50},[44,700,104],{"class":54},[44,702,130],{"class":85},[44,704,89],{"class":54},[44,706,707],{"class":61},"'booking-system'",[44,709,138],{"class":54},[44,711,141],{"class":85},[44,713,89],{"class":54},[44,715,716],{"class":61},"'ops'",[44,718,95],{"class":54},[44,720,721],{"class":46,"line":151},[44,722,69],{"emptyLinePlaceholder":68},[44,724,725],{"class":46,"line":156},[44,726,727],{"class":159},"// User is viewing 3 specific bookings on their dashboard\n",[44,729,730,732,735,737,740,743,746,749,751,754],{"class":46,"line":163},[44,731,75],{"class":50},[44,733,734],{"class":78}," visibleBookings",[44,736,82],{"class":50},[44,738,739],{"class":54}," [",[44,741,742],{"class":61},"'booking_42'",[44,744,745],{"class":54},", ",[44,747,748],{"class":61},"'booking_87'",[44,750,745],{"class":54},[44,752,753],{"class":61},"'booking_153'",[44,755,756],{"class":54},"]\n",[44,758,759],{"class":46,"line":179},[44,760,69],{"emptyLinePlaceholder":68},[44,762,763],{"class":46,"line":193},[44,764,765],{"class":159},"// Subscribe with filters: only receive updates for these bookings\n",[44,767,768,770,772,774,777],{"class":46,"line":207},[44,769,166],{"class":54},[44,771,169],{"class":85},[44,773,89],{"class":54},[44,775,776],{"class":61},"'bookings'",[44,778,779],{"class":54},", {\n",[44,781,782],{"class":46,"line":212},[44,783,784],{"class":54},"  filters: visibleBookings\n",[44,786,787],{"class":46,"line":218},[44,788,261],{"class":54},[44,790,791],{"class":46,"line":246},[44,792,69],{"emptyLinePlaceholder":68},[44,794,795,797,799,801,803,805,807,809,812,814,816],{"class":46,"line":258},[44,796,166],{"class":54},[44,798,223],{"class":85},[44,800,89],{"class":54},[44,802,776],{"class":61},[44,804,230],{"class":54},[44,806,234],{"class":233},[44,808,745],{"class":54},[44,810,811],{"class":233},"meta",[44,813,237],{"class":54},[44,815,240],{"class":50},[44,817,243],{"class":54},[44,819,820],{"class":46,"line":264},[44,821,822],{"class":159},"  // meta.filter tells you which booking was updated\n",[44,824,825,828],{"class":46,"line":269},[44,826,827],{"class":85},"  updateBookingCard",[44,829,830],{"class":54},"(meta.filter, data)\n",[44,832,833],{"class":46,"line":290},[44,834,261],{"class":54},[44,836,837],{"class":46,"line":302},[44,838,69],{"emptyLinePlaceholder":68},[44,840,841],{"class":46,"line":307},[44,842,843],{"class":159},"// User navigates to a different page, swap filters instantly\n",[44,845,846,849,852,854,857,860,863],{"class":46,"line":312},[44,847,848],{"class":50},"function",[44,850,851],{"class":85}," onPageChange",[44,853,89],{"class":54},[44,855,856],{"class":233},"newBookingIds",[44,858,859],{"class":50},":",[44,861,862],{"class":78}," string",[44,864,865],{"class":54},"[]) {\n",[44,867,868,871,874,876,878],{"class":46,"line":333},[44,869,870],{"class":54},"  dashboard.",[44,872,873],{"class":85},"setFilters",[44,875,89],{"class":54},[44,877,776],{"class":61},[44,879,880],{"class":54},", newBookingIds)\n",[44,882,883],{"class":46,"line":345},[44,884,625],{"class":54},[44,886,887],{"class":46,"line":357},[44,888,69],{"emptyLinePlaceholder":68},[44,890,891],{"class":46,"line":488},[44,892,893],{"class":159},"// User opens a booking detail, add it to filters\n",[44,895,896,898,901,903,906,908,910],{"class":46,"line":622},[44,897,848],{"class":50},[44,899,900],{"class":85}," onBookingOpen",[44,902,89],{"class":54},[44,904,905],{"class":233},"bookingId",[44,907,859],{"class":50},[44,909,862],{"class":78},[44,911,912],{"class":54},") {\n",[44,914,916,918,921,923,925],{"class":46,"line":915},28,[44,917,870],{"class":54},[44,919,920],{"class":85},"addFilters",[44,922,89],{"class":54},[44,924,776],{"class":61},[44,926,927],{"class":54},", [bookingId])\n",[44,929,931],{"class":46,"line":930},29,[44,932,625],{"class":54},[44,934,936],{"class":46,"line":935},30,[44,937,69],{"emptyLinePlaceholder":68},[44,939,941],{"class":46,"line":940},31,[44,942,943],{"class":159},"// User closes a booking detail, remove it\n",[44,945,947,949,952,954,956,958,960],{"class":46,"line":946},32,[44,948,848],{"class":50},[44,950,951],{"class":85}," onBookingClose",[44,953,89],{"class":54},[44,955,905],{"class":233},[44,957,859],{"class":50},[44,959,862],{"class":78},[44,961,912],{"class":54},[44,963,965,967,970,972,974],{"class":46,"line":964},33,[44,966,870],{"class":54},[44,968,969],{"class":85},"removeFilters",[44,971,89],{"class":54},[44,973,776],{"class":61},[44,975,927],{"class":54},[44,977,979],{"class":46,"line":978},34,[44,980,625],{"class":54},[33,982,984],{"className":362,"code":983,"filename":364,"language":365,"meta":39,"style":39},"from nolag import NoLag, SubscribeOptions\n\nclient = NoLag('your_access_token')\nawait client.connect()\n\ndashboard = client.set_app('booking-system').set_room('ops')\n\n# User is viewing 3 specific bookings on their dashboard\nvisible_bookings = ['booking_42', 'booking_87', 'booking_153']\n\n# Subscribe with filters\nawait dashboard.subscribe('bookings', SubscribeOptions(\n    filters=visible_bookings\n))\n\ndef on_booking_update(data, meta):\n    update_booking_card(meta.filter, data)\n\ndashboard.on('bookings', on_booking_update)\n\n# User navigates to a different page\nasync def on_page_change(new_booking_ids):\n    await dashboard.set_filters('bookings', new_booking_ids)\n\n# Add/remove individual bookings\nasync def on_booking_open(booking_id):\n    await dashboard.add_filters('bookings', [booking_id])\n\nasync def on_booking_close(booking_id):\n    await dashboard.remove_filters('bookings', [booking_id])\n",[41,985,986,991,995,999,1003,1007,1012,1016,1021,1026,1030,1035,1040,1045,1050,1054,1059,1064,1068,1073,1077,1082,1087,1092,1096,1101,1106,1111,1115,1120],{"__ignoreMap":39},[44,987,988],{"class":46,"line":47},[44,989,990],{},"from nolag import NoLag, SubscribeOptions\n",[44,992,993],{"class":46,"line":65},[44,994,69],{"emptyLinePlaceholder":68},[44,996,997],{"class":46,"line":72},[44,998,381],{},[44,1000,1001],{"class":46,"line":98},[44,1002,386],{},[44,1004,1005],{"class":46,"line":113},[44,1006,69],{"emptyLinePlaceholder":68},[44,1008,1009],{"class":46,"line":118},[44,1010,1011],{},"dashboard = client.set_app('booking-system').set_room('ops')\n",[44,1013,1014],{"class":46,"line":151},[44,1015,69],{"emptyLinePlaceholder":68},[44,1017,1018],{"class":46,"line":156},[44,1019,1020],{},"# User is viewing 3 specific bookings on their dashboard\n",[44,1022,1023],{"class":46,"line":163},[44,1024,1025],{},"visible_bookings = ['booking_42', 'booking_87', 'booking_153']\n",[44,1027,1028],{"class":46,"line":179},[44,1029,69],{"emptyLinePlaceholder":68},[44,1031,1032],{"class":46,"line":193},[44,1033,1034],{},"# Subscribe with filters\n",[44,1036,1037],{"class":46,"line":207},[44,1038,1039],{},"await dashboard.subscribe('bookings', SubscribeOptions(\n",[44,1041,1042],{"class":46,"line":212},[44,1043,1044],{},"    filters=visible_bookings\n",[44,1046,1047],{"class":46,"line":218},[44,1048,1049],{},"))\n",[44,1051,1052],{"class":46,"line":246},[44,1053,69],{"emptyLinePlaceholder":68},[44,1055,1056],{"class":46,"line":258},[44,1057,1058],{},"def on_booking_update(data, meta):\n",[44,1060,1061],{"class":46,"line":264},[44,1062,1063],{},"    update_booking_card(meta.filter, data)\n",[44,1065,1066],{"class":46,"line":269},[44,1067,69],{"emptyLinePlaceholder":68},[44,1069,1070],{"class":46,"line":290},[44,1071,1072],{},"dashboard.on('bookings', on_booking_update)\n",[44,1074,1075],{"class":46,"line":302},[44,1076,69],{"emptyLinePlaceholder":68},[44,1078,1079],{"class":46,"line":307},[44,1080,1081],{},"# User navigates to a different page\n",[44,1083,1084],{"class":46,"line":312},[44,1085,1086],{},"async def on_page_change(new_booking_ids):\n",[44,1088,1089],{"class":46,"line":333},[44,1090,1091],{},"    await dashboard.set_filters('bookings', new_booking_ids)\n",[44,1093,1094],{"class":46,"line":345},[44,1095,69],{"emptyLinePlaceholder":68},[44,1097,1098],{"class":46,"line":357},[44,1099,1100],{},"# Add/remove individual bookings\n",[44,1102,1103],{"class":46,"line":488},[44,1104,1105],{},"async def on_booking_open(booking_id):\n",[44,1107,1108],{"class":46,"line":622},[44,1109,1110],{},"    await dashboard.add_filters('bookings', [booking_id])\n",[44,1112,1113],{"class":46,"line":915},[44,1114,69],{"emptyLinePlaceholder":68},[44,1116,1117],{"class":46,"line":930},[44,1118,1119],{},"async def on_booking_close(booking_id):\n",[44,1121,1122],{"class":46,"line":935},[44,1123,1124],{},"    await dashboard.remove_filters('bookings', [booking_id])\n",[33,1126,1128],{"className":494,"code":1127,"filename":496,"language":497,"meta":39,"style":39},"package main\n\nimport nolag \"github.com/NoLagApp/go-sdk\"\n\nfunc main() {\n    client := nolag.New(\"your_access_token\")\n    client.Connect()\n\n    dashboard := client.SetApp(\"booking-system\").SetRoom(\"ops\")\n\n    // User is viewing 3 specific bookings\n    visibleBookings := []string{\"booking_42\", \"booking_87\", \"booking_153\"}\n\n    // Subscribe with filters and handler\n    dashboard.Subscribe(\"bookings\", func(data any, meta nolag.MessageMeta) {\n        updateBookingCard(meta.Filter, data)\n    }, nolag.SubscribeOptions{\n        Filters: visibleBookings,\n    })\n\n    // Swap filters on page change\n    dashboard.SetFilters(\"bookings\", []string{\"booking_200\", \"booking_201\"})\n}\n",[41,1129,1130,1134,1138,1142,1146,1150,1154,1158,1162,1167,1171,1176,1181,1185,1190,1195,1200,1205,1210,1214,1218,1223,1228],{"__ignoreMap":39},[44,1131,1132],{"class":46,"line":47},[44,1133,504],{},[44,1135,1136],{"class":46,"line":65},[44,1137,69],{"emptyLinePlaceholder":68},[44,1139,1140],{"class":46,"line":72},[44,1141,513],{},[44,1143,1144],{"class":46,"line":98},[44,1145,69],{"emptyLinePlaceholder":68},[44,1147,1148],{"class":46,"line":113},[44,1149,522],{},[44,1151,1152],{"class":46,"line":118},[44,1153,527],{},[44,1155,1156],{"class":46,"line":151},[44,1157,532],{},[44,1159,1160],{"class":46,"line":156},[44,1161,69],{"emptyLinePlaceholder":68},[44,1163,1164],{"class":46,"line":163},[44,1165,1166],{},"    dashboard := client.SetApp(\"booking-system\").SetRoom(\"ops\")\n",[44,1168,1169],{"class":46,"line":179},[44,1170,69],{"emptyLinePlaceholder":68},[44,1172,1173],{"class":46,"line":193},[44,1174,1175],{},"    // User is viewing 3 specific bookings\n",[44,1177,1178],{"class":46,"line":207},[44,1179,1180],{},"    visibleBookings := []string{\"booking_42\", \"booking_87\", \"booking_153\"}\n",[44,1182,1183],{"class":46,"line":212},[44,1184,69],{"emptyLinePlaceholder":68},[44,1186,1187],{"class":46,"line":218},[44,1188,1189],{},"    // Subscribe with filters and handler\n",[44,1191,1192],{"class":46,"line":246},[44,1193,1194],{},"    dashboard.Subscribe(\"bookings\", func(data any, meta nolag.MessageMeta) {\n",[44,1196,1197],{"class":46,"line":258},[44,1198,1199],{},"        updateBookingCard(meta.Filter, data)\n",[44,1201,1202],{"class":46,"line":264},[44,1203,1204],{},"    }, nolag.SubscribeOptions{\n",[44,1206,1207],{"class":46,"line":269},[44,1208,1209],{},"        Filters: visibleBookings,\n",[44,1211,1212],{"class":46,"line":290},[44,1213,570],{},[44,1215,1216],{"class":46,"line":302},[44,1217,69],{"emptyLinePlaceholder":68},[44,1219,1220],{"class":46,"line":307},[44,1221,1222],{},"    // Swap filters on page change\n",[44,1224,1225],{"class":46,"line":312},[44,1226,1227],{},"    dashboard.SetFilters(\"bookings\", []string{\"booking_200\", \"booking_201\"})\n",[44,1229,1230],{"class":46,"line":333},[44,1231,625],{},[1233,1234,1236],"h3",{"id":1235},"publishing-filtered-updates","Publishing Filtered Updates",[14,1238,1239,1240,1243],{},"On the backend, publish with a ",[41,1241,1242],{},"filter"," to target specific entities. Only dashboard clients watching that entity receive the update:",[30,1245,1246,1376,1443],{},[33,1247,1249],{"className":35,"code":1248,"filename":37,"language":38,"meta":39,"style":39},"// Backend service publishes updates with filters\n// Only dashboard users watching this specific booking receive it\nroom.emit('bookings', {\n  status: 'confirmed',\n  guest: 'John Smith',\n  checkIn: '2026-03-15'\n}, {\n  filter: 'booking_42'  // Target a specific booking\n})\n\n// Publish a different booking update\nroom.emit('bookings', {\n  status: 'cancelled',\n  reason: 'Guest request'\n}, {\n  filter: 'booking_87'\n})\n",[41,1250,1251,1256,1261,1275,1286,1296,1304,1309,1319,1323,1327,1332,1344,1353,1361,1365,1372],{"__ignoreMap":39},[44,1252,1253],{"class":46,"line":47},[44,1254,1255],{"class":159},"// Backend service publishes updates with filters\n",[44,1257,1258],{"class":46,"line":65},[44,1259,1260],{"class":159},"// Only dashboard users watching this specific booking receive it\n",[44,1262,1263,1266,1269,1271,1273],{"class":46,"line":72},[44,1264,1265],{"class":54},"room.",[44,1267,1268],{"class":85},"emit",[44,1270,89],{"class":54},[44,1272,776],{"class":61},[44,1274,779],{"class":54},[44,1276,1277,1280,1283],{"class":46,"line":98},[44,1278,1279],{"class":54},"  status: ",[44,1281,1282],{"class":61},"'confirmed'",[44,1284,1285],{"class":54},",\n",[44,1287,1288,1291,1294],{"class":46,"line":113},[44,1289,1290],{"class":54},"  guest: ",[44,1292,1293],{"class":61},"'John Smith'",[44,1295,1285],{"class":54},[44,1297,1298,1301],{"class":46,"line":118},[44,1299,1300],{"class":54},"  checkIn: ",[44,1302,1303],{"class":61},"'2026-03-15'\n",[44,1305,1306],{"class":46,"line":151},[44,1307,1308],{"class":54},"}, {\n",[44,1310,1311,1314,1316],{"class":46,"line":156},[44,1312,1313],{"class":54},"  filter: ",[44,1315,742],{"class":61},[44,1317,1318],{"class":159},"  // Target a specific booking\n",[44,1320,1321],{"class":46,"line":163},[44,1322,261],{"class":54},[44,1324,1325],{"class":46,"line":179},[44,1326,69],{"emptyLinePlaceholder":68},[44,1328,1329],{"class":46,"line":193},[44,1330,1331],{"class":159},"// Publish a different booking update\n",[44,1333,1334,1336,1338,1340,1342],{"class":46,"line":207},[44,1335,1265],{"class":54},[44,1337,1268],{"class":85},[44,1339,89],{"class":54},[44,1341,776],{"class":61},[44,1343,779],{"class":54},[44,1345,1346,1348,1351],{"class":46,"line":212},[44,1347,1279],{"class":54},[44,1349,1350],{"class":61},"'cancelled'",[44,1352,1285],{"class":54},[44,1354,1355,1358],{"class":46,"line":218},[44,1356,1357],{"class":54},"  reason: ",[44,1359,1360],{"class":61},"'Guest request'\n",[44,1362,1363],{"class":46,"line":246},[44,1364,1308],{"class":54},[44,1366,1367,1369],{"class":46,"line":258},[44,1368,1313],{"class":54},[44,1370,1371],{"class":61},"'booking_87'\n",[44,1373,1374],{"class":46,"line":264},[44,1375,261],{"class":54},[33,1377,1379],{"className":362,"code":1378,"filename":364,"language":365,"meta":39,"style":39},"from nolag import EmitOptions\n\n# Backend service publishes updates with filters\nawait room.emit('bookings', {\n    'status': 'confirmed',\n    'guest': 'John Smith',\n    'check_in': '2026-03-15'\n}, EmitOptions(filter='booking_42'))\n\nawait room.emit('bookings', {\n    'status': 'cancelled',\n    'reason': 'Guest request'\n}, EmitOptions(filter='booking_87'))\n",[41,1380,1381,1386,1390,1395,1400,1405,1410,1415,1420,1424,1428,1433,1438],{"__ignoreMap":39},[44,1382,1383],{"class":46,"line":47},[44,1384,1385],{},"from nolag import EmitOptions\n",[44,1387,1388],{"class":46,"line":65},[44,1389,69],{"emptyLinePlaceholder":68},[44,1391,1392],{"class":46,"line":72},[44,1393,1394],{},"# Backend service publishes updates with filters\n",[44,1396,1397],{"class":46,"line":98},[44,1398,1399],{},"await room.emit('bookings', {\n",[44,1401,1402],{"class":46,"line":113},[44,1403,1404],{},"    'status': 'confirmed',\n",[44,1406,1407],{"class":46,"line":118},[44,1408,1409],{},"    'guest': 'John Smith',\n",[44,1411,1412],{"class":46,"line":151},[44,1413,1414],{},"    'check_in': '2026-03-15'\n",[44,1416,1417],{"class":46,"line":156},[44,1418,1419],{},"}, EmitOptions(filter='booking_42'))\n",[44,1421,1422],{"class":46,"line":163},[44,1423,69],{"emptyLinePlaceholder":68},[44,1425,1426],{"class":46,"line":179},[44,1427,1399],{},[44,1429,1430],{"class":46,"line":193},[44,1431,1432],{},"    'status': 'cancelled',\n",[44,1434,1435],{"class":46,"line":207},[44,1436,1437],{},"    'reason': 'Guest request'\n",[44,1439,1440],{"class":46,"line":212},[44,1441,1442],{},"}, EmitOptions(filter='booking_87'))\n",[33,1444,1446],{"className":494,"code":1445,"filename":496,"language":497,"meta":39,"style":39},"// Backend service publishes updates with filters\nroom.Emit(\"bookings\", map[string]string{\n    \"status\": \"confirmed\",\n    \"guest\":  \"John Smith\",\n    \"checkIn\": \"2026-03-15\",\n}, nolag.EmitOptions{Filter: \"booking_42\"})\n\nroom.Emit(\"bookings\", map[string]string{\n    \"status\": \"cancelled\",\n    \"reason\": \"Guest request\",\n}, nolag.EmitOptions{Filter: \"booking_87\"})\n",[41,1447,1448,1452,1457,1462,1467,1472,1477,1481,1485,1490,1495],{"__ignoreMap":39},[44,1449,1450],{"class":46,"line":47},[44,1451,1255],{},[44,1453,1454],{"class":46,"line":65},[44,1455,1456],{},"room.Emit(\"bookings\", map[string]string{\n",[44,1458,1459],{"class":46,"line":72},[44,1460,1461],{},"    \"status\": \"confirmed\",\n",[44,1463,1464],{"class":46,"line":98},[44,1465,1466],{},"    \"guest\":  \"John Smith\",\n",[44,1468,1469],{"class":46,"line":113},[44,1470,1471],{},"    \"checkIn\": \"2026-03-15\",\n",[44,1473,1474],{"class":46,"line":118},[44,1475,1476],{},"}, nolag.EmitOptions{Filter: \"booking_42\"})\n",[44,1478,1479],{"class":46,"line":151},[44,1480,69],{"emptyLinePlaceholder":68},[44,1482,1483],{"class":46,"line":156},[44,1484,1456],{},[44,1486,1487],{"class":46,"line":163},[44,1488,1489],{},"    \"status\": \"cancelled\",\n",[44,1491,1492],{"class":46,"line":179},[44,1493,1494],{},"    \"reason\": \"Guest request\",\n",[44,1496,1497],{"class":46,"line":193},[44,1498,1499],{},"}, nolag.EmitOptions{Filter: \"booking_87\"})\n",[1501,1502,1504],"callout",{"type":1503},"tip",[14,1505,1506,1509,1510,1515],{},[636,1507,1508],{},"Tip:"," Filtering happens at the infrastructure level, no payload inspection, no wasted bandwidth. See ",[1511,1512,1514],"a",{"href":1513},"/docs/concepts/filters","Topic Filters"," for full details.",[18,1517,1519],{"id":1518},"use-cases","Use Cases",[1521,1522,1523,1530,1536,1542],"ul",{},[1524,1525,1526,1529],"li",{},[636,1527,1528],{},"Analytics dashboards"," - Page views, user sessions, conversion rates",[1524,1531,1532,1535],{},[636,1533,1534],{},"Sales dashboards"," - Revenue, orders, inventory levels",[1524,1537,1538,1541],{},[636,1539,1540],{},"Operations dashboards"," - Server health, error rates, response times",[1524,1543,1544,1547],{},[636,1545,1546],{},"Trading dashboards"," - Stock prices, market data, portfolio values",[18,1549,1551],{"id":1550},"architecture","Architecture",[1553,1554,1555,1558,1561],"ol",{},[1524,1556,1557],{},"Backend services publish metrics to NoLag topics",[1524,1559,1560],{},"Dashboard clients subscribe to relevant topics",[1524,1562,1563],{},"Charts and gauges update in real-time as data arrives",[18,1565,1567],{"id":1566},"best-practices","Best Practices",[1521,1569,1570,1577,1582,1585,1588,1591],{},[1524,1571,1572,1573,1576],{},"Use ",[636,1574,1575],{},"filters"," to subscribe only to entities visible on screen to avoid receiving thousands of irrelevant updates",[1524,1578,1572,1579,1581],{},[41,1580,873],{}," when the user navigates, it swaps filters atomically with minimal message gaps",[1524,1583,1584],{},"Use separate topics for different metric types",[1524,1586,1587],{},"Batch updates for high-frequency data to reduce rendering overhead",[1524,1589,1590],{},"Use per-topic hydration webhooks to load initial dashboard state",[1524,1592,1593],{},"Consider data retention and historical data storage separately",[18,1595,1597],{"id":1596},"next-steps","Next Steps",[1521,1599,1600,1605,1611],{},[1524,1601,1602,1604],{},[1511,1603,1514],{"href":1513}," - full reference for filter-based subscriptions",[1524,1606,1607],{},[1511,1608,1610],{"href":1609},"/docs/concepts/topics","Topics & Pub/Sub",[1524,1612,1613],{},[1511,1614,1616],{"href":1615},"/docs/concepts/qos","Quality of Service",[1618,1619,1620],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":39,"searchDepth":65,"depth":65,"links":1622},[1623,1624,1625,1628,1629,1630,1631],{"id":20,"depth":65,"text":21},{"id":27,"depth":65,"text":28},{"id":628,"depth":65,"text":629,"children":1626},[1627],{"id":1235,"depth":72,"text":1236},{"id":1518,"depth":65,"text":1519},{"id":1550,"depth":65,"text":1551},{"id":1566,"depth":65,"text":1567},{"id":1596,"depth":65,"text":1597},"Build real-time dashboards and live data visualizations with NoLag.","md",{},"/docs/guides/dashboards",{"title":5,"description":1632},"docs/guides/dashboards","fSaoACC9hRVuw2t8BnbAO37qmy7tEW0muIlLOE0VJAk",1788160343441]