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