[{"data":1,"prerenderedAt":3423},["ShallowReactive",2],{"docs:/docs/concepts/lobbies":3},{"id":4,"title":5,"body":6,"description":3416,"extension":3417,"meta":3418,"navigation":237,"path":3419,"seo":3420,"stem":3421,"__hash__":3422},"docs/docs/concepts/lobbies.md","Lobbies",{"type":7,"value":8,"toc":3401},"minimark",[9,13,17,22,35,110,120,124,158,162,189,202,206,209,1043,1047,1050,1621,1625,1631,2098,2102,2232,2236,2239,3024,3028,3031,3160,3164,3167,3249,3253,3285,3289,3366,3370,3397],[10,11,5],"h1",{"id":12},"lobbies",[14,15,16],"p",{},"Observe presence across multiple rooms. Build dashboards that monitor all active sessions, trips, games, or conversations in real-time.",[18,19,21],"h2",{"id":20},"what-is-a-lobby","What is a Lobby?",[14,23,24,25,29,30,34],{},"A ",[26,27,28],"strong",{},"Lobby"," is a group of rooms that share presence visibility. While actors in a room can only see each other, a lobby observer can see presence from ",[31,32,33],"em",{},"all rooms"," in that lobby.",[36,37,38],"code-tabs",{},[39,40,46],"pre",{"className":41,"code":42,"filename":43,"language":44,"meta":45,"style":45},"language-typescript shiki shiki-themes github-light github-dark","// The Hotel Metaphor\n//\n// Room 101 (trip-123)  -> Driver + Rider (private conversation)\n// Room 102 (trip-456)  -> Driver + Rider (private conversation)\n// Room 103 (trip-789)  -> Driver + Rider (private conversation)\n//\n// Lobby (active-trips) -> Dashboard sees everyone who's \"checked in\"\n//\n// Actors in rooms can only see each other within that room.\n// The dashboard in the lobby can see presence from ALL rooms.\n","TypeScript","typescript","",[47,48,49,58,64,70,76,82,87,93,98,104],"code",{"__ignoreMap":45},[50,51,54],"span",{"class":52,"line":53},"line",1,[50,55,57],{"class":56},"sJ8bj","// The Hotel Metaphor\n",[50,59,61],{"class":52,"line":60},2,[50,62,63],{"class":56},"//\n",[50,65,67],{"class":52,"line":66},3,[50,68,69],{"class":56},"// Room 101 (trip-123)  -> Driver + Rider (private conversation)\n",[50,71,73],{"class":52,"line":72},4,[50,74,75],{"class":56},"// Room 102 (trip-456)  -> Driver + Rider (private conversation)\n",[50,77,79],{"class":52,"line":78},5,[50,80,81],{"class":56},"// Room 103 (trip-789)  -> Driver + Rider (private conversation)\n",[50,83,85],{"class":52,"line":84},6,[50,86,63],{"class":56},[50,88,90],{"class":52,"line":89},7,[50,91,92],{"class":56},"// Lobby (active-trips) -> Dashboard sees everyone who's \"checked in\"\n",[50,94,96],{"class":52,"line":95},8,[50,97,63],{"class":56},[50,99,101],{"class":52,"line":100},9,[50,102,103],{"class":56},"// Actors in rooms can only see each other within that room.\n",[50,105,107],{"class":52,"line":106},10,[50,108,109],{"class":56},"// The dashboard in the lobby can see presence from ALL rooms.\n",[111,112,114],"callout",{"type":113},"info",[14,115,116,119],{},[26,117,118],{},"Read-only observation:"," Lobbies are for observing presence only. Actors cannot publish messages or set presence directly on a lobby - they must do so on a room.",[18,121,123],{"id":122},"use-cases","Use Cases",[125,126,127,134,140,146,152],"ul",{},[128,129,130,133],"li",{},[26,131,132],{},"Ride-sharing dashboard"," - Monitor all active trips, see driver locations across the city",[128,135,136,139],{},[26,137,138],{},"Support center"," - View all active support conversations, see agent availability",[128,141,142,145],{},[26,143,144],{},"Game matchmaking"," - Observe all game lobbies, show player counts",[128,147,148,151],{},[26,149,150],{},"IoT monitoring"," - Track all connected devices across multiple facilities",[128,153,154,157],{},[26,155,156],{},"Trading floor"," - Monitor all active trading sessions",[18,159,161],{"id":160},"how-it-works","How It Works",[163,164,165,171,177,183],"ol",{},[128,166,167,170],{},[26,168,169],{},"Actors set presence on rooms"," - Drivers, riders, players, etc. join their specific rooms",[128,172,173,176],{},[26,174,175],{},"Rooms are added to lobbies"," - Via REST API when a session starts",[128,178,179,182],{},[26,180,181],{},"Presence auto-propagates"," - When presence is set on a room, it automatically propagates to all lobbies containing that room",[128,184,185,188],{},[26,186,187],{},"Dashboard subscribes to lobby"," - Receives aggregated presence from all rooms",[111,190,192],{"type":191},"warning",[14,193,194,197,198,201],{},[26,195,196],{},"Limit:"," A room can belong to a maximum of ",[26,199,200],{},"10 lobbies",". This bounds the fan-out when presence is updated.",[18,203,205],{"id":204},"setting-presence-on-a-room","Setting Presence on a Room",[14,207,208],{},"Actors set presence on their room. This presence automatically propagates to any lobbies the room belongs to:",[36,210,211,636,823],{},[39,212,214],{"className":41,"code":213,"filename":43,"language":44,"meta":45,"style":45},"import { NoLag } from '@nolag/js-sdk'\n\nconst client = NoLag('driver_token')\nawait client.connect()\n\n// Driver joins trip room and sets presence\nconst trip = client.setApp('rides').setRoom('trip-123')\n\ntrip.setPresence({\n  role: 'driver',\n  name: 'John Smith',\n  vehicle: 'Toyota Camry',\n  location: { lat: 37.77, lng: -122.41 }\n})\n\n// Update location as driving\nsetInterval(() => {\n  trip.setPresence({\n    role: 'driver',\n    name: 'John Smith',\n    vehicle: 'Toyota Camry',\n    location: getCurrentLocation()\n  })\n}, 5000)\n\n// Listen for presence events (client-level, not room-scoped)\nclient.on('presence:join', (actor) => {\n  console.log(`${actor.presence.name} joined`)\n})\n\nclient.on('presence:update', (actor) => {\n  if (actor.presence.role === 'rider') {\n    console.log('Rider location:', actor.presence.location)\n  }\n})\n",[47,215,216,233,239,264,278,282,287,319,323,334,345,356,367,388,394,399,405,420,430,440,450,460,471,477,488,493,499,527,559,564,569,591,609,625,631],{"__ignoreMap":45},[50,217,218,222,226,229],{"class":52,"line":53},[50,219,221],{"class":220},"szBVR","import",[50,223,225],{"class":224},"sVt8B"," { NoLag } ",[50,227,228],{"class":220},"from",[50,230,232],{"class":231},"sZZnC"," '@nolag/js-sdk'\n",[50,234,235],{"class":52,"line":60},[50,236,238],{"emptyLinePlaceholder":237},true,"\n",[50,240,241,244,248,251,255,258,261],{"class":52,"line":66},[50,242,243],{"class":220},"const",[50,245,247],{"class":246},"sj4cs"," client",[50,249,250],{"class":220}," =",[50,252,254],{"class":253},"sScJk"," NoLag",[50,256,257],{"class":224},"(",[50,259,260],{"class":231},"'driver_token'",[50,262,263],{"class":224},")\n",[50,265,266,269,272,275],{"class":52,"line":72},[50,267,268],{"class":220},"await",[50,270,271],{"class":224}," client.",[50,273,274],{"class":253},"connect",[50,276,277],{"class":224},"()\n",[50,279,280],{"class":52,"line":78},[50,281,238],{"emptyLinePlaceholder":237},[50,283,284],{"class":52,"line":84},[50,285,286],{"class":56},"// Driver joins trip room and sets presence\n",[50,288,289,291,294,296,298,301,303,306,309,312,314,317],{"class":52,"line":89},[50,290,243],{"class":220},[50,292,293],{"class":246}," trip",[50,295,250],{"class":220},[50,297,271],{"class":224},[50,299,300],{"class":253},"setApp",[50,302,257],{"class":224},[50,304,305],{"class":231},"'rides'",[50,307,308],{"class":224},").",[50,310,311],{"class":253},"setRoom",[50,313,257],{"class":224},[50,315,316],{"class":231},"'trip-123'",[50,318,263],{"class":224},[50,320,321],{"class":52,"line":95},[50,322,238],{"emptyLinePlaceholder":237},[50,324,325,328,331],{"class":52,"line":100},[50,326,327],{"class":224},"trip.",[50,329,330],{"class":253},"setPresence",[50,332,333],{"class":224},"({\n",[50,335,336,339,342],{"class":52,"line":106},[50,337,338],{"class":224},"  role: ",[50,340,341],{"class":231},"'driver'",[50,343,344],{"class":224},",\n",[50,346,348,351,354],{"class":52,"line":347},11,[50,349,350],{"class":224},"  name: ",[50,352,353],{"class":231},"'John Smith'",[50,355,344],{"class":224},[50,357,359,362,365],{"class":52,"line":358},12,[50,360,361],{"class":224},"  vehicle: ",[50,363,364],{"class":231},"'Toyota Camry'",[50,366,344],{"class":224},[50,368,370,373,376,379,382,385],{"class":52,"line":369},13,[50,371,372],{"class":224},"  location: { lat: ",[50,374,375],{"class":246},"37.77",[50,377,378],{"class":224},", lng: ",[50,380,381],{"class":220},"-",[50,383,384],{"class":246},"122.41",[50,386,387],{"class":224}," }\n",[50,389,391],{"class":52,"line":390},14,[50,392,393],{"class":224},"})\n",[50,395,397],{"class":52,"line":396},15,[50,398,238],{"emptyLinePlaceholder":237},[50,400,402],{"class":52,"line":401},16,[50,403,404],{"class":56},"// Update location as driving\n",[50,406,408,411,414,417],{"class":52,"line":407},17,[50,409,410],{"class":253},"setInterval",[50,412,413],{"class":224},"(() ",[50,415,416],{"class":220},"=>",[50,418,419],{"class":224}," {\n",[50,421,423,426,428],{"class":52,"line":422},18,[50,424,425],{"class":224},"  trip.",[50,427,330],{"class":253},[50,429,333],{"class":224},[50,431,433,436,438],{"class":52,"line":432},19,[50,434,435],{"class":224},"    role: ",[50,437,341],{"class":231},[50,439,344],{"class":224},[50,441,443,446,448],{"class":52,"line":442},20,[50,444,445],{"class":224},"    name: ",[50,447,353],{"class":231},[50,449,344],{"class":224},[50,451,453,456,458],{"class":52,"line":452},21,[50,454,455],{"class":224},"    vehicle: ",[50,457,364],{"class":231},[50,459,344],{"class":224},[50,461,463,466,469],{"class":52,"line":462},22,[50,464,465],{"class":224},"    location: ",[50,467,468],{"class":253},"getCurrentLocation",[50,470,277],{"class":224},[50,472,474],{"class":52,"line":473},23,[50,475,476],{"class":224},"  })\n",[50,478,480,483,486],{"class":52,"line":479},24,[50,481,482],{"class":224},"}, ",[50,484,485],{"class":246},"5000",[50,487,263],{"class":224},[50,489,491],{"class":52,"line":490},25,[50,492,238],{"emptyLinePlaceholder":237},[50,494,496],{"class":52,"line":495},26,[50,497,498],{"class":56},"// Listen for presence events (client-level, not room-scoped)\n",[50,500,502,505,508,510,513,516,520,523,525],{"class":52,"line":501},27,[50,503,504],{"class":224},"client.",[50,506,507],{"class":253},"on",[50,509,257],{"class":224},[50,511,512],{"class":231},"'presence:join'",[50,514,515],{"class":224},", (",[50,517,519],{"class":518},"s4XuR","actor",[50,521,522],{"class":224},") ",[50,524,416],{"class":220},[50,526,419],{"class":224},[50,528,530,533,536,538,541,543,546,549,551,554,557],{"class":52,"line":529},28,[50,531,532],{"class":224},"  console.",[50,534,535],{"class":253},"log",[50,537,257],{"class":224},[50,539,540],{"class":231},"`${",[50,542,519],{"class":224},[50,544,545],{"class":231},".",[50,547,548],{"class":224},"presence",[50,550,545],{"class":231},[50,552,553],{"class":224},"name",[50,555,556],{"class":231},"} joined`",[50,558,263],{"class":224},[50,560,562],{"class":52,"line":561},29,[50,563,393],{"class":224},[50,565,567],{"class":52,"line":566},30,[50,568,238],{"emptyLinePlaceholder":237},[50,570,572,574,576,578,581,583,585,587,589],{"class":52,"line":571},31,[50,573,504],{"class":224},[50,575,507],{"class":253},[50,577,257],{"class":224},[50,579,580],{"class":231},"'presence:update'",[50,582,515],{"class":224},[50,584,519],{"class":518},[50,586,522],{"class":224},[50,588,416],{"class":220},[50,590,419],{"class":224},[50,592,594,597,600,603,606],{"class":52,"line":593},32,[50,595,596],{"class":220},"  if",[50,598,599],{"class":224}," (actor.presence.role ",[50,601,602],{"class":220},"===",[50,604,605],{"class":231}," 'rider'",[50,607,608],{"class":224},") {\n",[50,610,612,615,617,619,622],{"class":52,"line":611},33,[50,613,614],{"class":224},"    console.",[50,616,535],{"class":253},[50,618,257],{"class":224},[50,620,621],{"class":231},"'Rider location:'",[50,623,624],{"class":224},", actor.presence.location)\n",[50,626,628],{"class":52,"line":627},34,[50,629,630],{"class":224},"  }\n",[50,632,634],{"class":52,"line":633},35,[50,635,393],{"class":224},[39,637,642],{"className":638,"code":639,"filename":640,"language":641,"meta":45,"style":45},"language-python shiki shiki-themes github-light github-dark","from nolag import NoLag\n\nclient = NoLag('driver_token')\nawait client.connect()\n\n# Driver joins trip room and sets presence\ntrip = client.set_app('rides').set_room('trip-123')\n\n# Set presence at the client level (propagates to rooms/lobbies)\nawait client.set_presence({\n    'role': 'driver',\n    'name': 'John Smith',\n    'vehicle': 'Toyota Camry',\n    'location': {'lat': 37.77, 'lng': -122.41}\n})\n\n# Update location as driving\nasync def update_location():\n    while True:\n        await client.set_presence({\n            'role': 'driver',\n            'name': 'John Smith',\n            'vehicle': 'Toyota Camry',\n            'location': get_current_location()\n        })\n        await asyncio.sleep(5)\n\n# Listen for rider presence in the same room\ndef on_rider_join(actor):\n    print(f\"Rider {actor.presence['name']} joined the trip\")\n\ndef on_presence_update(actor):\n    if actor.presence['role'] == 'rider':\n        print('Rider location:', actor.presence['location'])\n\nclient.on('presence:join', on_rider_join)\nclient.on('presence:update', on_presence_update)\n","Python","python",[47,643,644,649,653,658,663,667,672,677,681,686,691,696,701,706,711,715,719,724,729,734,739,744,749,754,759,764,769,773,778,783,788,792,797,802,807,811,817],{"__ignoreMap":45},[50,645,646],{"class":52,"line":53},[50,647,648],{},"from nolag import NoLag\n",[50,650,651],{"class":52,"line":60},[50,652,238],{"emptyLinePlaceholder":237},[50,654,655],{"class":52,"line":66},[50,656,657],{},"client = NoLag('driver_token')\n",[50,659,660],{"class":52,"line":72},[50,661,662],{},"await client.connect()\n",[50,664,665],{"class":52,"line":78},[50,666,238],{"emptyLinePlaceholder":237},[50,668,669],{"class":52,"line":84},[50,670,671],{},"# Driver joins trip room and sets presence\n",[50,673,674],{"class":52,"line":89},[50,675,676],{},"trip = client.set_app('rides').set_room('trip-123')\n",[50,678,679],{"class":52,"line":95},[50,680,238],{"emptyLinePlaceholder":237},[50,682,683],{"class":52,"line":100},[50,684,685],{},"# Set presence at the client level (propagates to rooms/lobbies)\n",[50,687,688],{"class":52,"line":106},[50,689,690],{},"await client.set_presence({\n",[50,692,693],{"class":52,"line":347},[50,694,695],{},"    'role': 'driver',\n",[50,697,698],{"class":52,"line":358},[50,699,700],{},"    'name': 'John Smith',\n",[50,702,703],{"class":52,"line":369},[50,704,705],{},"    'vehicle': 'Toyota Camry',\n",[50,707,708],{"class":52,"line":390},[50,709,710],{},"    'location': {'lat': 37.77, 'lng': -122.41}\n",[50,712,713],{"class":52,"line":396},[50,714,393],{},[50,716,717],{"class":52,"line":401},[50,718,238],{"emptyLinePlaceholder":237},[50,720,721],{"class":52,"line":407},[50,722,723],{},"# Update location as driving\n",[50,725,726],{"class":52,"line":422},[50,727,728],{},"async def update_location():\n",[50,730,731],{"class":52,"line":432},[50,732,733],{},"    while True:\n",[50,735,736],{"class":52,"line":442},[50,737,738],{},"        await client.set_presence({\n",[50,740,741],{"class":52,"line":452},[50,742,743],{},"            'role': 'driver',\n",[50,745,746],{"class":52,"line":462},[50,747,748],{},"            'name': 'John Smith',\n",[50,750,751],{"class":52,"line":473},[50,752,753],{},"            'vehicle': 'Toyota Camry',\n",[50,755,756],{"class":52,"line":479},[50,757,758],{},"            'location': get_current_location()\n",[50,760,761],{"class":52,"line":490},[50,762,763],{},"        })\n",[50,765,766],{"class":52,"line":495},[50,767,768],{},"        await asyncio.sleep(5)\n",[50,770,771],{"class":52,"line":501},[50,772,238],{"emptyLinePlaceholder":237},[50,774,775],{"class":52,"line":529},[50,776,777],{},"# Listen for rider presence in the same room\n",[50,779,780],{"class":52,"line":561},[50,781,782],{},"def on_rider_join(actor):\n",[50,784,785],{"class":52,"line":566},[50,786,787],{},"    print(f\"Rider {actor.presence['name']} joined the trip\")\n",[50,789,790],{"class":52,"line":571},[50,791,238],{"emptyLinePlaceholder":237},[50,793,794],{"class":52,"line":593},[50,795,796],{},"def on_presence_update(actor):\n",[50,798,799],{"class":52,"line":611},[50,800,801],{},"    if actor.presence['role'] == 'rider':\n",[50,803,804],{"class":52,"line":627},[50,805,806],{},"        print('Rider location:', actor.presence['location'])\n",[50,808,809],{"class":52,"line":633},[50,810,238],{"emptyLinePlaceholder":237},[50,812,814],{"class":52,"line":813},36,[50,815,816],{},"client.on('presence:join', on_rider_join)\n",[50,818,820],{"class":52,"line":819},37,[50,821,822],{},"client.on('presence:update', on_presence_update)\n",[39,824,829],{"className":825,"code":826,"filename":827,"language":828,"meta":45,"style":45},"language-go shiki shiki-themes github-light github-dark","package main\n\nimport (\n    \"fmt\"\n    \"time\"\n\n    nolag \"github.com/NoLagApp/go-sdk\"\n)\n\nfunc main() {\n    client := nolag.New(\"driver_token\")\n    client.Connect()\n\n    // Driver joins trip room and sets presence\n    trip := client.SetApp(\"rides\").SetRoom(\"trip-123\")\n\n    // Set presence at the client level (propagates to rooms/lobbies)\n    client.SetPresence(map[string]any{\n        \"role\":     \"driver\",\n        \"name\":     \"John Smith\",\n        \"vehicle\":  \"Toyota Camry\",\n        \"location\": map[string]any{\"lat\": 37.77, \"lng\": -122.41},\n    })\n\n    // Update location as driving\n    go func() {\n        for {\n            client.SetPresence(map[string]any{\n                \"role\":     \"driver\",\n                \"name\":     \"John Smith\",\n                \"vehicle\":  \"Toyota Camry\",\n                \"location\": getCurrentLocation(),\n            })\n            time.Sleep(5 * time.Second)\n        }\n    }()\n\n    // Listen for presence events\n    client.On(\"presence\", func(args ...any) {\n        data, _ := args[1].(map[string]any)\n        fmt.Printf(\"Presence event: %v\\n\", data)\n    })\n}\n","Go","go",[47,830,831,836,840,845,850,855,859,864,868,872,877,882,887,891,896,901,905,910,915,920,925,930,935,940,944,949,954,959,964,969,974,979,984,989,994,999,1004,1008,1014,1020,1026,1032,1037],{"__ignoreMap":45},[50,832,833],{"class":52,"line":53},[50,834,835],{},"package main\n",[50,837,838],{"class":52,"line":60},[50,839,238],{"emptyLinePlaceholder":237},[50,841,842],{"class":52,"line":66},[50,843,844],{},"import (\n",[50,846,847],{"class":52,"line":72},[50,848,849],{},"    \"fmt\"\n",[50,851,852],{"class":52,"line":78},[50,853,854],{},"    \"time\"\n",[50,856,857],{"class":52,"line":84},[50,858,238],{"emptyLinePlaceholder":237},[50,860,861],{"class":52,"line":89},[50,862,863],{},"    nolag \"github.com/NoLagApp/go-sdk\"\n",[50,865,866],{"class":52,"line":95},[50,867,263],{},[50,869,870],{"class":52,"line":100},[50,871,238],{"emptyLinePlaceholder":237},[50,873,874],{"class":52,"line":106},[50,875,876],{},"func main() {\n",[50,878,879],{"class":52,"line":347},[50,880,881],{},"    client := nolag.New(\"driver_token\")\n",[50,883,884],{"class":52,"line":358},[50,885,886],{},"    client.Connect()\n",[50,888,889],{"class":52,"line":369},[50,890,238],{"emptyLinePlaceholder":237},[50,892,893],{"class":52,"line":390},[50,894,895],{},"    // Driver joins trip room and sets presence\n",[50,897,898],{"class":52,"line":396},[50,899,900],{},"    trip := client.SetApp(\"rides\").SetRoom(\"trip-123\")\n",[50,902,903],{"class":52,"line":401},[50,904,238],{"emptyLinePlaceholder":237},[50,906,907],{"class":52,"line":407},[50,908,909],{},"    // Set presence at the client level (propagates to rooms/lobbies)\n",[50,911,912],{"class":52,"line":422},[50,913,914],{},"    client.SetPresence(map[string]any{\n",[50,916,917],{"class":52,"line":432},[50,918,919],{},"        \"role\":     \"driver\",\n",[50,921,922],{"class":52,"line":442},[50,923,924],{},"        \"name\":     \"John Smith\",\n",[50,926,927],{"class":52,"line":452},[50,928,929],{},"        \"vehicle\":  \"Toyota Camry\",\n",[50,931,932],{"class":52,"line":462},[50,933,934],{},"        \"location\": map[string]any{\"lat\": 37.77, \"lng\": -122.41},\n",[50,936,937],{"class":52,"line":473},[50,938,939],{},"    })\n",[50,941,942],{"class":52,"line":479},[50,943,238],{"emptyLinePlaceholder":237},[50,945,946],{"class":52,"line":490},[50,947,948],{},"    // Update location as driving\n",[50,950,951],{"class":52,"line":495},[50,952,953],{},"    go func() {\n",[50,955,956],{"class":52,"line":501},[50,957,958],{},"        for {\n",[50,960,961],{"class":52,"line":529},[50,962,963],{},"            client.SetPresence(map[string]any{\n",[50,965,966],{"class":52,"line":561},[50,967,968],{},"                \"role\":     \"driver\",\n",[50,970,971],{"class":52,"line":566},[50,972,973],{},"                \"name\":     \"John Smith\",\n",[50,975,976],{"class":52,"line":571},[50,977,978],{},"                \"vehicle\":  \"Toyota Camry\",\n",[50,980,981],{"class":52,"line":593},[50,982,983],{},"                \"location\": getCurrentLocation(),\n",[50,985,986],{"class":52,"line":611},[50,987,988],{},"            })\n",[50,990,991],{"class":52,"line":627},[50,992,993],{},"            time.Sleep(5 * time.Second)\n",[50,995,996],{"class":52,"line":633},[50,997,998],{},"        }\n",[50,1000,1001],{"class":52,"line":813},[50,1002,1003],{},"    }()\n",[50,1005,1006],{"class":52,"line":819},[50,1007,238],{"emptyLinePlaceholder":237},[50,1009,1011],{"class":52,"line":1010},38,[50,1012,1013],{},"    // Listen for presence events\n",[50,1015,1017],{"class":52,"line":1016},39,[50,1018,1019],{},"    client.On(\"presence\", func(args ...any) {\n",[50,1021,1023],{"class":52,"line":1022},40,[50,1024,1025],{},"        data, _ := args[1].(map[string]any)\n",[50,1027,1029],{"class":52,"line":1028},41,[50,1030,1031],{},"        fmt.Printf(\"Presence event: %v\\n\", data)\n",[50,1033,1035],{"class":52,"line":1034},42,[50,1036,939],{},[50,1038,1040],{"class":52,"line":1039},43,[50,1041,1042],{},"}\n",[18,1044,1046],{"id":1045},"subscribing-to-a-lobby","Subscribing to a Lobby",[14,1048,1049],{},"Subscribe to a lobby to receive presence from all rooms. You'll get a snapshot of current presence when you subscribe, plus live updates as actors join, leave, or update:",[36,1051,1052,1349,1487],{},[39,1053,1055],{"className":41,"code":1054,"filename":43,"language":44,"meta":45,"style":45},"import { NoLag } from '@nolag/js-sdk'\n\nconst client = NoLag('dashboard_token')\nawait client.connect()\n\n// Subscribe to a lobby to observe all trips\nconst lobby = client.setApp('rides').setLobby('active-trips')\n\n// Subscribe returns a snapshot of current presence\nconst snapshot = await lobby.subscribe()\nconsole.log('Current trips:', Object.keys(snapshot))\n\n// snapshot structure: { roomId -> { actorId -> presenceData } }\n// {\n//   \"trip-123\": {\n//     \"driver-1\": { role: \"driver\", name: \"John\", location: {...} },\n//     \"rider-5\": { role: \"rider\", name: \"Alice\" }\n//   },\n//   \"trip-456\": {\n//     \"driver-2\": { role: \"driver\", name: \"Mike\", location: {...} }\n//   }\n// }\n\n// Build initial map\nconst presenceMap = new Map()\nfor (const [roomId, actors] of Object.entries(snapshot)) {\n  for (const [actorId, data] of Object.entries(actors)) {\n    addToMap(roomId, actorId, data)\n  }\n}\n",[47,1056,1057,1067,1071,1088,1098,1102,1107,1136,1140,1145,1165,1186,1190,1195,1200,1205,1210,1215,1220,1225,1230,1235,1240,1244,1249,1266,1303,1333,1341,1345],{"__ignoreMap":45},[50,1058,1059,1061,1063,1065],{"class":52,"line":53},[50,1060,221],{"class":220},[50,1062,225],{"class":224},[50,1064,228],{"class":220},[50,1066,232],{"class":231},[50,1068,1069],{"class":52,"line":60},[50,1070,238],{"emptyLinePlaceholder":237},[50,1072,1073,1075,1077,1079,1081,1083,1086],{"class":52,"line":66},[50,1074,243],{"class":220},[50,1076,247],{"class":246},[50,1078,250],{"class":220},[50,1080,254],{"class":253},[50,1082,257],{"class":224},[50,1084,1085],{"class":231},"'dashboard_token'",[50,1087,263],{"class":224},[50,1089,1090,1092,1094,1096],{"class":52,"line":72},[50,1091,268],{"class":220},[50,1093,271],{"class":224},[50,1095,274],{"class":253},[50,1097,277],{"class":224},[50,1099,1100],{"class":52,"line":78},[50,1101,238],{"emptyLinePlaceholder":237},[50,1103,1104],{"class":52,"line":84},[50,1105,1106],{"class":56},"// Subscribe to a lobby to observe all trips\n",[50,1108,1109,1111,1114,1116,1118,1120,1122,1124,1126,1129,1131,1134],{"class":52,"line":89},[50,1110,243],{"class":220},[50,1112,1113],{"class":246}," lobby",[50,1115,250],{"class":220},[50,1117,271],{"class":224},[50,1119,300],{"class":253},[50,1121,257],{"class":224},[50,1123,305],{"class":231},[50,1125,308],{"class":224},[50,1127,1128],{"class":253},"setLobby",[50,1130,257],{"class":224},[50,1132,1133],{"class":231},"'active-trips'",[50,1135,263],{"class":224},[50,1137,1138],{"class":52,"line":95},[50,1139,238],{"emptyLinePlaceholder":237},[50,1141,1142],{"class":52,"line":100},[50,1143,1144],{"class":56},"// Subscribe returns a snapshot of current presence\n",[50,1146,1147,1149,1152,1154,1157,1160,1163],{"class":52,"line":106},[50,1148,243],{"class":220},[50,1150,1151],{"class":246}," snapshot",[50,1153,250],{"class":220},[50,1155,1156],{"class":220}," await",[50,1158,1159],{"class":224}," lobby.",[50,1161,1162],{"class":253},"subscribe",[50,1164,277],{"class":224},[50,1166,1167,1170,1172,1174,1177,1180,1183],{"class":52,"line":347},[50,1168,1169],{"class":224},"console.",[50,1171,535],{"class":253},[50,1173,257],{"class":224},[50,1175,1176],{"class":231},"'Current trips:'",[50,1178,1179],{"class":224},", Object.",[50,1181,1182],{"class":253},"keys",[50,1184,1185],{"class":224},"(snapshot))\n",[50,1187,1188],{"class":52,"line":358},[50,1189,238],{"emptyLinePlaceholder":237},[50,1191,1192],{"class":52,"line":369},[50,1193,1194],{"class":56},"// snapshot structure: { roomId -> { actorId -> presenceData } }\n",[50,1196,1197],{"class":52,"line":390},[50,1198,1199],{"class":56},"// {\n",[50,1201,1202],{"class":52,"line":396},[50,1203,1204],{"class":56},"//   \"trip-123\": {\n",[50,1206,1207],{"class":52,"line":401},[50,1208,1209],{"class":56},"//     \"driver-1\": { role: \"driver\", name: \"John\", location: {...} },\n",[50,1211,1212],{"class":52,"line":407},[50,1213,1214],{"class":56},"//     \"rider-5\": { role: \"rider\", name: \"Alice\" }\n",[50,1216,1217],{"class":52,"line":422},[50,1218,1219],{"class":56},"//   },\n",[50,1221,1222],{"class":52,"line":432},[50,1223,1224],{"class":56},"//   \"trip-456\": {\n",[50,1226,1227],{"class":52,"line":442},[50,1228,1229],{"class":56},"//     \"driver-2\": { role: \"driver\", name: \"Mike\", location: {...} }\n",[50,1231,1232],{"class":52,"line":452},[50,1233,1234],{"class":56},"//   }\n",[50,1236,1237],{"class":52,"line":462},[50,1238,1239],{"class":56},"// }\n",[50,1241,1242],{"class":52,"line":473},[50,1243,238],{"emptyLinePlaceholder":237},[50,1245,1246],{"class":52,"line":479},[50,1247,1248],{"class":56},"// Build initial map\n",[50,1250,1251,1253,1256,1258,1261,1264],{"class":52,"line":490},[50,1252,243],{"class":220},[50,1254,1255],{"class":246}," presenceMap",[50,1257,250],{"class":220},[50,1259,1260],{"class":220}," new",[50,1262,1263],{"class":253}," Map",[50,1265,277],{"class":224},[50,1267,1268,1271,1274,1276,1279,1282,1285,1288,1291,1294,1297,1300],{"class":52,"line":495},[50,1269,1270],{"class":220},"for",[50,1272,1273],{"class":224}," (",[50,1275,243],{"class":220},[50,1277,1278],{"class":224}," [",[50,1280,1281],{"class":246},"roomId",[50,1283,1284],{"class":224},", ",[50,1286,1287],{"class":246},"actors",[50,1289,1290],{"class":224},"] ",[50,1292,1293],{"class":220},"of",[50,1295,1296],{"class":224}," Object.",[50,1298,1299],{"class":253},"entries",[50,1301,1302],{"class":224},"(snapshot)) {\n",[50,1304,1305,1308,1310,1312,1314,1317,1319,1322,1324,1326,1328,1330],{"class":52,"line":501},[50,1306,1307],{"class":220},"  for",[50,1309,1273],{"class":224},[50,1311,243],{"class":220},[50,1313,1278],{"class":224},[50,1315,1316],{"class":246},"actorId",[50,1318,1284],{"class":224},[50,1320,1321],{"class":246},"data",[50,1323,1290],{"class":224},[50,1325,1293],{"class":220},[50,1327,1296],{"class":224},[50,1329,1299],{"class":253},[50,1331,1332],{"class":224},"(actors)) {\n",[50,1334,1335,1338],{"class":52,"line":529},[50,1336,1337],{"class":253},"    addToMap",[50,1339,1340],{"class":224},"(roomId, actorId, data)\n",[50,1342,1343],{"class":52,"line":561},[50,1344,630],{"class":224},[50,1346,1347],{"class":52,"line":566},[50,1348,1042],{"class":224},[39,1350,1352],{"className":638,"code":1351,"filename":640,"language":641,"meta":45,"style":45},"from nolag import NoLag\n\nclient = NoLag('dashboard_token')\nawait client.connect()\n\n# Subscribe to a lobby to observe all trips\nlobby = client.set_app('rides').set_lobby('active-trips')\n\n# Subscribe returns a snapshot of current presence\nsnapshot = await lobby.subscribe()\nprint('Current trips:', list(snapshot.keys()))\n\n# snapshot structure: { roomId -> { actorId -> presenceData } }\n# {\n#   \"trip-123\": {\n#     \"driver-1\": { \"role\": \"driver\", \"name\": \"John\", \"location\": {...} },\n#     \"rider-5\": { \"role\": \"rider\", \"name\": \"Alice\" }\n#   },\n#   \"trip-456\": {\n#     \"driver-2\": { \"role\": \"driver\", \"name\": \"Mike\", \"location\": {...} }\n#   }\n# }\n\n# Build initial map\npresence_map = {}\nfor room_id, actors in snapshot.items():\n    for actor_id, data in actors.items():\n        add_to_map(room_id, actor_id, data)\n",[47,1353,1354,1358,1362,1367,1371,1375,1380,1385,1389,1394,1399,1404,1408,1413,1418,1423,1428,1433,1438,1443,1448,1453,1458,1462,1467,1472,1477,1482],{"__ignoreMap":45},[50,1355,1356],{"class":52,"line":53},[50,1357,648],{},[50,1359,1360],{"class":52,"line":60},[50,1361,238],{"emptyLinePlaceholder":237},[50,1363,1364],{"class":52,"line":66},[50,1365,1366],{},"client = NoLag('dashboard_token')\n",[50,1368,1369],{"class":52,"line":72},[50,1370,662],{},[50,1372,1373],{"class":52,"line":78},[50,1374,238],{"emptyLinePlaceholder":237},[50,1376,1377],{"class":52,"line":84},[50,1378,1379],{},"# Subscribe to a lobby to observe all trips\n",[50,1381,1382],{"class":52,"line":89},[50,1383,1384],{},"lobby = client.set_app('rides').set_lobby('active-trips')\n",[50,1386,1387],{"class":52,"line":95},[50,1388,238],{"emptyLinePlaceholder":237},[50,1390,1391],{"class":52,"line":100},[50,1392,1393],{},"# Subscribe returns a snapshot of current presence\n",[50,1395,1396],{"class":52,"line":106},[50,1397,1398],{},"snapshot = await lobby.subscribe()\n",[50,1400,1401],{"class":52,"line":347},[50,1402,1403],{},"print('Current trips:', list(snapshot.keys()))\n",[50,1405,1406],{"class":52,"line":358},[50,1407,238],{"emptyLinePlaceholder":237},[50,1409,1410],{"class":52,"line":369},[50,1411,1412],{},"# snapshot structure: { roomId -> { actorId -> presenceData } }\n",[50,1414,1415],{"class":52,"line":390},[50,1416,1417],{},"# {\n",[50,1419,1420],{"class":52,"line":396},[50,1421,1422],{},"#   \"trip-123\": {\n",[50,1424,1425],{"class":52,"line":401},[50,1426,1427],{},"#     \"driver-1\": { \"role\": \"driver\", \"name\": \"John\", \"location\": {...} },\n",[50,1429,1430],{"class":52,"line":407},[50,1431,1432],{},"#     \"rider-5\": { \"role\": \"rider\", \"name\": \"Alice\" }\n",[50,1434,1435],{"class":52,"line":422},[50,1436,1437],{},"#   },\n",[50,1439,1440],{"class":52,"line":432},[50,1441,1442],{},"#   \"trip-456\": {\n",[50,1444,1445],{"class":52,"line":442},[50,1446,1447],{},"#     \"driver-2\": { \"role\": \"driver\", \"name\": \"Mike\", \"location\": {...} }\n",[50,1449,1450],{"class":52,"line":452},[50,1451,1452],{},"#   }\n",[50,1454,1455],{"class":52,"line":462},[50,1456,1457],{},"# }\n",[50,1459,1460],{"class":52,"line":473},[50,1461,238],{"emptyLinePlaceholder":237},[50,1463,1464],{"class":52,"line":479},[50,1465,1466],{},"# Build initial map\n",[50,1468,1469],{"class":52,"line":490},[50,1470,1471],{},"presence_map = {}\n",[50,1473,1474],{"class":52,"line":495},[50,1475,1476],{},"for room_id, actors in snapshot.items():\n",[50,1478,1479],{"class":52,"line":501},[50,1480,1481],{},"    for actor_id, data in actors.items():\n",[50,1483,1484],{"class":52,"line":529},[50,1485,1486],{},"        add_to_map(room_id, actor_id, data)\n",[39,1488,1490],{"className":825,"code":1489,"filename":827,"language":828,"meta":45,"style":45},"package main\n\nimport (\n    \"fmt\"\n\n    nolag \"github.com/NoLagApp/go-sdk\"\n)\n\nfunc main() {\n    client := nolag.New(\"dashboard_token\")\n    client.Connect()\n\n    // Subscribe to a lobby to observe all trips\n    lobby := client.SetApp(\"rides\").SetLobby(\"active-trips\")\n\n    // Subscribe returns a snapshot of current presence\n    snapshot, err := lobby.Subscribe()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"Current trips:\", len(snapshot))\n\n    // snapshot structure: map[roomId]map[actorId]presenceData\n    for roomId, actors := range snapshot {\n        for actorId, data := range actors {\n            addToMap(roomId, actorId, data)\n        }\n    }\n}\n",[47,1491,1492,1496,1500,1504,1508,1512,1516,1520,1524,1528,1533,1537,1541,1546,1551,1555,1560,1565,1570,1575,1580,1585,1589,1594,1599,1604,1609,1613,1617],{"__ignoreMap":45},[50,1493,1494],{"class":52,"line":53},[50,1495,835],{},[50,1497,1498],{"class":52,"line":60},[50,1499,238],{"emptyLinePlaceholder":237},[50,1501,1502],{"class":52,"line":66},[50,1503,844],{},[50,1505,1506],{"class":52,"line":72},[50,1507,849],{},[50,1509,1510],{"class":52,"line":78},[50,1511,238],{"emptyLinePlaceholder":237},[50,1513,1514],{"class":52,"line":84},[50,1515,863],{},[50,1517,1518],{"class":52,"line":89},[50,1519,263],{},[50,1521,1522],{"class":52,"line":95},[50,1523,238],{"emptyLinePlaceholder":237},[50,1525,1526],{"class":52,"line":100},[50,1527,876],{},[50,1529,1530],{"class":52,"line":106},[50,1531,1532],{},"    client := nolag.New(\"dashboard_token\")\n",[50,1534,1535],{"class":52,"line":347},[50,1536,886],{},[50,1538,1539],{"class":52,"line":358},[50,1540,238],{"emptyLinePlaceholder":237},[50,1542,1543],{"class":52,"line":369},[50,1544,1545],{},"    // Subscribe to a lobby to observe all trips\n",[50,1547,1548],{"class":52,"line":390},[50,1549,1550],{},"    lobby := client.SetApp(\"rides\").SetLobby(\"active-trips\")\n",[50,1552,1553],{"class":52,"line":396},[50,1554,238],{"emptyLinePlaceholder":237},[50,1556,1557],{"class":52,"line":401},[50,1558,1559],{},"    // Subscribe returns a snapshot of current presence\n",[50,1561,1562],{"class":52,"line":407},[50,1563,1564],{},"    snapshot, err := lobby.Subscribe()\n",[50,1566,1567],{"class":52,"line":422},[50,1568,1569],{},"    if err != nil {\n",[50,1571,1572],{"class":52,"line":432},[50,1573,1574],{},"        panic(err)\n",[50,1576,1577],{"class":52,"line":442},[50,1578,1579],{},"    }\n",[50,1581,1582],{"class":52,"line":452},[50,1583,1584],{},"    fmt.Println(\"Current trips:\", len(snapshot))\n",[50,1586,1587],{"class":52,"line":462},[50,1588,238],{"emptyLinePlaceholder":237},[50,1590,1591],{"class":52,"line":473},[50,1592,1593],{},"    // snapshot structure: map[roomId]map[actorId]presenceData\n",[50,1595,1596],{"class":52,"line":479},[50,1597,1598],{},"    for roomId, actors := range snapshot {\n",[50,1600,1601],{"class":52,"line":490},[50,1602,1603],{},"        for actorId, data := range actors {\n",[50,1605,1606],{"class":52,"line":495},[50,1607,1608],{},"            addToMap(roomId, actorId, data)\n",[50,1610,1611],{"class":52,"line":501},[50,1612,998],{},[50,1614,1615],{"class":52,"line":529},[50,1616,1579],{},[50,1618,1619],{"class":52,"line":561},[50,1620,1042],{},[18,1622,1624],{"id":1623},"lobby-presence-events","Lobby Presence Events",[14,1626,1627,1628,1630],{},"Lobby presence events include the ",[47,1629,1281],{}," so you know which room the presence came from. This lets you group actors by room on your dashboard:",[36,1632,1633,1888,1998],{},[39,1634,1636],{"className":41,"code":1635,"filename":43,"language":44,"meta":45,"style":45},"// Listen for presence events (includes room context)\nlobby.on('presence:join', (event) => {\n  // event: { lobbyId, roomId, actorId, data }\n  console.log(`${event.actorId} joined room ${event.roomId}`)\n  addToMap(event.roomId, event.actorId, event.data)\n})\n\nlobby.on('presence:update', (event) => {\n  console.log(`${event.actorId} in room ${event.roomId} updated`)\n  updateOnMap(event.roomId, event.actorId, event.data)\n})\n\nlobby.on('presence:leave', (event) => {\n  console.log(`${event.actorId} left room ${event.roomId}`)\n  removeFromMap(event.roomId, event.actorId)\n})\n\n// Fetch fresh presence at any time\nconst freshPresence = await lobby.fetchPresence()\n\n// Unsubscribe when done\nlobby.unsubscribe()\n",[47,1637,1638,1643,1665,1670,1700,1708,1712,1716,1736,1766,1773,1777,1781,1802,1831,1839,1843,1847,1852,1870,1874,1879],{"__ignoreMap":45},[50,1639,1640],{"class":52,"line":53},[50,1641,1642],{"class":56},"// Listen for presence events (includes room context)\n",[50,1644,1645,1648,1650,1652,1654,1656,1659,1661,1663],{"class":52,"line":60},[50,1646,1647],{"class":224},"lobby.",[50,1649,507],{"class":253},[50,1651,257],{"class":224},[50,1653,512],{"class":231},[50,1655,515],{"class":224},[50,1657,1658],{"class":518},"event",[50,1660,522],{"class":224},[50,1662,416],{"class":220},[50,1664,419],{"class":224},[50,1666,1667],{"class":52,"line":66},[50,1668,1669],{"class":56},"  // event: { lobbyId, roomId, actorId, data }\n",[50,1671,1672,1674,1676,1678,1680,1682,1684,1686,1689,1691,1693,1695,1698],{"class":52,"line":72},[50,1673,532],{"class":224},[50,1675,535],{"class":253},[50,1677,257],{"class":224},[50,1679,540],{"class":231},[50,1681,1658],{"class":224},[50,1683,545],{"class":231},[50,1685,1316],{"class":224},[50,1687,1688],{"class":231},"} joined room ${",[50,1690,1658],{"class":224},[50,1692,545],{"class":231},[50,1694,1281],{"class":224},[50,1696,1697],{"class":231},"}`",[50,1699,263],{"class":224},[50,1701,1702,1705],{"class":52,"line":78},[50,1703,1704],{"class":253},"  addToMap",[50,1706,1707],{"class":224},"(event.roomId, event.actorId, event.data)\n",[50,1709,1710],{"class":52,"line":84},[50,1711,393],{"class":224},[50,1713,1714],{"class":52,"line":89},[50,1715,238],{"emptyLinePlaceholder":237},[50,1717,1718,1720,1722,1724,1726,1728,1730,1732,1734],{"class":52,"line":95},[50,1719,1647],{"class":224},[50,1721,507],{"class":253},[50,1723,257],{"class":224},[50,1725,580],{"class":231},[50,1727,515],{"class":224},[50,1729,1658],{"class":518},[50,1731,522],{"class":224},[50,1733,416],{"class":220},[50,1735,419],{"class":224},[50,1737,1738,1740,1742,1744,1746,1748,1750,1752,1755,1757,1759,1761,1764],{"class":52,"line":100},[50,1739,532],{"class":224},[50,1741,535],{"class":253},[50,1743,257],{"class":224},[50,1745,540],{"class":231},[50,1747,1658],{"class":224},[50,1749,545],{"class":231},[50,1751,1316],{"class":224},[50,1753,1754],{"class":231},"} in room ${",[50,1756,1658],{"class":224},[50,1758,545],{"class":231},[50,1760,1281],{"class":224},[50,1762,1763],{"class":231},"} updated`",[50,1765,263],{"class":224},[50,1767,1768,1771],{"class":52,"line":106},[50,1769,1770],{"class":253},"  updateOnMap",[50,1772,1707],{"class":224},[50,1774,1775],{"class":52,"line":347},[50,1776,393],{"class":224},[50,1778,1779],{"class":52,"line":358},[50,1780,238],{"emptyLinePlaceholder":237},[50,1782,1783,1785,1787,1789,1792,1794,1796,1798,1800],{"class":52,"line":369},[50,1784,1647],{"class":224},[50,1786,507],{"class":253},[50,1788,257],{"class":224},[50,1790,1791],{"class":231},"'presence:leave'",[50,1793,515],{"class":224},[50,1795,1658],{"class":518},[50,1797,522],{"class":224},[50,1799,416],{"class":220},[50,1801,419],{"class":224},[50,1803,1804,1806,1808,1810,1812,1814,1816,1818,1821,1823,1825,1827,1829],{"class":52,"line":390},[50,1805,532],{"class":224},[50,1807,535],{"class":253},[50,1809,257],{"class":224},[50,1811,540],{"class":231},[50,1813,1658],{"class":224},[50,1815,545],{"class":231},[50,1817,1316],{"class":224},[50,1819,1820],{"class":231},"} left room ${",[50,1822,1658],{"class":224},[50,1824,545],{"class":231},[50,1826,1281],{"class":224},[50,1828,1697],{"class":231},[50,1830,263],{"class":224},[50,1832,1833,1836],{"class":52,"line":396},[50,1834,1835],{"class":253},"  removeFromMap",[50,1837,1838],{"class":224},"(event.roomId, event.actorId)\n",[50,1840,1841],{"class":52,"line":401},[50,1842,393],{"class":224},[50,1844,1845],{"class":52,"line":407},[50,1846,238],{"emptyLinePlaceholder":237},[50,1848,1849],{"class":52,"line":422},[50,1850,1851],{"class":56},"// Fetch fresh presence at any time\n",[50,1853,1854,1856,1859,1861,1863,1865,1868],{"class":52,"line":432},[50,1855,243],{"class":220},[50,1857,1858],{"class":246}," freshPresence",[50,1860,250],{"class":220},[50,1862,1156],{"class":220},[50,1864,1159],{"class":224},[50,1866,1867],{"class":253},"fetchPresence",[50,1869,277],{"class":224},[50,1871,1872],{"class":52,"line":442},[50,1873,238],{"emptyLinePlaceholder":237},[50,1875,1876],{"class":52,"line":452},[50,1877,1878],{"class":56},"// Unsubscribe when done\n",[50,1880,1881,1883,1886],{"class":52,"line":462},[50,1882,1647],{"class":224},[50,1884,1885],{"class":253},"unsubscribe",[50,1887,277],{"class":224},[39,1889,1891],{"className":638,"code":1890,"filename":640,"language":641,"meta":45,"style":45},"# Listen for presence events (includes room context)\ndef on_join(event):\n    print(f\"{event.actor_id} joined room {event.room_id}\")\n    add_to_map(event.room_id, event.actor_id, event.data)\n\ndef on_update(event):\n    print(f\"{event.actor_id} in room {event.room_id} updated\")\n    update_on_map(event.room_id, event.actor_id, event.data)\n\ndef on_leave(event):\n    print(f\"{event.actor_id} left room {event.room_id}\")\n    remove_from_map(event.room_id, event.actor_id)\n\nlobby.on('presence:join', on_join)\nlobby.on('presence:update', on_update)\nlobby.on('presence:leave', on_leave)\n\n# Fetch fresh presence at any time\nfresh_presence = await lobby.fetch_presence()\n\n# Unsubscribe when done\nlobby.unsubscribe()\n",[47,1892,1893,1898,1903,1908,1913,1917,1922,1927,1932,1936,1941,1946,1951,1955,1960,1965,1970,1974,1979,1984,1988,1993],{"__ignoreMap":45},[50,1894,1895],{"class":52,"line":53},[50,1896,1897],{},"# Listen for presence events (includes room context)\n",[50,1899,1900],{"class":52,"line":60},[50,1901,1902],{},"def on_join(event):\n",[50,1904,1905],{"class":52,"line":66},[50,1906,1907],{},"    print(f\"{event.actor_id} joined room {event.room_id}\")\n",[50,1909,1910],{"class":52,"line":72},[50,1911,1912],{},"    add_to_map(event.room_id, event.actor_id, event.data)\n",[50,1914,1915],{"class":52,"line":78},[50,1916,238],{"emptyLinePlaceholder":237},[50,1918,1919],{"class":52,"line":84},[50,1920,1921],{},"def on_update(event):\n",[50,1923,1924],{"class":52,"line":89},[50,1925,1926],{},"    print(f\"{event.actor_id} in room {event.room_id} updated\")\n",[50,1928,1929],{"class":52,"line":95},[50,1930,1931],{},"    update_on_map(event.room_id, event.actor_id, event.data)\n",[50,1933,1934],{"class":52,"line":100},[50,1935,238],{"emptyLinePlaceholder":237},[50,1937,1938],{"class":52,"line":106},[50,1939,1940],{},"def on_leave(event):\n",[50,1942,1943],{"class":52,"line":347},[50,1944,1945],{},"    print(f\"{event.actor_id} left room {event.room_id}\")\n",[50,1947,1948],{"class":52,"line":358},[50,1949,1950],{},"    remove_from_map(event.room_id, event.actor_id)\n",[50,1952,1953],{"class":52,"line":369},[50,1954,238],{"emptyLinePlaceholder":237},[50,1956,1957],{"class":52,"line":390},[50,1958,1959],{},"lobby.on('presence:join', on_join)\n",[50,1961,1962],{"class":52,"line":396},[50,1963,1964],{},"lobby.on('presence:update', on_update)\n",[50,1966,1967],{"class":52,"line":401},[50,1968,1969],{},"lobby.on('presence:leave', on_leave)\n",[50,1971,1972],{"class":52,"line":407},[50,1973,238],{"emptyLinePlaceholder":237},[50,1975,1976],{"class":52,"line":422},[50,1977,1978],{},"# Fetch fresh presence at any time\n",[50,1980,1981],{"class":52,"line":432},[50,1982,1983],{},"fresh_presence = await lobby.fetch_presence()\n",[50,1985,1986],{"class":52,"line":442},[50,1987,238],{"emptyLinePlaceholder":237},[50,1989,1990],{"class":52,"line":452},[50,1991,1992],{},"# Unsubscribe when done\n",[50,1994,1995],{"class":52,"line":462},[50,1996,1997],{},"lobby.unsubscribe()\n",[39,1999,2001],{"className":825,"code":2000,"filename":827,"language":828,"meta":45,"style":45},"// Listen for presence events (includes room context)\nlobby.On(\"presence:join\", func(event nolag.LobbyPresenceEvent) {\n    fmt.Printf(\"%s joined room %s\\n\", event.ActorID, event.RoomID)\n    addToMap(event.RoomID, event.ActorID, event.Data)\n})\n\nlobby.On(\"presence:update\", func(event nolag.LobbyPresenceEvent) {\n    fmt.Printf(\"%s in room %s updated\\n\", event.ActorID, event.RoomID)\n    updateOnMap(event.RoomID, event.ActorID, event.Data)\n})\n\nlobby.On(\"presence:leave\", func(event nolag.LobbyPresenceEvent) {\n    fmt.Printf(\"%s left room %s\\n\", event.ActorID, event.RoomID)\n    removeFromMap(event.RoomID, event.ActorID)\n})\n\n// Fetch fresh presence at any time\nfreshPresence, _ := lobby.FetchPresence()\n\n// Unsubscribe when done\nlobby.Unsubscribe()\n",[47,2002,2003,2007,2012,2017,2022,2026,2030,2035,2040,2045,2049,2053,2058,2063,2068,2072,2076,2080,2085,2089,2093],{"__ignoreMap":45},[50,2004,2005],{"class":52,"line":53},[50,2006,1642],{},[50,2008,2009],{"class":52,"line":60},[50,2010,2011],{},"lobby.On(\"presence:join\", func(event nolag.LobbyPresenceEvent) {\n",[50,2013,2014],{"class":52,"line":66},[50,2015,2016],{},"    fmt.Printf(\"%s joined room %s\\n\", event.ActorID, event.RoomID)\n",[50,2018,2019],{"class":52,"line":72},[50,2020,2021],{},"    addToMap(event.RoomID, event.ActorID, event.Data)\n",[50,2023,2024],{"class":52,"line":78},[50,2025,393],{},[50,2027,2028],{"class":52,"line":84},[50,2029,238],{"emptyLinePlaceholder":237},[50,2031,2032],{"class":52,"line":89},[50,2033,2034],{},"lobby.On(\"presence:update\", func(event nolag.LobbyPresenceEvent) {\n",[50,2036,2037],{"class":52,"line":95},[50,2038,2039],{},"    fmt.Printf(\"%s in room %s updated\\n\", event.ActorID, event.RoomID)\n",[50,2041,2042],{"class":52,"line":100},[50,2043,2044],{},"    updateOnMap(event.RoomID, event.ActorID, event.Data)\n",[50,2046,2047],{"class":52,"line":106},[50,2048,393],{},[50,2050,2051],{"class":52,"line":347},[50,2052,238],{"emptyLinePlaceholder":237},[50,2054,2055],{"class":52,"line":358},[50,2056,2057],{},"lobby.On(\"presence:leave\", func(event nolag.LobbyPresenceEvent) {\n",[50,2059,2060],{"class":52,"line":369},[50,2061,2062],{},"    fmt.Printf(\"%s left room %s\\n\", event.ActorID, event.RoomID)\n",[50,2064,2065],{"class":52,"line":390},[50,2066,2067],{},"    removeFromMap(event.RoomID, event.ActorID)\n",[50,2069,2070],{"class":52,"line":396},[50,2071,393],{},[50,2073,2074],{"class":52,"line":401},[50,2075,238],{"emptyLinePlaceholder":237},[50,2077,2078],{"class":52,"line":407},[50,2079,1851],{},[50,2081,2082],{"class":52,"line":422},[50,2083,2084],{},"freshPresence, _ := lobby.FetchPresence()\n",[50,2086,2087],{"class":52,"line":432},[50,2088,238],{"emptyLinePlaceholder":237},[50,2090,2091],{"class":52,"line":442},[50,2092,1878],{},[50,2094,2095],{"class":52,"line":452},[50,2096,2097],{},"lobby.Unsubscribe()\n",[18,2099,2101],{"id":2100},"lobby-presence-event-structure","Lobby Presence Event Structure",[36,2103,2104],{},[39,2105,2107],{"className":41,"code":2106,"filename":43,"language":44,"meta":45,"style":45},"interface LobbyPresenceEvent {\n  lobbyId: string    // The lobby this event is from\n  roomId: string     // Which room the actor is in\n  actorId: string    // The actor's token ID\n  data: {            // The actor's presence data\n    role?: string\n    name?: string\n    location?: { lat: number, lng: number }\n    // ... any custom fields\n  }\n}\n",[47,2108,2109,2119,2133,2145,2157,2170,2181,2190,2219,2224,2228],{"__ignoreMap":45},[50,2110,2111,2114,2117],{"class":52,"line":53},[50,2112,2113],{"class":220},"interface",[50,2115,2116],{"class":253}," LobbyPresenceEvent",[50,2118,419],{"class":224},[50,2120,2121,2124,2127,2130],{"class":52,"line":60},[50,2122,2123],{"class":518},"  lobbyId",[50,2125,2126],{"class":220},":",[50,2128,2129],{"class":246}," string",[50,2131,2132],{"class":56},"    // The lobby this event is from\n",[50,2134,2135,2138,2140,2142],{"class":52,"line":66},[50,2136,2137],{"class":518},"  roomId",[50,2139,2126],{"class":220},[50,2141,2129],{"class":246},[50,2143,2144],{"class":56},"     // Which room the actor is in\n",[50,2146,2147,2150,2152,2154],{"class":52,"line":72},[50,2148,2149],{"class":518},"  actorId",[50,2151,2126],{"class":220},[50,2153,2129],{"class":246},[50,2155,2156],{"class":56},"    // The actor's token ID\n",[50,2158,2159,2162,2164,2167],{"class":52,"line":78},[50,2160,2161],{"class":518},"  data",[50,2163,2126],{"class":220},[50,2165,2166],{"class":224}," {            ",[50,2168,2169],{"class":56},"// The actor's presence data\n",[50,2171,2172,2175,2178],{"class":52,"line":84},[50,2173,2174],{"class":518},"    role",[50,2176,2177],{"class":220},"?:",[50,2179,2180],{"class":246}," string\n",[50,2182,2183,2186,2188],{"class":52,"line":89},[50,2184,2185],{"class":518},"    name",[50,2187,2177],{"class":220},[50,2189,2180],{"class":246},[50,2191,2192,2195,2197,2200,2203,2205,2208,2210,2213,2215,2217],{"class":52,"line":95},[50,2193,2194],{"class":518},"    location",[50,2196,2177],{"class":220},[50,2198,2199],{"class":224}," { ",[50,2201,2202],{"class":518},"lat",[50,2204,2126],{"class":220},[50,2206,2207],{"class":246}," number",[50,2209,1284],{"class":224},[50,2211,2212],{"class":518},"lng",[50,2214,2126],{"class":220},[50,2216,2207],{"class":246},[50,2218,387],{"class":224},[50,2220,2221],{"class":52,"line":100},[50,2222,2223],{"class":56},"    // ... any custom fields\n",[50,2225,2226],{"class":52,"line":106},[50,2227,630],{"class":224},[50,2229,2230],{"class":52,"line":347},[50,2231,1042],{"class":224},[18,2233,2235],{"id":2234},"full-dashboard-example","Full Dashboard Example",[14,2237,2238],{},"Here's a complete example of a trip monitoring dashboard:",[36,2240,2241],{},[39,2242,2244],{"className":41,"code":2243,"filename":43,"language":44,"meta":45,"style":45},"import { NoLag, LobbyPresenceEvent, LobbyPresenceState } from '@nolag/js-sdk'\n\n// Dashboard that shows all active trips on a map\nclass TripDashboard {\n  private client: NoLag\n  private presence: Map\u003Cstring, Map\u003Cstring, any>> = new Map()\n\n  async connect() {\n    this.client = NoLag('dashboard_token')\n    await this.client.connect()\n\n    const lobby = this.client.setApp('rides').setLobby('active-trips')\n\n    // Get initial snapshot\n    const snapshot = await lobby.subscribe()\n    this.initializeFromSnapshot(snapshot)\n\n    // Listen for live updates\n    lobby.on('presence:join', (e) => this.handleJoin(e))\n    lobby.on('presence:update', (e) => this.handleUpdate(e))\n    lobby.on('presence:leave', (e) => this.handleLeave(e))\n  }\n\n  private initializeFromSnapshot(snapshot: LobbyPresenceState) {\n    for (const [roomId, actors] of Object.entries(snapshot)) {\n      const roomMap = new Map()\n      for (const [actorId, data] of Object.entries(actors)) {\n        roomMap.set(actorId, data)\n        this.addMarkerToMap(roomId, actorId, data)\n      }\n      this.presence.set(roomId, roomMap)\n    }\n  }\n\n  private handleJoin(event: LobbyPresenceEvent) {\n    if (!this.presence.has(event.roomId)) {\n      this.presence.set(event.roomId, new Map())\n    }\n    this.presence.get(event.roomId)!.set(event.actorId, event.data)\n    this.addMarkerToMap(event.roomId, event.actorId, event.data)\n  }\n\n  private handleUpdate(event: LobbyPresenceEvent) {\n    this.presence.get(event.roomId)?.set(event.actorId, event.data)\n    this.updateMarkerOnMap(event.roomId, event.actorId, event.data)\n  }\n\n  private handleLeave(event: LobbyPresenceEvent) {\n    this.presence.get(event.roomId)?.delete(event.actorId)\n    this.removeMarkerFromMap(event.roomId, event.actorId)\n  }\n\n  // Map rendering methods...\n  private addMarkerToMap(roomId: string, actorId: string, data: any) { /* ... */ }\n  private updateMarkerOnMap(roomId: string, actorId: string, data: any) { /* ... */ }\n  private removeMarkerFromMap(roomId: string, actorId: string) { /* ... */ }\n}\n",[47,2245,2246,2257,2261,2266,2276,2288,2331,2335,2346,2364,2379,2383,2412,2416,2421,2437,2449,2453,2458,2488,2515,2542,2546,2550,2569,2596,2612,2639,2650,2662,2667,2680,2684,2688,2692,2709,2730,2749,2753,2774,2784,2788,2792,2809,2825,2837,2842,2847,2865,2882,2894,2899,2904,2910,2951,2989,3019],{"__ignoreMap":45},[50,2247,2248,2250,2253,2255],{"class":52,"line":53},[50,2249,221],{"class":220},[50,2251,2252],{"class":224}," { NoLag, LobbyPresenceEvent, LobbyPresenceState } ",[50,2254,228],{"class":220},[50,2256,232],{"class":231},[50,2258,2259],{"class":52,"line":60},[50,2260,238],{"emptyLinePlaceholder":237},[50,2262,2263],{"class":52,"line":66},[50,2264,2265],{"class":56},"// Dashboard that shows all active trips on a map\n",[50,2267,2268,2271,2274],{"class":52,"line":72},[50,2269,2270],{"class":220},"class",[50,2272,2273],{"class":253}," TripDashboard",[50,2275,419],{"class":224},[50,2277,2278,2281,2283,2285],{"class":52,"line":78},[50,2279,2280],{"class":220},"  private",[50,2282,247],{"class":518},[50,2284,2126],{"class":220},[50,2286,2287],{"class":253}," NoLag\n",[50,2289,2290,2292,2295,2297,2299,2302,2305,2307,2310,2312,2314,2316,2319,2322,2325,2327,2329],{"class":52,"line":84},[50,2291,2280],{"class":220},[50,2293,2294],{"class":518}," presence",[50,2296,2126],{"class":220},[50,2298,1263],{"class":253},[50,2300,2301],{"class":224},"\u003C",[50,2303,2304],{"class":246},"string",[50,2306,1284],{"class":224},[50,2308,2309],{"class":253},"Map",[50,2311,2301],{"class":224},[50,2313,2304],{"class":246},[50,2315,1284],{"class":224},[50,2317,2318],{"class":246},"any",[50,2320,2321],{"class":224},">> ",[50,2323,2324],{"class":220},"=",[50,2326,1260],{"class":220},[50,2328,1263],{"class":253},[50,2330,277],{"class":224},[50,2332,2333],{"class":52,"line":89},[50,2334,238],{"emptyLinePlaceholder":237},[50,2336,2337,2340,2343],{"class":52,"line":95},[50,2338,2339],{"class":220},"  async",[50,2341,2342],{"class":253}," connect",[50,2344,2345],{"class":224},"() {\n",[50,2347,2348,2351,2354,2356,2358,2360,2362],{"class":52,"line":100},[50,2349,2350],{"class":246},"    this",[50,2352,2353],{"class":224},".client ",[50,2355,2324],{"class":220},[50,2357,254],{"class":253},[50,2359,257],{"class":224},[50,2361,1085],{"class":231},[50,2363,263],{"class":224},[50,2365,2366,2369,2372,2375,2377],{"class":52,"line":106},[50,2367,2368],{"class":220},"    await",[50,2370,2371],{"class":246}," this",[50,2373,2374],{"class":224},".client.",[50,2376,274],{"class":253},[50,2378,277],{"class":224},[50,2380,2381],{"class":52,"line":347},[50,2382,238],{"emptyLinePlaceholder":237},[50,2384,2385,2388,2390,2392,2394,2396,2398,2400,2402,2404,2406,2408,2410],{"class":52,"line":358},[50,2386,2387],{"class":220},"    const",[50,2389,1113],{"class":246},[50,2391,250],{"class":220},[50,2393,2371],{"class":246},[50,2395,2374],{"class":224},[50,2397,300],{"class":253},[50,2399,257],{"class":224},[50,2401,305],{"class":231},[50,2403,308],{"class":224},[50,2405,1128],{"class":253},[50,2407,257],{"class":224},[50,2409,1133],{"class":231},[50,2411,263],{"class":224},[50,2413,2414],{"class":52,"line":369},[50,2415,238],{"emptyLinePlaceholder":237},[50,2417,2418],{"class":52,"line":390},[50,2419,2420],{"class":56},"    // Get initial snapshot\n",[50,2422,2423,2425,2427,2429,2431,2433,2435],{"class":52,"line":396},[50,2424,2387],{"class":220},[50,2426,1151],{"class":246},[50,2428,250],{"class":220},[50,2430,1156],{"class":220},[50,2432,1159],{"class":224},[50,2434,1162],{"class":253},[50,2436,277],{"class":224},[50,2438,2439,2441,2443,2446],{"class":52,"line":401},[50,2440,2350],{"class":246},[50,2442,545],{"class":224},[50,2444,2445],{"class":253},"initializeFromSnapshot",[50,2447,2448],{"class":224},"(snapshot)\n",[50,2450,2451],{"class":52,"line":407},[50,2452,238],{"emptyLinePlaceholder":237},[50,2454,2455],{"class":52,"line":422},[50,2456,2457],{"class":56},"    // Listen for live updates\n",[50,2459,2460,2463,2465,2467,2469,2471,2474,2476,2478,2480,2482,2485],{"class":52,"line":432},[50,2461,2462],{"class":224},"    lobby.",[50,2464,507],{"class":253},[50,2466,257],{"class":224},[50,2468,512],{"class":231},[50,2470,515],{"class":224},[50,2472,2473],{"class":518},"e",[50,2475,522],{"class":224},[50,2477,416],{"class":220},[50,2479,2371],{"class":246},[50,2481,545],{"class":224},[50,2483,2484],{"class":253},"handleJoin",[50,2486,2487],{"class":224},"(e))\n",[50,2489,2490,2492,2494,2496,2498,2500,2502,2504,2506,2508,2510,2513],{"class":52,"line":442},[50,2491,2462],{"class":224},[50,2493,507],{"class":253},[50,2495,257],{"class":224},[50,2497,580],{"class":231},[50,2499,515],{"class":224},[50,2501,2473],{"class":518},[50,2503,522],{"class":224},[50,2505,416],{"class":220},[50,2507,2371],{"class":246},[50,2509,545],{"class":224},[50,2511,2512],{"class":253},"handleUpdate",[50,2514,2487],{"class":224},[50,2516,2517,2519,2521,2523,2525,2527,2529,2531,2533,2535,2537,2540],{"class":52,"line":452},[50,2518,2462],{"class":224},[50,2520,507],{"class":253},[50,2522,257],{"class":224},[50,2524,1791],{"class":231},[50,2526,515],{"class":224},[50,2528,2473],{"class":518},[50,2530,522],{"class":224},[50,2532,416],{"class":220},[50,2534,2371],{"class":246},[50,2536,545],{"class":224},[50,2538,2539],{"class":253},"handleLeave",[50,2541,2487],{"class":224},[50,2543,2544],{"class":52,"line":462},[50,2545,630],{"class":224},[50,2547,2548],{"class":52,"line":473},[50,2549,238],{"emptyLinePlaceholder":237},[50,2551,2552,2554,2557,2559,2562,2564,2567],{"class":52,"line":479},[50,2553,2280],{"class":220},[50,2555,2556],{"class":253}," initializeFromSnapshot",[50,2558,257],{"class":224},[50,2560,2561],{"class":518},"snapshot",[50,2563,2126],{"class":220},[50,2565,2566],{"class":253}," LobbyPresenceState",[50,2568,608],{"class":224},[50,2570,2571,2574,2576,2578,2580,2582,2584,2586,2588,2590,2592,2594],{"class":52,"line":490},[50,2572,2573],{"class":220},"    for",[50,2575,1273],{"class":224},[50,2577,243],{"class":220},[50,2579,1278],{"class":224},[50,2581,1281],{"class":246},[50,2583,1284],{"class":224},[50,2585,1287],{"class":246},[50,2587,1290],{"class":224},[50,2589,1293],{"class":220},[50,2591,1296],{"class":224},[50,2593,1299],{"class":253},[50,2595,1302],{"class":224},[50,2597,2598,2601,2604,2606,2608,2610],{"class":52,"line":495},[50,2599,2600],{"class":220},"      const",[50,2602,2603],{"class":246}," roomMap",[50,2605,250],{"class":220},[50,2607,1260],{"class":220},[50,2609,1263],{"class":253},[50,2611,277],{"class":224},[50,2613,2614,2617,2619,2621,2623,2625,2627,2629,2631,2633,2635,2637],{"class":52,"line":501},[50,2615,2616],{"class":220},"      for",[50,2618,1273],{"class":224},[50,2620,243],{"class":220},[50,2622,1278],{"class":224},[50,2624,1316],{"class":246},[50,2626,1284],{"class":224},[50,2628,1321],{"class":246},[50,2630,1290],{"class":224},[50,2632,1293],{"class":220},[50,2634,1296],{"class":224},[50,2636,1299],{"class":253},[50,2638,1332],{"class":224},[50,2640,2641,2644,2647],{"class":52,"line":529},[50,2642,2643],{"class":224},"        roomMap.",[50,2645,2646],{"class":253},"set",[50,2648,2649],{"class":224},"(actorId, data)\n",[50,2651,2652,2655,2657,2660],{"class":52,"line":561},[50,2653,2654],{"class":246},"        this",[50,2656,545],{"class":224},[50,2658,2659],{"class":253},"addMarkerToMap",[50,2661,1340],{"class":224},[50,2663,2664],{"class":52,"line":566},[50,2665,2666],{"class":224},"      }\n",[50,2668,2669,2672,2675,2677],{"class":52,"line":571},[50,2670,2671],{"class":246},"      this",[50,2673,2674],{"class":224},".presence.",[50,2676,2646],{"class":253},[50,2678,2679],{"class":224},"(roomId, roomMap)\n",[50,2681,2682],{"class":52,"line":593},[50,2683,1579],{"class":224},[50,2685,2686],{"class":52,"line":611},[50,2687,630],{"class":224},[50,2689,2690],{"class":52,"line":627},[50,2691,238],{"emptyLinePlaceholder":237},[50,2693,2694,2696,2699,2701,2703,2705,2707],{"class":52,"line":633},[50,2695,2280],{"class":220},[50,2697,2698],{"class":253}," handleJoin",[50,2700,257],{"class":224},[50,2702,1658],{"class":518},[50,2704,2126],{"class":220},[50,2706,2116],{"class":253},[50,2708,608],{"class":224},[50,2710,2711,2714,2716,2719,2722,2724,2727],{"class":52,"line":813},[50,2712,2713],{"class":220},"    if",[50,2715,1273],{"class":224},[50,2717,2718],{"class":220},"!",[50,2720,2721],{"class":246},"this",[50,2723,2674],{"class":224},[50,2725,2726],{"class":253},"has",[50,2728,2729],{"class":224},"(event.roomId)) {\n",[50,2731,2732,2734,2736,2738,2741,2744,2746],{"class":52,"line":819},[50,2733,2671],{"class":246},[50,2735,2674],{"class":224},[50,2737,2646],{"class":253},[50,2739,2740],{"class":224},"(event.roomId, ",[50,2742,2743],{"class":220},"new",[50,2745,1263],{"class":253},[50,2747,2748],{"class":224},"())\n",[50,2750,2751],{"class":52,"line":1010},[50,2752,1579],{"class":224},[50,2754,2755,2757,2759,2762,2765,2767,2769,2771],{"class":52,"line":1016},[50,2756,2350],{"class":246},[50,2758,2674],{"class":224},[50,2760,2761],{"class":253},"get",[50,2763,2764],{"class":224},"(event.roomId)",[50,2766,2718],{"class":220},[50,2768,545],{"class":224},[50,2770,2646],{"class":253},[50,2772,2773],{"class":224},"(event.actorId, event.data)\n",[50,2775,2776,2778,2780,2782],{"class":52,"line":1022},[50,2777,2350],{"class":246},[50,2779,545],{"class":224},[50,2781,2659],{"class":253},[50,2783,1707],{"class":224},[50,2785,2786],{"class":52,"line":1028},[50,2787,630],{"class":224},[50,2789,2790],{"class":52,"line":1034},[50,2791,238],{"emptyLinePlaceholder":237},[50,2793,2794,2796,2799,2801,2803,2805,2807],{"class":52,"line":1039},[50,2795,2280],{"class":220},[50,2797,2798],{"class":253}," handleUpdate",[50,2800,257],{"class":224},[50,2802,1658],{"class":518},[50,2804,2126],{"class":220},[50,2806,2116],{"class":253},[50,2808,608],{"class":224},[50,2810,2812,2814,2816,2818,2821,2823],{"class":52,"line":2811},44,[50,2813,2350],{"class":246},[50,2815,2674],{"class":224},[50,2817,2761],{"class":253},[50,2819,2820],{"class":224},"(event.roomId)?.",[50,2822,2646],{"class":253},[50,2824,2773],{"class":224},[50,2826,2828,2830,2832,2835],{"class":52,"line":2827},45,[50,2829,2350],{"class":246},[50,2831,545],{"class":224},[50,2833,2834],{"class":253},"updateMarkerOnMap",[50,2836,1707],{"class":224},[50,2838,2840],{"class":52,"line":2839},46,[50,2841,630],{"class":224},[50,2843,2845],{"class":52,"line":2844},47,[50,2846,238],{"emptyLinePlaceholder":237},[50,2848,2850,2852,2855,2857,2859,2861,2863],{"class":52,"line":2849},48,[50,2851,2280],{"class":220},[50,2853,2854],{"class":253}," handleLeave",[50,2856,257],{"class":224},[50,2858,1658],{"class":518},[50,2860,2126],{"class":220},[50,2862,2116],{"class":253},[50,2864,608],{"class":224},[50,2866,2868,2870,2872,2874,2876,2879],{"class":52,"line":2867},49,[50,2869,2350],{"class":246},[50,2871,2674],{"class":224},[50,2873,2761],{"class":253},[50,2875,2820],{"class":224},[50,2877,2878],{"class":253},"delete",[50,2880,2881],{"class":224},"(event.actorId)\n",[50,2883,2885,2887,2889,2892],{"class":52,"line":2884},50,[50,2886,2350],{"class":246},[50,2888,545],{"class":224},[50,2890,2891],{"class":253},"removeMarkerFromMap",[50,2893,1838],{"class":224},[50,2895,2897],{"class":52,"line":2896},51,[50,2898,630],{"class":224},[50,2900,2902],{"class":52,"line":2901},52,[50,2903,238],{"emptyLinePlaceholder":237},[50,2905,2907],{"class":52,"line":2906},53,[50,2908,2909],{"class":56},"  // Map rendering methods...\n",[50,2911,2913,2915,2918,2920,2922,2924,2926,2928,2930,2932,2934,2936,2938,2940,2943,2946,2949],{"class":52,"line":2912},54,[50,2914,2280],{"class":220},[50,2916,2917],{"class":253}," addMarkerToMap",[50,2919,257],{"class":224},[50,2921,1281],{"class":518},[50,2923,2126],{"class":220},[50,2925,2129],{"class":246},[50,2927,1284],{"class":224},[50,2929,1316],{"class":518},[50,2931,2126],{"class":220},[50,2933,2129],{"class":246},[50,2935,1284],{"class":224},[50,2937,1321],{"class":518},[50,2939,2126],{"class":220},[50,2941,2942],{"class":246}," any",[50,2944,2945],{"class":224},") { ",[50,2947,2948],{"class":56},"/* ... */",[50,2950,387],{"class":224},[50,2952,2954,2956,2959,2961,2963,2965,2967,2969,2971,2973,2975,2977,2979,2981,2983,2985,2987],{"class":52,"line":2953},55,[50,2955,2280],{"class":220},[50,2957,2958],{"class":253}," updateMarkerOnMap",[50,2960,257],{"class":224},[50,2962,1281],{"class":518},[50,2964,2126],{"class":220},[50,2966,2129],{"class":246},[50,2968,1284],{"class":224},[50,2970,1316],{"class":518},[50,2972,2126],{"class":220},[50,2974,2129],{"class":246},[50,2976,1284],{"class":224},[50,2978,1321],{"class":518},[50,2980,2126],{"class":220},[50,2982,2942],{"class":246},[50,2984,2945],{"class":224},[50,2986,2948],{"class":56},[50,2988,387],{"class":224},[50,2990,2992,2994,2997,2999,3001,3003,3005,3007,3009,3011,3013,3015,3017],{"class":52,"line":2991},56,[50,2993,2280],{"class":220},[50,2995,2996],{"class":253}," removeMarkerFromMap",[50,2998,257],{"class":224},[50,3000,1281],{"class":518},[50,3002,2126],{"class":220},[50,3004,2129],{"class":246},[50,3006,1284],{"class":224},[50,3008,1316],{"class":518},[50,3010,2126],{"class":220},[50,3012,2129],{"class":246},[50,3014,2945],{"class":224},[50,3016,2948],{"class":56},[50,3018,387],{"class":224},[50,3020,3022],{"class":52,"line":3021},57,[50,3023,1042],{"class":224},[18,3025,3027],{"id":3026},"managing-lobbies-rest-api","Managing Lobbies (REST API)",[14,3029,3030],{},"Lobbies are configured via the REST API. Typically, your backend adds rooms to lobbies when sessions start:",[36,3032,3033],{},[39,3034,3039],{"className":3035,"code":3036,"filename":3037,"language":3038,"meta":45,"style":45},"language-bash shiki shiki-themes github-light github-dark","# Create a lobby\nPOST /v1/organizations/:orgId/projects/:projId/apps/:appId/lobbies\n{\n  \"name\": \"Active Trips\",\n  \"slug\": \"active-trips\",\n  \"description\": \"All currently active trip rooms\"\n}\n\n# Add a room to the lobby (when trip starts)\nPOST /v1/.../lobbies/:lobbyId/rooms\n{\n  \"roomId\": \"trip-123-uuid\"\n}\n\n# Remove room from lobby (when trip ends)\nDELETE /v1/.../lobbies/:lobbyId/rooms/:roomId\n\n# List all rooms in a lobby\nGET /v1/.../lobbies/:lobbyId/rooms\n","REST API","bash",[47,3040,3041,3046,3054,3059,3069,3079,3089,3093,3097,3102,3109,3113,3123,3127,3131,3136,3144,3148,3153],{"__ignoreMap":45},[50,3042,3043],{"class":52,"line":53},[50,3044,3045],{"class":56},"# Create a lobby\n",[50,3047,3048,3051],{"class":52,"line":60},[50,3049,3050],{"class":253},"POST",[50,3052,3053],{"class":231}," /v1/organizations/:orgId/projects/:projId/apps/:appId/lobbies\n",[50,3055,3056],{"class":52,"line":66},[50,3057,3058],{"class":224},"{\n",[50,3060,3061,3064,3066],{"class":52,"line":72},[50,3062,3063],{"class":253},"  \"name\"",[50,3065,2126],{"class":246},[50,3067,3068],{"class":231}," \"Active Trips\",\n",[50,3070,3071,3074,3076],{"class":52,"line":78},[50,3072,3073],{"class":253},"  \"slug\"",[50,3075,2126],{"class":246},[50,3077,3078],{"class":231}," \"active-trips\",\n",[50,3080,3081,3084,3086],{"class":52,"line":84},[50,3082,3083],{"class":253},"  \"description\"",[50,3085,2126],{"class":246},[50,3087,3088],{"class":231}," \"All currently active trip rooms\"\n",[50,3090,3091],{"class":52,"line":89},[50,3092,1042],{"class":224},[50,3094,3095],{"class":52,"line":95},[50,3096,238],{"emptyLinePlaceholder":237},[50,3098,3099],{"class":52,"line":100},[50,3100,3101],{"class":56},"# Add a room to the lobby (when trip starts)\n",[50,3103,3104,3106],{"class":52,"line":106},[50,3105,3050],{"class":253},[50,3107,3108],{"class":231}," /v1/.../lobbies/:lobbyId/rooms\n",[50,3110,3111],{"class":52,"line":347},[50,3112,3058],{"class":224},[50,3114,3115,3118,3120],{"class":52,"line":358},[50,3116,3117],{"class":253},"  \"roomId\"",[50,3119,2126],{"class":246},[50,3121,3122],{"class":231}," \"trip-123-uuid\"\n",[50,3124,3125],{"class":52,"line":369},[50,3126,1042],{"class":224},[50,3128,3129],{"class":52,"line":390},[50,3130,238],{"emptyLinePlaceholder":237},[50,3132,3133],{"class":52,"line":396},[50,3134,3135],{"class":56},"# Remove room from lobby (when trip ends)\n",[50,3137,3138,3141],{"class":52,"line":401},[50,3139,3140],{"class":253},"DELETE",[50,3142,3143],{"class":231}," /v1/.../lobbies/:lobbyId/rooms/:roomId\n",[50,3145,3146],{"class":52,"line":407},[50,3147,238],{"emptyLinePlaceholder":237},[50,3149,3150],{"class":52,"line":422},[50,3151,3152],{"class":56},"# List all rooms in a lobby\n",[50,3154,3155,3158],{"class":52,"line":432},[50,3156,3157],{"class":253},"GET",[50,3159,3108],{"class":231},[18,3161,3163],{"id":3162},"access-control","Access Control",[14,3165,3166],{},"Lobby subscriptions are controlled by ACL. Typically, only admin/server actors should have permission to subscribe to lobbies:",[36,3168,3169],{},[39,3170,3172],{"className":41,"code":3171,"filename":43,"language":44,"meta":45,"style":45},"// Actor token with lobby permissions\n{\n  actorType: \"server\",\n  permissions: {\n    lobbies: {\n      \"active-trips\": [\"subscribe\"],\n      \"admin-lobby\": [\"subscribe\"]\n    }\n  }\n}\n",[47,3173,3174,3179,3183,3196,3204,3211,3225,3237,3241,3245],{"__ignoreMap":45},[50,3175,3176],{"class":52,"line":53},[50,3177,3178],{"class":56},"// Actor token with lobby permissions\n",[50,3180,3181],{"class":52,"line":60},[50,3182,3058],{"class":224},[50,3184,3185,3188,3191,3194],{"class":52,"line":66},[50,3186,3187],{"class":253},"  actorType",[50,3189,3190],{"class":224},": ",[50,3192,3193],{"class":231},"\"server\"",[50,3195,344],{"class":224},[50,3197,3198,3201],{"class":52,"line":72},[50,3199,3200],{"class":253},"  permissions",[50,3202,3203],{"class":224},": {\n",[50,3205,3206,3209],{"class":52,"line":78},[50,3207,3208],{"class":253},"    lobbies",[50,3210,3203],{"class":224},[50,3212,3213,3216,3219,3222],{"class":52,"line":84},[50,3214,3215],{"class":231},"      \"active-trips\"",[50,3217,3218],{"class":224},": [",[50,3220,3221],{"class":231},"\"subscribe\"",[50,3223,3224],{"class":224},"],\n",[50,3226,3227,3230,3232,3234],{"class":52,"line":89},[50,3228,3229],{"class":231},"      \"admin-lobby\"",[50,3231,3218],{"class":224},[50,3233,3221],{"class":231},[50,3235,3236],{"class":224},"]\n",[50,3238,3239],{"class":52,"line":95},[50,3240,1579],{"class":224},[50,3242,3243],{"class":52,"line":100},[50,3244,630],{"class":224},[50,3246,3247],{"class":52,"line":106},[50,3248,1042],{"class":224},[18,3250,3252],{"id":3251},"best-practices","Best Practices",[125,3254,3255,3261,3267,3273,3279],{},[128,3256,3257,3260],{},[26,3258,3259],{},"Use lobbies for dashboards, not clients"," - Regular users should use room presence; lobbies are for admin/monitoring",[128,3262,3263,3266],{},[26,3264,3265],{},"Keep presence data small"," - Lobby events fan out to all subscribers",[128,3268,3269,3272],{},[26,3270,3271],{},"Add rooms to lobbies on session start"," - Remove them when sessions end",[128,3274,3275,3278],{},[26,3276,3277],{},"Use the 10-lobby limit wisely"," - Group rooms into meaningful categories",[128,3280,3281,3284],{},[26,3282,3283],{},"Handle the initial snapshot"," - Don't rely only on live events; process the snapshot first",[18,3286,3288],{"id":3287},"room-vs-lobby-presence","Room vs Lobby Presence",[3290,3291,3292,3308],"table",{},[3293,3294,3295],"thead",{},[3296,3297,3298,3302,3305],"tr",{},[3299,3300,3301],"th",{},"Feature",[3299,3303,3304],{},"Room Presence",[3299,3306,3307],{},"Lobby Presence",[3309,3310,3311,3323,3334,3344,3355],"tbody",{},[3296,3312,3313,3317,3320],{},[3314,3315,3316],"td",{},"Scope",[3314,3318,3319],{},"Single room",[3314,3321,3322],{},"Multiple rooms",[3296,3324,3325,3328,3331],{},[3314,3326,3327],{},"Can set presence",[3314,3329,3330],{},"Yes",[3314,3332,3333],{},"No (read-only)",[3296,3335,3336,3339,3342],{},[3314,3337,3338],{},"Events include roomId",[3314,3340,3341],{},"No (implicit)",[3314,3343,3330],{},[3296,3345,3346,3349,3352],{},[3314,3347,3348],{},"Use case",[3314,3350,3351],{},"Participants in a session",[3314,3353,3354],{},"Dashboards, monitoring",[3296,3356,3357,3360,3363],{},[3314,3358,3359],{},"ACL",[3314,3361,3362],{},"Room-level permissions",[3314,3364,3365],{},"Lobby-level permissions",[18,3367,3369],{"id":3368},"next-steps","Next Steps",[125,3371,3372,3379,3385,3391],{},[128,3373,3374],{},[3375,3376,3378],"a",{"href":3377},"/docs/concepts/presence","Learn about Room Presence",[128,3380,3381],{},[3375,3382,3384],{"href":3383},"/docs/concepts/rooms","Understanding Rooms",[128,3386,3387],{},[3375,3388,3390],{"href":3389},"/docs/guides/dashboards","Build a Live Dashboard",[128,3392,3393],{},[3375,3394,3396],{"href":3395},"/docs/concepts/acl","Access Control Lists",[3398,3399,3400],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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);}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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":45,"searchDepth":60,"depth":60,"links":3402},[3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415],{"id":20,"depth":60,"text":21},{"id":122,"depth":60,"text":123},{"id":160,"depth":60,"text":161},{"id":204,"depth":60,"text":205},{"id":1045,"depth":60,"text":1046},{"id":1623,"depth":60,"text":1624},{"id":2100,"depth":60,"text":2101},{"id":2234,"depth":60,"text":2235},{"id":3026,"depth":60,"text":3027},{"id":3162,"depth":60,"text":3163},{"id":3251,"depth":60,"text":3252},{"id":3287,"depth":60,"text":3288},{"id":3368,"depth":60,"text":3369},"Learn how to use Lobbies in NoLag to observe presence across multiple rooms. Build dashboards that monitor all active sessions in real-time.","md",{},"/docs/concepts/lobbies",{"title":5,"description":3416},"docs/concepts/lobbies","OF2sZjHjyQvmAUeCF-fpwn4coTmmWlijFWm-6_z-Hns",1788160343013]