[{"data":1,"prerenderedAt":2495},["ShallowReactive",2],{"docs:/docs/getting-started":3},{"id":4,"title":5,"body":6,"description":2488,"extension":2489,"meta":2490,"navigation":228,"path":2491,"seo":2492,"stem":2493,"__hash__":2494},"docs/docs/getting-started.md","Getting Started",{"type":7,"value":8,"toc":2477},"minimark",[9,13,17,22,40,43,47,50,111,115,118,142,145,150,178,197,672,682,706,730,738,742,763,766,1185,1189,1192,1195,1393,1397,1403,1625,1629,1632,2401,2405,2424,2436,2443,2447,2473],[10,11,5],"h1",{"id":12},"getting-started",[14,15,16],"p",{},"Get up and running with NoLag in under 5 minutes.",[18,19,21],"h2",{"id":20},"prerequisites","Prerequisites",[23,24,25,37],"ul",{},[26,27,28,29,36],"li",{},"A NoLag account (",[30,31,35],"a",{"href":32,"rel":33},"https://portal.nolag.app",[34],"nofollow","sign up free",")",[26,38,39],{},"Node.js 18+ (for the JavaScript SDK)",[14,41,42],{},"You create your app and access tokens in Step 2, so nothing else is needed up front.",[18,44,46],{"id":45},"step-1-install-the-sdk","Step 1: Install the SDK",[14,48,49],{},"Install the NoLag SDK for your preferred language:",[51,52,53,79,94],"code-tabs",{},[54,55,61],"pre",{"className":56,"code":57,"filename":58,"language":59,"meta":60,"style":60},"language-bash shiki shiki-themes github-light github-dark","npm install @nolag/js-sdk\n","npm","bash","",[62,63,64],"code",{"__ignoreMap":60},[65,66,69,72,76],"span",{"class":67,"line":68},"line",1,[65,70,58],{"class":71},"sScJk",[65,73,75],{"class":74},"sZZnC"," install",[65,77,78],{"class":74}," @nolag/js-sdk\n",[54,80,83],{"className":56,"code":81,"filename":82,"language":59,"meta":60,"style":60},"pip install nolag\n","pip",[62,84,85],{"__ignoreMap":60},[65,86,87,89,91],{"class":67,"line":68},[65,88,82],{"class":71},[65,90,75],{"class":74},[65,92,93],{"class":74}," nolag\n",[54,95,98],{"className":56,"code":96,"filename":97,"language":59,"meta":60,"style":60},"go get github.com/NoLagApp/go-sdk\n","go get",[62,99,100],{"__ignoreMap":60},[65,101,102,105,108],{"class":67,"line":68},[65,103,104],{"class":71},"go",[65,106,107],{"class":74}," get",[65,109,110],{"class":74}," github.com/NoLagApp/go-sdk\n",[18,112,114],{"id":113},"step-2-create-an-app-a-room-and-two-access-tokens","Step 2: Create an App, a Room, and Two Access Tokens",[14,116,117],{},"You need three kinds of thing:",[23,119,120,128,135],{},[26,121,122,123,127],{},"an ",[124,125,126],"strong",{},"app",", a container for your rooms, carrying the list of topics it allows",[26,129,130,131,134],{},"a ",[124,132,133],{},"room"," inside that app, the namespace your topics live in",[26,136,137,138,141],{},"two ",[124,139,140],{},"actors",", client identities whose access tokens authenticate the connections",[14,143,144],{},"Why two actors? A publishing actor never receives its own message, so one token\nthat subscribes and then publishes hears nothing. This guide uses one actor to\npublish and another to subscribe.",[14,146,147],{},[124,148,149],{},"In the dashboard:",[151,152,153,161,168,171],"ol",{},[26,154,155,156,160],{},"Log in to the ",[30,157,159],{"href":32,"rel":158},[34],"NoLag Dashboard"," and create a project.",[26,162,163,164,167],{},"Create an app inside the project, with ",[62,165,166],{},"messages"," in its topic list.",[26,169,170],{},"Add a room to the app, and note its slug.",[26,172,173,174,177],{},"Open the ",[124,175,176],{},"Actors"," section, create two actors, and copy both access tokens.",[14,179,180,183,184,188,189,192,193,196],{},[124,181,182],{},"Or over the REST API."," This is the path to use from a script or an AI agent\nthat sets everything up on its own. The only bootstrap secret is a project-scoped\n",[30,185,187],{"href":186},"/docs/authentication#api-keys","API key",", created once in the dashboard;\neverything else is an API call, through the SDK's ",[62,190,191],{},"NoLagApi"," client or plain\n",[62,194,195],{},"curl",":",[51,198,199,474],{},[54,200,205],{"className":201,"code":202,"filename":203,"language":204,"meta":60,"style":60},"language-typescript shiki shiki-themes github-light github-dark","import { NoLagApi } from '@nolag/js-sdk'\n\nconst api = new NoLagApi(process.env.NOLAG_API_KEY) // nlg_live_...\n\n// 1. Create an app and declare the topics it allows. The slug that comes back\n//    is not the one you sent (see the note below), so read it from the response.\nconst app = await api.apps.create({\n  name: 'My App',\n  slug: 'my-app',\n  topics: ['messages'],\n})\nconsole.log(app.slug) // e.g. \"my-app-a3f9\": this is what you pass to setApp()\n\n// 2. Create a room in that app. Clients cannot subscribe to a room that does not exist.\nawait api.rooms.create(app.appId, { name: 'General', slug: 'general' })\n\n// 3. Create two actors. Each access token is shown once; keep both.\nconst publisher = await api.actors.create({ name: 'Publisher', actorType: 'service' })\nconst subscriber = await api.actors.create({ name: 'Subscriber', actorType: 'user' })\nconsole.log(publisher.accessToken, subscriber.accessToken)\n","Setup (server side, once)","typescript",[62,206,207,223,230,262,267,273,279,301,313,324,336,342,357,362,368,394,399,405,436,464],{"__ignoreMap":60},[65,208,209,213,217,220],{"class":67,"line":68},[65,210,212],{"class":211},"szBVR","import",[65,214,216],{"class":215},"sVt8B"," { NoLagApi } ",[65,218,219],{"class":211},"from",[65,221,222],{"class":74}," '@nolag/js-sdk'\n",[65,224,226],{"class":67,"line":225},2,[65,227,229],{"emptyLinePlaceholder":228},true,"\n",[65,231,233,236,240,243,246,249,252,255,258],{"class":67,"line":232},3,[65,234,235],{"class":211},"const",[65,237,239],{"class":238},"sj4cs"," api",[65,241,242],{"class":211}," =",[65,244,245],{"class":211}," new",[65,247,248],{"class":71}," NoLagApi",[65,250,251],{"class":215},"(process.env.",[65,253,254],{"class":238},"NOLAG_API_KEY",[65,256,257],{"class":215},") ",[65,259,261],{"class":260},"sJ8bj","// nlg_live_...\n",[65,263,265],{"class":67,"line":264},4,[65,266,229],{"emptyLinePlaceholder":228},[65,268,270],{"class":67,"line":269},5,[65,271,272],{"class":260},"// 1. Create an app and declare the topics it allows. The slug that comes back\n",[65,274,276],{"class":67,"line":275},6,[65,277,278],{"class":260},"//    is not the one you sent (see the note below), so read it from the response.\n",[65,280,282,284,287,289,292,295,298],{"class":67,"line":281},7,[65,283,235],{"class":211},[65,285,286],{"class":238}," app",[65,288,242],{"class":211},[65,290,291],{"class":211}," await",[65,293,294],{"class":215}," api.apps.",[65,296,297],{"class":71},"create",[65,299,300],{"class":215},"({\n",[65,302,304,307,310],{"class":67,"line":303},8,[65,305,306],{"class":215},"  name: ",[65,308,309],{"class":74},"'My App'",[65,311,312],{"class":215},",\n",[65,314,316,319,322],{"class":67,"line":315},9,[65,317,318],{"class":215},"  slug: ",[65,320,321],{"class":74},"'my-app'",[65,323,312],{"class":215},[65,325,327,330,333],{"class":67,"line":326},10,[65,328,329],{"class":215},"  topics: [",[65,331,332],{"class":74},"'messages'",[65,334,335],{"class":215},"],\n",[65,337,339],{"class":67,"line":338},11,[65,340,341],{"class":215},"})\n",[65,343,345,348,351,354],{"class":67,"line":344},12,[65,346,347],{"class":215},"console.",[65,349,350],{"class":71},"log",[65,352,353],{"class":215},"(app.slug) ",[65,355,356],{"class":260},"// e.g. \"my-app-a3f9\": this is what you pass to setApp()\n",[65,358,360],{"class":67,"line":359},13,[65,361,229],{"emptyLinePlaceholder":228},[65,363,365],{"class":67,"line":364},14,[65,366,367],{"class":260},"// 2. Create a room in that app. Clients cannot subscribe to a room that does not exist.\n",[65,369,371,374,377,379,382,385,388,391],{"class":67,"line":370},15,[65,372,373],{"class":211},"await",[65,375,376],{"class":215}," api.rooms.",[65,378,297],{"class":71},[65,380,381],{"class":215},"(app.appId, { name: ",[65,383,384],{"class":74},"'General'",[65,386,387],{"class":215},", slug: ",[65,389,390],{"class":74},"'general'",[65,392,393],{"class":215}," })\n",[65,395,397],{"class":67,"line":396},16,[65,398,229],{"emptyLinePlaceholder":228},[65,400,402],{"class":67,"line":401},17,[65,403,404],{"class":260},"// 3. Create two actors. Each access token is shown once; keep both.\n",[65,406,408,410,413,415,417,420,422,425,428,431,434],{"class":67,"line":407},18,[65,409,235],{"class":211},[65,411,412],{"class":238}," publisher",[65,414,242],{"class":211},[65,416,291],{"class":211},[65,418,419],{"class":215}," api.actors.",[65,421,297],{"class":71},[65,423,424],{"class":215},"({ name: ",[65,426,427],{"class":74},"'Publisher'",[65,429,430],{"class":215},", actorType: ",[65,432,433],{"class":74},"'service'",[65,435,393],{"class":215},[65,437,439,441,444,446,448,450,452,454,457,459,462],{"class":67,"line":438},19,[65,440,235],{"class":211},[65,442,443],{"class":238}," subscriber",[65,445,242],{"class":211},[65,447,291],{"class":211},[65,449,419],{"class":215},[65,451,297],{"class":71},[65,453,424],{"class":215},[65,455,456],{"class":74},"'Subscriber'",[65,458,430],{"class":215},[65,460,461],{"class":74},"'user'",[65,463,393],{"class":215},[65,465,467,469,471],{"class":67,"line":466},20,[65,468,347],{"class":215},[65,470,350],{"class":71},[65,472,473],{"class":215},"(publisher.accessToken, subscriber.accessToken)\n",[54,475,478],{"className":56,"code":476,"filename":477,"language":59,"meta":60,"style":60},"# 1. Create an app with the topics it allows. Read appId and slug back out of\n#    the response: the returned slug is not the one you sent (see the note below).\ncurl -X POST https://api.nolag.app/v1/apps \\\n  -H \"Authorization: Bearer nlg_live_xxx.secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"My App\",\"slug\":\"my-app\",\"topics\":[\"messages\"]}'\n# => {\"appId\":\"019fd987-9dee-75cb-97a7-39d71957ca23\",\"slug\":\"my-app-a3f9\",...}\n\n# 2. Create a room in that app, using the appId from step 1.\n#    Clients cannot subscribe to a room that does not exist yet.\ncurl -X POST https://api.nolag.app/v1/apps/019fd987-9dee-75cb-97a7-39d71957ca23/rooms \\\n  -H \"Authorization: Bearer nlg_live_xxx.secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"General\",\"slug\":\"general\"}'\n\n# 3. Create two actors, and copy accessToken from each response\ncurl -X POST https://api.nolag.app/v1/actors \\\n  -H \"Authorization: Bearer nlg_live_xxx.secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"Publisher\",\"actorType\":\"service\"}'\ncurl -X POST https://api.nolag.app/v1/actors \\\n  -H \"Authorization: Bearer nlg_live_xxx.secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"Subscriber\",\"actorType\":\"user\"}'\n","Terminal",[62,479,480,485,490,506,516,525,533,538,542,547,552,565,573,581,588,592,597,610,618,626,633,646,655,664],{"__ignoreMap":60},[65,481,482],{"class":67,"line":68},[65,483,484],{"class":260},"# 1. Create an app with the topics it allows. Read appId and slug back out of\n",[65,486,487],{"class":67,"line":225},[65,488,489],{"class":260},"#    the response: the returned slug is not the one you sent (see the note below).\n",[65,491,492,494,497,500,503],{"class":67,"line":232},[65,493,195],{"class":71},[65,495,496],{"class":238}," -X",[65,498,499],{"class":74}," POST",[65,501,502],{"class":74}," https://api.nolag.app/v1/apps",[65,504,505],{"class":238}," \\\n",[65,507,508,511,514],{"class":67,"line":264},[65,509,510],{"class":238},"  -H",[65,512,513],{"class":74}," \"Authorization: Bearer nlg_live_xxx.secret\"",[65,515,505],{"class":238},[65,517,518,520,523],{"class":67,"line":269},[65,519,510],{"class":238},[65,521,522],{"class":74}," \"Content-Type: application/json\"",[65,524,505],{"class":238},[65,526,527,530],{"class":67,"line":275},[65,528,529],{"class":238},"  -d",[65,531,532],{"class":74}," '{\"name\":\"My App\",\"slug\":\"my-app\",\"topics\":[\"messages\"]}'\n",[65,534,535],{"class":67,"line":281},[65,536,537],{"class":260},"# => {\"appId\":\"019fd987-9dee-75cb-97a7-39d71957ca23\",\"slug\":\"my-app-a3f9\",...}\n",[65,539,540],{"class":67,"line":303},[65,541,229],{"emptyLinePlaceholder":228},[65,543,544],{"class":67,"line":315},[65,545,546],{"class":260},"# 2. Create a room in that app, using the appId from step 1.\n",[65,548,549],{"class":67,"line":326},[65,550,551],{"class":260},"#    Clients cannot subscribe to a room that does not exist yet.\n",[65,553,554,556,558,560,563],{"class":67,"line":338},[65,555,195],{"class":71},[65,557,496],{"class":238},[65,559,499],{"class":74},[65,561,562],{"class":74}," https://api.nolag.app/v1/apps/019fd987-9dee-75cb-97a7-39d71957ca23/rooms",[65,564,505],{"class":238},[65,566,567,569,571],{"class":67,"line":344},[65,568,510],{"class":238},[65,570,513],{"class":74},[65,572,505],{"class":238},[65,574,575,577,579],{"class":67,"line":359},[65,576,510],{"class":238},[65,578,522],{"class":74},[65,580,505],{"class":238},[65,582,583,585],{"class":67,"line":364},[65,584,529],{"class":238},[65,586,587],{"class":74}," '{\"name\":\"General\",\"slug\":\"general\"}'\n",[65,589,590],{"class":67,"line":370},[65,591,229],{"emptyLinePlaceholder":228},[65,593,594],{"class":67,"line":396},[65,595,596],{"class":260},"# 3. Create two actors, and copy accessToken from each response\n",[65,598,599,601,603,605,608],{"class":67,"line":401},[65,600,195],{"class":71},[65,602,496],{"class":238},[65,604,499],{"class":74},[65,606,607],{"class":74}," https://api.nolag.app/v1/actors",[65,609,505],{"class":238},[65,611,612,614,616],{"class":67,"line":407},[65,613,510],{"class":238},[65,615,513],{"class":74},[65,617,505],{"class":238},[65,619,620,622,624],{"class":67,"line":438},[65,621,510],{"class":238},[65,623,522],{"class":74},[65,625,505],{"class":238},[65,627,628,630],{"class":67,"line":466},[65,629,529],{"class":238},[65,631,632],{"class":74}," '{\"name\":\"Publisher\",\"actorType\":\"service\"}'\n",[65,634,636,638,640,642,644],{"class":67,"line":635},21,[65,637,195],{"class":71},[65,639,496],{"class":238},[65,641,499],{"class":74},[65,643,607],{"class":74},[65,645,505],{"class":238},[65,647,649,651,653],{"class":67,"line":648},22,[65,650,510],{"class":238},[65,652,513],{"class":74},[65,654,505],{"class":238},[65,656,658,660,662],{"class":67,"line":657},23,[65,659,510],{"class":238},[65,661,522],{"class":74},[65,663,505],{"class":238},[65,665,667,669],{"class":67,"line":666},24,[65,668,529],{"class":238},[65,670,671],{"class":74}," '{\"name\":\"Subscriber\",\"actorType\":\"user\"}'\n",[673,674,676],"callout",{"type":675},"warning",[14,677,678,681],{},[124,679,680],{},"Save the tokens now."," An actor's access token is only returned when the actor is\ncreated. It is never shown again.",[673,683,684],{"type":675},[14,685,686,689,690,693,694,697,698,701,702,705],{},[124,687,688],{},"App slugs always get a random suffix."," NoLag appends four random characters to\nevery app slug to keep it unique within the project, so a requested slug of\n",[62,691,692],{},"my-app"," comes back as something like ",[62,695,696],{},"my-app-a3f9",". Read the ",[62,699,700],{},"slug"," field from the\ncreate response and pass that value to ",[62,703,704],{},"setApp()",". Room slugs are different: they\nare stored exactly as you supply them.",[673,707,708],{"type":675},[14,709,710,713,714,717,718,721,722,725,726,729],{},[124,711,712],{},"Rooms must exist before you subscribe."," Rooms are never created implicitly.\nSubscribing to a room that has not been created returns an ",[62,715,716],{},"unknown_topic"," error\n(code 42940) instead of delivering messages. If you skip the error handler in\nStep 3, this looks like total silence: ",[62,719,720],{},"connect()",", ",[62,723,724],{},"subscribe()",", and ",[62,727,728],{},"emit()","\nall appear to succeed and no message ever arrives.",[14,731,732,733,737],{},"See the ",[30,734,736],{"href":735},"/docs/api-reference","REST API Reference"," for the full app, room, and actor endpoints.",[18,739,741],{"id":740},"step-3-connect-to-nolag","Step 3: Connect to NoLag",[14,743,744,745,748,749,752,753,721,755,758,759,762],{},"Attach an error handler before you connect. Subscribe and publish calls do not\nthrow: the broker reports problems such as an unknown topic or a permission\nrefusal on the ",[62,746,747],{},"error"," event, so without a handler a misconfigured app simply\ngoes quiet. Broker errors arrive as ",[62,750,751],{},"NoLagServerError",", with ",[62,754,62],{},[62,756,757],{},"topic"," and\n",[62,760,761],{},"hint","; transport failures arrive as a plain error.",[14,764,765],{},"This first client is the subscriber:",[51,767,768,987,1065],{},[54,769,772],{"className":201,"code":770,"filename":771,"language":204,"meta":60,"style":60},"import { NoLag, NoLagServerError } from '@nolag/js-sdk'\n\n// Create client and connect\nconst client = NoLag('subscriber_access_token')\n\n// Attach this first: server-side errors arrive here, not as thrown exceptions\nclient.on('error', (err) => {\n  if (err instanceof NoLagServerError) {\n    console.error(`NoLag ${err.error} (${err.code}) on ${err.topic}: ${err.hint}`)\n  } else {\n    console.error('NoLag error:', err)\n  }\n})\n\nawait client.connect()\n\nconsole.log('Connected to NoLag!')\n","TypeScript",[62,773,774,785,789,794,815,819,824,852,869,920,930,944,949,953,957,970,974],{"__ignoreMap":60},[65,775,776,778,781,783],{"class":67,"line":68},[65,777,212],{"class":211},[65,779,780],{"class":215}," { NoLag, NoLagServerError } ",[65,782,219],{"class":211},[65,784,222],{"class":74},[65,786,787],{"class":67,"line":225},[65,788,229],{"emptyLinePlaceholder":228},[65,790,791],{"class":67,"line":232},[65,792,793],{"class":260},"// Create client and connect\n",[65,795,796,798,801,803,806,809,812],{"class":67,"line":264},[65,797,235],{"class":211},[65,799,800],{"class":238}," client",[65,802,242],{"class":211},[65,804,805],{"class":71}," NoLag",[65,807,808],{"class":215},"(",[65,810,811],{"class":74},"'subscriber_access_token'",[65,813,814],{"class":215},")\n",[65,816,817],{"class":67,"line":269},[65,818,229],{"emptyLinePlaceholder":228},[65,820,821],{"class":67,"line":275},[65,822,823],{"class":260},"// Attach this first: server-side errors arrive here, not as thrown exceptions\n",[65,825,826,829,832,834,837,840,844,846,849],{"class":67,"line":281},[65,827,828],{"class":215},"client.",[65,830,831],{"class":71},"on",[65,833,808],{"class":215},[65,835,836],{"class":74},"'error'",[65,838,839],{"class":215},", (",[65,841,843],{"class":842},"s4XuR","err",[65,845,257],{"class":215},[65,847,848],{"class":211},"=>",[65,850,851],{"class":215}," {\n",[65,853,854,857,860,863,866],{"class":67,"line":303},[65,855,856],{"class":211},"  if",[65,858,859],{"class":215}," (err ",[65,861,862],{"class":211},"instanceof",[65,864,865],{"class":71}," NoLagServerError",[65,867,868],{"class":215},") {\n",[65,870,871,874,876,878,881,883,886,888,891,893,895,897,900,902,904,906,909,911,913,915,918],{"class":67,"line":315},[65,872,873],{"class":215},"    console.",[65,875,747],{"class":71},[65,877,808],{"class":215},[65,879,880],{"class":74},"`NoLag ${",[65,882,843],{"class":215},[65,884,885],{"class":74},".",[65,887,747],{"class":215},[65,889,890],{"class":74},"} (${",[65,892,843],{"class":215},[65,894,885],{"class":74},[65,896,62],{"class":215},[65,898,899],{"class":74},"}) on ${",[65,901,843],{"class":215},[65,903,885],{"class":74},[65,905,757],{"class":215},[65,907,908],{"class":74},"}: ${",[65,910,843],{"class":215},[65,912,885],{"class":74},[65,914,761],{"class":215},[65,916,917],{"class":74},"}`",[65,919,814],{"class":215},[65,921,922,925,928],{"class":67,"line":326},[65,923,924],{"class":215},"  } ",[65,926,927],{"class":211},"else",[65,929,851],{"class":215},[65,931,932,934,936,938,941],{"class":67,"line":338},[65,933,873],{"class":215},[65,935,747],{"class":71},[65,937,808],{"class":215},[65,939,940],{"class":74},"'NoLag error:'",[65,942,943],{"class":215},", err)\n",[65,945,946],{"class":67,"line":344},[65,947,948],{"class":215},"  }\n",[65,950,951],{"class":67,"line":359},[65,952,341],{"class":215},[65,954,955],{"class":67,"line":364},[65,956,229],{"emptyLinePlaceholder":228},[65,958,959,961,964,967],{"class":67,"line":370},[65,960,373],{"class":211},[65,962,963],{"class":215}," client.",[65,965,966],{"class":71},"connect",[65,968,969],{"class":215},"()\n",[65,971,972],{"class":67,"line":396},[65,973,229],{"emptyLinePlaceholder":228},[65,975,976,978,980,982,985],{"class":67,"line":401},[65,977,347],{"class":215},[65,979,350],{"class":71},[65,981,808],{"class":215},[65,983,984],{"class":74},"'Connected to NoLag!'",[65,986,814],{"class":215},[54,988,993],{"className":989,"code":990,"filename":991,"language":992,"meta":60,"style":60},"language-python shiki shiki-themes github-light github-dark","from nolag import NoLag\n\n# Create client and connect\nclient = NoLag('subscriber_access_token')\n\n# Attach this first: server-side errors arrive here, not as raised exceptions.\n# Broker errors are NoLagServerError; str(err) includes code, topic and hint.\ndef handle_error(err):\n    print(f'NoLag error: {err}')\n\nclient.on('error', handle_error)\n\nawait client.connect()\n\nprint('Connected to NoLag!')\n","Python","python",[62,994,995,1000,1004,1009,1014,1018,1023,1028,1033,1038,1042,1047,1051,1056,1060],{"__ignoreMap":60},[65,996,997],{"class":67,"line":68},[65,998,999],{},"from nolag import NoLag\n",[65,1001,1002],{"class":67,"line":225},[65,1003,229],{"emptyLinePlaceholder":228},[65,1005,1006],{"class":67,"line":232},[65,1007,1008],{},"# Create client and connect\n",[65,1010,1011],{"class":67,"line":264},[65,1012,1013],{},"client = NoLag('subscriber_access_token')\n",[65,1015,1016],{"class":67,"line":269},[65,1017,229],{"emptyLinePlaceholder":228},[65,1019,1020],{"class":67,"line":275},[65,1021,1022],{},"# Attach this first: server-side errors arrive here, not as raised exceptions.\n",[65,1024,1025],{"class":67,"line":281},[65,1026,1027],{},"# Broker errors are NoLagServerError; str(err) includes code, topic and hint.\n",[65,1029,1030],{"class":67,"line":303},[65,1031,1032],{},"def handle_error(err):\n",[65,1034,1035],{"class":67,"line":315},[65,1036,1037],{},"    print(f'NoLag error: {err}')\n",[65,1039,1040],{"class":67,"line":326},[65,1041,229],{"emptyLinePlaceholder":228},[65,1043,1044],{"class":67,"line":338},[65,1045,1046],{},"client.on('error', handle_error)\n",[65,1048,1049],{"class":67,"line":344},[65,1050,229],{"emptyLinePlaceholder":228},[65,1052,1053],{"class":67,"line":359},[65,1054,1055],{},"await client.connect()\n",[65,1057,1058],{"class":67,"line":364},[65,1059,229],{"emptyLinePlaceholder":228},[65,1061,1062],{"class":67,"line":370},[65,1063,1064],{},"print('Connected to NoLag!')\n",[54,1066,1070],{"className":1067,"code":1068,"filename":1069,"language":104,"meta":60,"style":60},"language-go shiki shiki-themes github-light github-dark","package main\n\nimport (\n    \"fmt\"\n    \"log\"\n\n    nolag \"github.com/NoLagApp/go-sdk\"\n)\n\nfunc main() {\n    // Create client and connect\n    client := nolag.New(\"subscriber_access_token\")\n\n    // Attach this first: server-side errors arrive here, not as returned errors\n    client.OnError(func(err *nolag.ServerError) {\n        log.Printf(\"NoLag %s (%d) on %s: %s\", err.Name, err.Code, err.Topic, err.Hint)\n    })\n\n    if err := client.Connect(); err != nil {\n        log.Fatal(err)\n    }\n\n    fmt.Println(\"Connected to NoLag!\")\n}\n","Go",[62,1071,1072,1077,1081,1086,1091,1096,1100,1105,1109,1113,1118,1123,1128,1132,1137,1142,1147,1152,1156,1161,1166,1171,1175,1180],{"__ignoreMap":60},[65,1073,1074],{"class":67,"line":68},[65,1075,1076],{},"package main\n",[65,1078,1079],{"class":67,"line":225},[65,1080,229],{"emptyLinePlaceholder":228},[65,1082,1083],{"class":67,"line":232},[65,1084,1085],{},"import (\n",[65,1087,1088],{"class":67,"line":264},[65,1089,1090],{},"    \"fmt\"\n",[65,1092,1093],{"class":67,"line":269},[65,1094,1095],{},"    \"log\"\n",[65,1097,1098],{"class":67,"line":275},[65,1099,229],{"emptyLinePlaceholder":228},[65,1101,1102],{"class":67,"line":281},[65,1103,1104],{},"    nolag \"github.com/NoLagApp/go-sdk\"\n",[65,1106,1107],{"class":67,"line":303},[65,1108,814],{},[65,1110,1111],{"class":67,"line":315},[65,1112,229],{"emptyLinePlaceholder":228},[65,1114,1115],{"class":67,"line":326},[65,1116,1117],{},"func main() {\n",[65,1119,1120],{"class":67,"line":338},[65,1121,1122],{},"    // Create client and connect\n",[65,1124,1125],{"class":67,"line":344},[65,1126,1127],{},"    client := nolag.New(\"subscriber_access_token\")\n",[65,1129,1130],{"class":67,"line":359},[65,1131,229],{"emptyLinePlaceholder":228},[65,1133,1134],{"class":67,"line":364},[65,1135,1136],{},"    // Attach this first: server-side errors arrive here, not as returned errors\n",[65,1138,1139],{"class":67,"line":370},[65,1140,1141],{},"    client.OnError(func(err *nolag.ServerError) {\n",[65,1143,1144],{"class":67,"line":396},[65,1145,1146],{},"        log.Printf(\"NoLag %s (%d) on %s: %s\", err.Name, err.Code, err.Topic, err.Hint)\n",[65,1148,1149],{"class":67,"line":401},[65,1150,1151],{},"    })\n",[65,1153,1154],{"class":67,"line":407},[65,1155,229],{"emptyLinePlaceholder":228},[65,1157,1158],{"class":67,"line":438},[65,1159,1160],{},"    if err := client.Connect(); err != nil {\n",[65,1162,1163],{"class":67,"line":466},[65,1164,1165],{},"        log.Fatal(err)\n",[65,1167,1168],{"class":67,"line":635},[65,1169,1170],{},"    }\n",[65,1172,1173],{"class":67,"line":648},[65,1174,229],{"emptyLinePlaceholder":228},[65,1176,1177],{"class":67,"line":657},[65,1178,1179],{},"    fmt.Println(\"Connected to NoLag!\")\n",[65,1181,1182],{"class":67,"line":666},[65,1183,1184],{},"}\n",[18,1186,1188],{"id":1187},"step-4-subscribe-to-a-topic","Step 4: Subscribe to a Topic",[14,1190,1191],{},"Topics are channels for messages. Subscribe to receive messages published to a topic.",[14,1193,1194],{},"Pass the app slug exactly as the create response returned it, suffix included, and\nthe slug of a room that already exists:",[51,1196,1197,1306,1359],{},[54,1198,1200],{"className":201,"code":1199,"filename":771,"language":204,"meta":60,"style":60},"// Set up app and room, then subscribe.\n// 'my-app-a3f9' is the slug returned when the app was created.\nconst room = client.setApp('my-app-a3f9').setRoom('general')\nroom.subscribe('messages')\n\n// Listen for messages\nroom.on('messages', (data) => {\n  console.log('Received:', data)\n})\n",[62,1201,1202,1207,1212,1243,1257,1261,1266,1287,1302],{"__ignoreMap":60},[65,1203,1204],{"class":67,"line":68},[65,1205,1206],{"class":260},"// Set up app and room, then subscribe.\n",[65,1208,1209],{"class":67,"line":225},[65,1210,1211],{"class":260},"// 'my-app-a3f9' is the slug returned when the app was created.\n",[65,1213,1214,1216,1219,1221,1223,1226,1228,1231,1234,1237,1239,1241],{"class":67,"line":232},[65,1215,235],{"class":211},[65,1217,1218],{"class":238}," room",[65,1220,242],{"class":211},[65,1222,963],{"class":215},[65,1224,1225],{"class":71},"setApp",[65,1227,808],{"class":215},[65,1229,1230],{"class":74},"'my-app-a3f9'",[65,1232,1233],{"class":215},").",[65,1235,1236],{"class":71},"setRoom",[65,1238,808],{"class":215},[65,1240,390],{"class":74},[65,1242,814],{"class":215},[65,1244,1245,1248,1251,1253,1255],{"class":67,"line":264},[65,1246,1247],{"class":215},"room.",[65,1249,1250],{"class":71},"subscribe",[65,1252,808],{"class":215},[65,1254,332],{"class":74},[65,1256,814],{"class":215},[65,1258,1259],{"class":67,"line":269},[65,1260,229],{"emptyLinePlaceholder":228},[65,1262,1263],{"class":67,"line":275},[65,1264,1265],{"class":260},"// Listen for messages\n",[65,1267,1268,1270,1272,1274,1276,1278,1281,1283,1285],{"class":67,"line":281},[65,1269,1247],{"class":215},[65,1271,831],{"class":71},[65,1273,808],{"class":215},[65,1275,332],{"class":74},[65,1277,839],{"class":215},[65,1279,1280],{"class":842},"data",[65,1282,257],{"class":215},[65,1284,848],{"class":211},[65,1286,851],{"class":215},[65,1288,1289,1292,1294,1296,1299],{"class":67,"line":303},[65,1290,1291],{"class":215},"  console.",[65,1293,350],{"class":71},[65,1295,808],{"class":215},[65,1297,1298],{"class":74},"'Received:'",[65,1300,1301],{"class":215},", data)\n",[65,1303,1304],{"class":67,"line":315},[65,1305,341],{"class":215},[54,1307,1309],{"className":989,"code":1308,"filename":991,"language":992,"meta":60,"style":60},"# Set up app and room, then subscribe.\n# 'my-app-a3f9' is the slug returned when the app was created.\nroom = client.set_app('my-app-a3f9').set_room('general')\nawait room.subscribe('messages')\n\n# Listen for messages\ndef handle_message(data, meta):\n    print('Received:', data)\n\nroom.on('messages', handle_message)\n",[62,1310,1311,1316,1321,1326,1331,1335,1340,1345,1350,1354],{"__ignoreMap":60},[65,1312,1313],{"class":67,"line":68},[65,1314,1315],{},"# Set up app and room, then subscribe.\n",[65,1317,1318],{"class":67,"line":225},[65,1319,1320],{},"# 'my-app-a3f9' is the slug returned when the app was created.\n",[65,1322,1323],{"class":67,"line":232},[65,1324,1325],{},"room = client.set_app('my-app-a3f9').set_room('general')\n",[65,1327,1328],{"class":67,"line":264},[65,1329,1330],{},"await room.subscribe('messages')\n",[65,1332,1333],{"class":67,"line":269},[65,1334,229],{"emptyLinePlaceholder":228},[65,1336,1337],{"class":67,"line":275},[65,1338,1339],{},"# Listen for messages\n",[65,1341,1342],{"class":67,"line":281},[65,1343,1344],{},"def handle_message(data, meta):\n",[65,1346,1347],{"class":67,"line":303},[65,1348,1349],{},"    print('Received:', data)\n",[65,1351,1352],{"class":67,"line":315},[65,1353,229],{"emptyLinePlaceholder":228},[65,1355,1356],{"class":67,"line":326},[65,1357,1358],{},"room.on('messages', handle_message)\n",[54,1360,1362],{"className":1067,"code":1361,"filename":1069,"language":104,"meta":60,"style":60},"// Set up app and room, then subscribe with handler.\n// \"my-app-a3f9\" is the slug returned when the app was created.\nroom := client.SetApp(\"my-app-a3f9\").SetRoom(\"general\")\nroom.Subscribe(\"messages\", func(data any, meta nolag.MessageMeta) {\n    fmt.Println(\"Received:\", data)\n})\n",[62,1363,1364,1369,1374,1379,1384,1389],{"__ignoreMap":60},[65,1365,1366],{"class":67,"line":68},[65,1367,1368],{},"// Set up app and room, then subscribe with handler.\n",[65,1370,1371],{"class":67,"line":225},[65,1372,1373],{},"// \"my-app-a3f9\" is the slug returned when the app was created.\n",[65,1375,1376],{"class":67,"line":232},[65,1377,1378],{},"room := client.SetApp(\"my-app-a3f9\").SetRoom(\"general\")\n",[65,1380,1381],{"class":67,"line":264},[65,1382,1383],{},"room.Subscribe(\"messages\", func(data any, meta nolag.MessageMeta) {\n",[65,1385,1386],{"class":67,"line":269},[65,1387,1388],{},"    fmt.Println(\"Received:\", data)\n",[65,1390,1391],{"class":67,"line":275},[65,1392,341],{},[18,1394,1396],{"id":1395},"step-5-publish-a-message","Step 5: Publish a Message",[14,1398,1399,1400,1402],{},"Publish from a second connection, authenticated with the publisher's token.\nPublishers never receive their own messages, so an ",[62,1401,728],{}," on the connection\nthat subscribed in Step 4 would deliver nothing:",[51,1404,1405,1512,1569],{},[54,1406,1408],{"className":201,"code":1407,"filename":771,"language":204,"meta":60,"style":60},"const publisher = NoLag('publisher_access_token')\nawait publisher.connect()\n\n// Publish a message\npublisher.setApp('my-app-a3f9').setRoom('general').emit('messages', {\n  text: 'Hello, World!',\n  sender: 'user-123',\n  timestamp: Date.now()\n})\n",[62,1409,1410,1427,1438,1442,1447,1478,1488,1498,1508],{"__ignoreMap":60},[65,1411,1412,1414,1416,1418,1420,1422,1425],{"class":67,"line":68},[65,1413,235],{"class":211},[65,1415,412],{"class":238},[65,1417,242],{"class":211},[65,1419,805],{"class":71},[65,1421,808],{"class":215},[65,1423,1424],{"class":74},"'publisher_access_token'",[65,1426,814],{"class":215},[65,1428,1429,1431,1434,1436],{"class":67,"line":225},[65,1430,373],{"class":211},[65,1432,1433],{"class":215}," publisher.",[65,1435,966],{"class":71},[65,1437,969],{"class":215},[65,1439,1440],{"class":67,"line":232},[65,1441,229],{"emptyLinePlaceholder":228},[65,1443,1444],{"class":67,"line":264},[65,1445,1446],{"class":260},"// Publish a message\n",[65,1448,1449,1452,1454,1456,1458,1460,1462,1464,1466,1468,1471,1473,1475],{"class":67,"line":269},[65,1450,1451],{"class":215},"publisher.",[65,1453,1225],{"class":71},[65,1455,808],{"class":215},[65,1457,1230],{"class":74},[65,1459,1233],{"class":215},[65,1461,1236],{"class":71},[65,1463,808],{"class":215},[65,1465,390],{"class":74},[65,1467,1233],{"class":215},[65,1469,1470],{"class":71},"emit",[65,1472,808],{"class":215},[65,1474,332],{"class":74},[65,1476,1477],{"class":215},", {\n",[65,1479,1480,1483,1486],{"class":67,"line":275},[65,1481,1482],{"class":215},"  text: ",[65,1484,1485],{"class":74},"'Hello, World!'",[65,1487,312],{"class":215},[65,1489,1490,1493,1496],{"class":67,"line":281},[65,1491,1492],{"class":215},"  sender: ",[65,1494,1495],{"class":74},"'user-123'",[65,1497,312],{"class":215},[65,1499,1500,1503,1506],{"class":67,"line":303},[65,1501,1502],{"class":215},"  timestamp: Date.",[65,1504,1505],{"class":71},"now",[65,1507,969],{"class":215},[65,1509,1510],{"class":67,"line":315},[65,1511,341],{"class":215},[54,1513,1515],{"className":989,"code":1514,"filename":991,"language":992,"meta":60,"style":60},"import time\n\npublisher = NoLag('publisher_access_token')\nawait publisher.connect()\n\n# Publish a message\nawait publisher.set_app('my-app-a3f9').set_room('general').emit('messages', {\n    'text': 'Hello, World!',\n    'sender': 'user-123',\n    'timestamp': time.time()\n})\n",[62,1516,1517,1522,1526,1531,1536,1540,1545,1550,1555,1560,1565],{"__ignoreMap":60},[65,1518,1519],{"class":67,"line":68},[65,1520,1521],{},"import time\n",[65,1523,1524],{"class":67,"line":225},[65,1525,229],{"emptyLinePlaceholder":228},[65,1527,1528],{"class":67,"line":232},[65,1529,1530],{},"publisher = NoLag('publisher_access_token')\n",[65,1532,1533],{"class":67,"line":264},[65,1534,1535],{},"await publisher.connect()\n",[65,1537,1538],{"class":67,"line":269},[65,1539,229],{"emptyLinePlaceholder":228},[65,1541,1542],{"class":67,"line":275},[65,1543,1544],{},"# Publish a message\n",[65,1546,1547],{"class":67,"line":281},[65,1548,1549],{},"await publisher.set_app('my-app-a3f9').set_room('general').emit('messages', {\n",[65,1551,1552],{"class":67,"line":303},[65,1553,1554],{},"    'text': 'Hello, World!',\n",[65,1556,1557],{"class":67,"line":315},[65,1558,1559],{},"    'sender': 'user-123',\n",[65,1561,1562],{"class":67,"line":326},[65,1563,1564],{},"    'timestamp': time.time()\n",[65,1566,1567],{"class":67,"line":338},[65,1568,341],{},[54,1570,1572],{"className":1067,"code":1571,"filename":1069,"language":104,"meta":60,"style":60},"publisher := nolag.New(\"publisher_access_token\")\nif err := publisher.Connect(); err != nil {\n    log.Fatal(err)\n}\n\n// Publish a message\npublisher.SetApp(\"my-app-a3f9\").SetRoom(\"general\").Emit(\"messages\", map[string]any{\n    \"text\":      \"Hello, World!\",\n    \"sender\":    \"user-123\",\n    \"timestamp\": time.Now().Unix(),\n})\n",[62,1573,1574,1579,1584,1589,1593,1597,1601,1606,1611,1616,1621],{"__ignoreMap":60},[65,1575,1576],{"class":67,"line":68},[65,1577,1578],{},"publisher := nolag.New(\"publisher_access_token\")\n",[65,1580,1581],{"class":67,"line":225},[65,1582,1583],{},"if err := publisher.Connect(); err != nil {\n",[65,1585,1586],{"class":67,"line":232},[65,1587,1588],{},"    log.Fatal(err)\n",[65,1590,1591],{"class":67,"line":264},[65,1592,1184],{},[65,1594,1595],{"class":67,"line":269},[65,1596,229],{"emptyLinePlaceholder":228},[65,1598,1599],{"class":67,"line":275},[65,1600,1446],{},[65,1602,1603],{"class":67,"line":281},[65,1604,1605],{},"publisher.SetApp(\"my-app-a3f9\").SetRoom(\"general\").Emit(\"messages\", map[string]any{\n",[65,1607,1608],{"class":67,"line":303},[65,1609,1610],{},"    \"text\":      \"Hello, World!\",\n",[65,1612,1613],{"class":67,"line":315},[65,1614,1615],{},"    \"sender\":    \"user-123\",\n",[65,1617,1618],{"class":67,"line":326},[65,1619,1620],{},"    \"timestamp\": time.Now().Unix(),\n",[65,1622,1623],{"class":67,"line":338},[65,1624,341],{},[18,1626,1628],{"id":1627},"complete-example","Complete Example",[14,1630,1631],{},"Here's a complete example in your preferred language. It assumes the app, room, and\ntwo actors from Step 2 already exist. One actor subscribes and a different actor\npublishes, because publishers never receive their own messages.",[51,1633,1634,2007,2202],{},[54,1635,1637],{"className":201,"code":1636,"filename":771,"language":204,"meta":60,"style":60},"import { NoLag, NoLagServerError } from '@nolag/js-sdk'\n\nconst APP_SLUG = 'my-app-a3f9' // the slug returned when you created the app\n\n// Surface broker errors: subscribe and emit never throw\nconst logErrors = (err: Error) => {\n  if (err instanceof NoLagServerError) {\n    console.error(`NoLag ${err.error} (${err.code}) on ${err.topic}: ${err.hint}`)\n  } else {\n    console.error('NoLag error:', err)\n  }\n}\n\n// One actor subscribes...\nconst subscriber = NoLag('subscriber_access_token')\nsubscriber.on('error', logErrors)\nawait subscriber.connect()\n\nconst inbox = subscriber.setApp(APP_SLUG).setRoom('general')\ninbox.subscribe('messages')\ninbox.on('messages', (data) => {\n  console.log('Received:', data)\n})\n\n// ...and a different actor publishes\nconst publisher = NoLag('publisher_access_token')\npublisher.on('error', logErrors)\nawait publisher.connect()\n\npublisher.setApp(APP_SLUG).setRoom('general').emit('messages', { text: 'Hello, World!' })\n",[62,1638,1639,1649,1653,1668,1672,1677,1702,1714,1758,1766,1778,1782,1786,1790,1795,1811,1825,1836,1840,1868,1881,1901,1913,1917,1921,1927,1944,1957,1968,1973],{"__ignoreMap":60},[65,1640,1641,1643,1645,1647],{"class":67,"line":68},[65,1642,212],{"class":211},[65,1644,780],{"class":215},[65,1646,219],{"class":211},[65,1648,222],{"class":74},[65,1650,1651],{"class":67,"line":225},[65,1652,229],{"emptyLinePlaceholder":228},[65,1654,1655,1657,1660,1662,1665],{"class":67,"line":232},[65,1656,235],{"class":211},[65,1658,1659],{"class":238}," APP_SLUG",[65,1661,242],{"class":211},[65,1663,1664],{"class":74}," 'my-app-a3f9'",[65,1666,1667],{"class":260}," // the slug returned when you created the app\n",[65,1669,1670],{"class":67,"line":264},[65,1671,229],{"emptyLinePlaceholder":228},[65,1673,1674],{"class":67,"line":269},[65,1675,1676],{"class":260},"// Surface broker errors: subscribe and emit never throw\n",[65,1678,1679,1681,1684,1686,1689,1691,1693,1696,1698,1700],{"class":67,"line":275},[65,1680,235],{"class":211},[65,1682,1683],{"class":71}," logErrors",[65,1685,242],{"class":211},[65,1687,1688],{"class":215}," (",[65,1690,843],{"class":842},[65,1692,196],{"class":211},[65,1694,1695],{"class":71}," Error",[65,1697,257],{"class":215},[65,1699,848],{"class":211},[65,1701,851],{"class":215},[65,1703,1704,1706,1708,1710,1712],{"class":67,"line":281},[65,1705,856],{"class":211},[65,1707,859],{"class":215},[65,1709,862],{"class":211},[65,1711,865],{"class":71},[65,1713,868],{"class":215},[65,1715,1716,1718,1720,1722,1724,1726,1728,1730,1732,1734,1736,1738,1740,1742,1744,1746,1748,1750,1752,1754,1756],{"class":67,"line":303},[65,1717,873],{"class":215},[65,1719,747],{"class":71},[65,1721,808],{"class":215},[65,1723,880],{"class":74},[65,1725,843],{"class":215},[65,1727,885],{"class":74},[65,1729,747],{"class":215},[65,1731,890],{"class":74},[65,1733,843],{"class":215},[65,1735,885],{"class":74},[65,1737,62],{"class":215},[65,1739,899],{"class":74},[65,1741,843],{"class":215},[65,1743,885],{"class":74},[65,1745,757],{"class":215},[65,1747,908],{"class":74},[65,1749,843],{"class":215},[65,1751,885],{"class":74},[65,1753,761],{"class":215},[65,1755,917],{"class":74},[65,1757,814],{"class":215},[65,1759,1760,1762,1764],{"class":67,"line":315},[65,1761,924],{"class":215},[65,1763,927],{"class":211},[65,1765,851],{"class":215},[65,1767,1768,1770,1772,1774,1776],{"class":67,"line":326},[65,1769,873],{"class":215},[65,1771,747],{"class":71},[65,1773,808],{"class":215},[65,1775,940],{"class":74},[65,1777,943],{"class":215},[65,1779,1780],{"class":67,"line":338},[65,1781,948],{"class":215},[65,1783,1784],{"class":67,"line":344},[65,1785,1184],{"class":215},[65,1787,1788],{"class":67,"line":359},[65,1789,229],{"emptyLinePlaceholder":228},[65,1791,1792],{"class":67,"line":364},[65,1793,1794],{"class":260},"// One actor subscribes...\n",[65,1796,1797,1799,1801,1803,1805,1807,1809],{"class":67,"line":370},[65,1798,235],{"class":211},[65,1800,443],{"class":238},[65,1802,242],{"class":211},[65,1804,805],{"class":71},[65,1806,808],{"class":215},[65,1808,811],{"class":74},[65,1810,814],{"class":215},[65,1812,1813,1816,1818,1820,1822],{"class":67,"line":396},[65,1814,1815],{"class":215},"subscriber.",[65,1817,831],{"class":71},[65,1819,808],{"class":215},[65,1821,836],{"class":74},[65,1823,1824],{"class":215},", logErrors)\n",[65,1826,1827,1829,1832,1834],{"class":67,"line":401},[65,1828,373],{"class":211},[65,1830,1831],{"class":215}," subscriber.",[65,1833,966],{"class":71},[65,1835,969],{"class":215},[65,1837,1838],{"class":67,"line":407},[65,1839,229],{"emptyLinePlaceholder":228},[65,1841,1842,1844,1847,1849,1851,1853,1855,1858,1860,1862,1864,1866],{"class":67,"line":438},[65,1843,235],{"class":211},[65,1845,1846],{"class":238}," inbox",[65,1848,242],{"class":211},[65,1850,1831],{"class":215},[65,1852,1225],{"class":71},[65,1854,808],{"class":215},[65,1856,1857],{"class":238},"APP_SLUG",[65,1859,1233],{"class":215},[65,1861,1236],{"class":71},[65,1863,808],{"class":215},[65,1865,390],{"class":74},[65,1867,814],{"class":215},[65,1869,1870,1873,1875,1877,1879],{"class":67,"line":466},[65,1871,1872],{"class":215},"inbox.",[65,1874,1250],{"class":71},[65,1876,808],{"class":215},[65,1878,332],{"class":74},[65,1880,814],{"class":215},[65,1882,1883,1885,1887,1889,1891,1893,1895,1897,1899],{"class":67,"line":635},[65,1884,1872],{"class":215},[65,1886,831],{"class":71},[65,1888,808],{"class":215},[65,1890,332],{"class":74},[65,1892,839],{"class":215},[65,1894,1280],{"class":842},[65,1896,257],{"class":215},[65,1898,848],{"class":211},[65,1900,851],{"class":215},[65,1902,1903,1905,1907,1909,1911],{"class":67,"line":648},[65,1904,1291],{"class":215},[65,1906,350],{"class":71},[65,1908,808],{"class":215},[65,1910,1298],{"class":74},[65,1912,1301],{"class":215},[65,1914,1915],{"class":67,"line":657},[65,1916,341],{"class":215},[65,1918,1919],{"class":67,"line":666},[65,1920,229],{"emptyLinePlaceholder":228},[65,1922,1924],{"class":67,"line":1923},25,[65,1925,1926],{"class":260},"// ...and a different actor publishes\n",[65,1928,1930,1932,1934,1936,1938,1940,1942],{"class":67,"line":1929},26,[65,1931,235],{"class":211},[65,1933,412],{"class":238},[65,1935,242],{"class":211},[65,1937,805],{"class":71},[65,1939,808],{"class":215},[65,1941,1424],{"class":74},[65,1943,814],{"class":215},[65,1945,1947,1949,1951,1953,1955],{"class":67,"line":1946},27,[65,1948,1451],{"class":215},[65,1950,831],{"class":71},[65,1952,808],{"class":215},[65,1954,836],{"class":74},[65,1956,1824],{"class":215},[65,1958,1960,1962,1964,1966],{"class":67,"line":1959},28,[65,1961,373],{"class":211},[65,1963,1433],{"class":215},[65,1965,966],{"class":71},[65,1967,969],{"class":215},[65,1969,1971],{"class":67,"line":1970},29,[65,1972,229],{"emptyLinePlaceholder":228},[65,1974,1976,1978,1980,1982,1984,1986,1988,1990,1992,1994,1996,1998,2000,2003,2005],{"class":67,"line":1975},30,[65,1977,1451],{"class":215},[65,1979,1225],{"class":71},[65,1981,808],{"class":215},[65,1983,1857],{"class":238},[65,1985,1233],{"class":215},[65,1987,1236],{"class":71},[65,1989,808],{"class":215},[65,1991,390],{"class":74},[65,1993,1233],{"class":215},[65,1995,1470],{"class":71},[65,1997,808],{"class":215},[65,1999,332],{"class":74},[65,2001,2002],{"class":215},", { text: ",[65,2004,1485],{"class":74},[65,2006,393],{"class":215},[54,2008,2010],{"className":989,"code":2009,"filename":991,"language":992,"meta":60,"style":60},"import asyncio\n\nfrom nolag import NoLag\n\nAPP_SLUG = 'my-app-a3f9'  # the slug returned when you created the app\n\n\n# Surface broker errors: subscribe and emit never raise.\n# Broker errors are NoLagServerError; str(err) includes code, topic and hint.\ndef handle_error(err):\n    print(f'NoLag error: {err}')\n\n\ndef handle_message(data, meta):\n    print('Received:', data)\n\n\nasync def main():\n    # One actor subscribes...\n    subscriber = NoLag('subscriber_access_token')\n    subscriber.on('error', handle_error)\n    await subscriber.connect()\n\n    inbox = subscriber.set_app(APP_SLUG).set_room('general')\n    await inbox.subscribe('messages')\n    inbox.on('messages', handle_message)\n\n    # ...and a different actor publishes\n    publisher = NoLag('publisher_access_token')\n    publisher.on('error', handle_error)\n    await publisher.connect()\n\n    await publisher.set_app(APP_SLUG).set_room('general').emit('messages', {'text': 'Hello, World!'})\n\n    await asyncio.sleep(1)  # give the message time to arrive\n    publisher.disconnect()\n    subscriber.disconnect()\n\n\nasyncio.run(main())\n",[62,2011,2012,2017,2021,2025,2029,2034,2038,2042,2047,2051,2055,2059,2063,2067,2071,2075,2079,2083,2088,2093,2098,2103,2108,2112,2117,2122,2127,2131,2136,2141,2146,2152,2157,2163,2168,2174,2180,2186,2191,2196],{"__ignoreMap":60},[65,2013,2014],{"class":67,"line":68},[65,2015,2016],{},"import asyncio\n",[65,2018,2019],{"class":67,"line":225},[65,2020,229],{"emptyLinePlaceholder":228},[65,2022,2023],{"class":67,"line":232},[65,2024,999],{},[65,2026,2027],{"class":67,"line":264},[65,2028,229],{"emptyLinePlaceholder":228},[65,2030,2031],{"class":67,"line":269},[65,2032,2033],{},"APP_SLUG = 'my-app-a3f9'  # the slug returned when you created the app\n",[65,2035,2036],{"class":67,"line":275},[65,2037,229],{"emptyLinePlaceholder":228},[65,2039,2040],{"class":67,"line":281},[65,2041,229],{"emptyLinePlaceholder":228},[65,2043,2044],{"class":67,"line":303},[65,2045,2046],{},"# Surface broker errors: subscribe and emit never raise.\n",[65,2048,2049],{"class":67,"line":315},[65,2050,1027],{},[65,2052,2053],{"class":67,"line":326},[65,2054,1032],{},[65,2056,2057],{"class":67,"line":338},[65,2058,1037],{},[65,2060,2061],{"class":67,"line":344},[65,2062,229],{"emptyLinePlaceholder":228},[65,2064,2065],{"class":67,"line":359},[65,2066,229],{"emptyLinePlaceholder":228},[65,2068,2069],{"class":67,"line":364},[65,2070,1344],{},[65,2072,2073],{"class":67,"line":370},[65,2074,1349],{},[65,2076,2077],{"class":67,"line":396},[65,2078,229],{"emptyLinePlaceholder":228},[65,2080,2081],{"class":67,"line":401},[65,2082,229],{"emptyLinePlaceholder":228},[65,2084,2085],{"class":67,"line":407},[65,2086,2087],{},"async def main():\n",[65,2089,2090],{"class":67,"line":438},[65,2091,2092],{},"    # One actor subscribes...\n",[65,2094,2095],{"class":67,"line":466},[65,2096,2097],{},"    subscriber = NoLag('subscriber_access_token')\n",[65,2099,2100],{"class":67,"line":635},[65,2101,2102],{},"    subscriber.on('error', handle_error)\n",[65,2104,2105],{"class":67,"line":648},[65,2106,2107],{},"    await subscriber.connect()\n",[65,2109,2110],{"class":67,"line":657},[65,2111,229],{"emptyLinePlaceholder":228},[65,2113,2114],{"class":67,"line":666},[65,2115,2116],{},"    inbox = subscriber.set_app(APP_SLUG).set_room('general')\n",[65,2118,2119],{"class":67,"line":1923},[65,2120,2121],{},"    await inbox.subscribe('messages')\n",[65,2123,2124],{"class":67,"line":1929},[65,2125,2126],{},"    inbox.on('messages', handle_message)\n",[65,2128,2129],{"class":67,"line":1946},[65,2130,229],{"emptyLinePlaceholder":228},[65,2132,2133],{"class":67,"line":1959},[65,2134,2135],{},"    # ...and a different actor publishes\n",[65,2137,2138],{"class":67,"line":1970},[65,2139,2140],{},"    publisher = NoLag('publisher_access_token')\n",[65,2142,2143],{"class":67,"line":1975},[65,2144,2145],{},"    publisher.on('error', handle_error)\n",[65,2147,2149],{"class":67,"line":2148},31,[65,2150,2151],{},"    await publisher.connect()\n",[65,2153,2155],{"class":67,"line":2154},32,[65,2156,229],{"emptyLinePlaceholder":228},[65,2158,2160],{"class":67,"line":2159},33,[65,2161,2162],{},"    await publisher.set_app(APP_SLUG).set_room('general').emit('messages', {'text': 'Hello, World!'})\n",[65,2164,2166],{"class":67,"line":2165},34,[65,2167,229],{"emptyLinePlaceholder":228},[65,2169,2171],{"class":67,"line":2170},35,[65,2172,2173],{},"    await asyncio.sleep(1)  # give the message time to arrive\n",[65,2175,2177],{"class":67,"line":2176},36,[65,2178,2179],{},"    publisher.disconnect()\n",[65,2181,2183],{"class":67,"line":2182},37,[65,2184,2185],{},"    subscriber.disconnect()\n",[65,2187,2189],{"class":67,"line":2188},38,[65,2190,229],{"emptyLinePlaceholder":228},[65,2192,2194],{"class":67,"line":2193},39,[65,2195,229],{"emptyLinePlaceholder":228},[65,2197,2199],{"class":67,"line":2198},40,[65,2200,2201],{},"asyncio.run(main())\n",[54,2203,2205],{"className":1067,"code":2204,"filename":1069,"language":104,"meta":60,"style":60},"package main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"time\"\n\n    nolag \"github.com/NoLagApp/go-sdk\"\n)\n\nconst appSlug = \"my-app-a3f9\" // the slug returned when you created the app\n\nfunc main() {\n    // Surface broker errors: Subscribe and Emit do not return them\n    logErrors := func(err *nolag.ServerError) {\n        log.Printf(\"NoLag %s (%d) on %s: %s\", err.Name, err.Code, err.Topic, err.Hint)\n    }\n\n    // One actor subscribes...\n    subscriber := nolag.New(\"subscriber_access_token\")\n    subscriber.OnError(logErrors)\n    if err := subscriber.Connect(); err != nil {\n        log.Fatal(err)\n    }\n    defer subscriber.Close()\n\n    inbox := subscriber.SetApp(appSlug).SetRoom(\"general\")\n    inbox.Subscribe(\"messages\", func(data any, meta nolag.MessageMeta) {\n        fmt.Println(\"Received:\", data)\n    })\n\n    // ...and a different actor publishes\n    publisher := nolag.New(\"publisher_access_token\")\n    publisher.OnError(logErrors)\n    if err := publisher.Connect(); err != nil {\n        log.Fatal(err)\n    }\n    defer publisher.Close()\n\n    publisher.SetApp(appSlug).SetRoom(\"general\").Emit(\"messages\", map[string]string{\"text\": \"Hello, World!\"})\n\n    time.Sleep(time.Second) // give the message time to arrive\n}\n",[62,2206,2207,2211,2215,2219,2223,2227,2232,2236,2240,2244,2248,2253,2257,2261,2266,2271,2275,2279,2283,2288,2293,2298,2303,2307,2311,2316,2320,2325,2330,2335,2339,2343,2348,2353,2358,2363,2367,2371,2376,2380,2385,2390,2396],{"__ignoreMap":60},[65,2208,2209],{"class":67,"line":68},[65,2210,1076],{},[65,2212,2213],{"class":67,"line":225},[65,2214,229],{"emptyLinePlaceholder":228},[65,2216,2217],{"class":67,"line":232},[65,2218,1085],{},[65,2220,2221],{"class":67,"line":264},[65,2222,1090],{},[65,2224,2225],{"class":67,"line":269},[65,2226,1095],{},[65,2228,2229],{"class":67,"line":275},[65,2230,2231],{},"    \"time\"\n",[65,2233,2234],{"class":67,"line":281},[65,2235,229],{"emptyLinePlaceholder":228},[65,2237,2238],{"class":67,"line":303},[65,2239,1104],{},[65,2241,2242],{"class":67,"line":315},[65,2243,814],{},[65,2245,2246],{"class":67,"line":326},[65,2247,229],{"emptyLinePlaceholder":228},[65,2249,2250],{"class":67,"line":338},[65,2251,2252],{},"const appSlug = \"my-app-a3f9\" // the slug returned when you created the app\n",[65,2254,2255],{"class":67,"line":344},[65,2256,229],{"emptyLinePlaceholder":228},[65,2258,2259],{"class":67,"line":359},[65,2260,1117],{},[65,2262,2263],{"class":67,"line":364},[65,2264,2265],{},"    // Surface broker errors: Subscribe and Emit do not return them\n",[65,2267,2268],{"class":67,"line":370},[65,2269,2270],{},"    logErrors := func(err *nolag.ServerError) {\n",[65,2272,2273],{"class":67,"line":396},[65,2274,1146],{},[65,2276,2277],{"class":67,"line":401},[65,2278,1170],{},[65,2280,2281],{"class":67,"line":407},[65,2282,229],{"emptyLinePlaceholder":228},[65,2284,2285],{"class":67,"line":438},[65,2286,2287],{},"    // One actor subscribes...\n",[65,2289,2290],{"class":67,"line":466},[65,2291,2292],{},"    subscriber := nolag.New(\"subscriber_access_token\")\n",[65,2294,2295],{"class":67,"line":635},[65,2296,2297],{},"    subscriber.OnError(logErrors)\n",[65,2299,2300],{"class":67,"line":648},[65,2301,2302],{},"    if err := subscriber.Connect(); err != nil {\n",[65,2304,2305],{"class":67,"line":657},[65,2306,1165],{},[65,2308,2309],{"class":67,"line":666},[65,2310,1170],{},[65,2312,2313],{"class":67,"line":1923},[65,2314,2315],{},"    defer subscriber.Close()\n",[65,2317,2318],{"class":67,"line":1929},[65,2319,229],{"emptyLinePlaceholder":228},[65,2321,2322],{"class":67,"line":1946},[65,2323,2324],{},"    inbox := subscriber.SetApp(appSlug).SetRoom(\"general\")\n",[65,2326,2327],{"class":67,"line":1959},[65,2328,2329],{},"    inbox.Subscribe(\"messages\", func(data any, meta nolag.MessageMeta) {\n",[65,2331,2332],{"class":67,"line":1970},[65,2333,2334],{},"        fmt.Println(\"Received:\", data)\n",[65,2336,2337],{"class":67,"line":1975},[65,2338,1151],{},[65,2340,2341],{"class":67,"line":2148},[65,2342,229],{"emptyLinePlaceholder":228},[65,2344,2345],{"class":67,"line":2154},[65,2346,2347],{},"    // ...and a different actor publishes\n",[65,2349,2350],{"class":67,"line":2159},[65,2351,2352],{},"    publisher := nolag.New(\"publisher_access_token\")\n",[65,2354,2355],{"class":67,"line":2165},[65,2356,2357],{},"    publisher.OnError(logErrors)\n",[65,2359,2360],{"class":67,"line":2170},[65,2361,2362],{},"    if err := publisher.Connect(); err != nil {\n",[65,2364,2365],{"class":67,"line":2176},[65,2366,1165],{},[65,2368,2369],{"class":67,"line":2182},[65,2370,1170],{},[65,2372,2373],{"class":67,"line":2188},[65,2374,2375],{},"    defer publisher.Close()\n",[65,2377,2378],{"class":67,"line":2193},[65,2379,229],{"emptyLinePlaceholder":228},[65,2381,2382],{"class":67,"line":2198},[65,2383,2384],{},"    publisher.SetApp(appSlug).SetRoom(\"general\").Emit(\"messages\", map[string]string{\"text\": \"Hello, World!\"})\n",[65,2386,2388],{"class":67,"line":2387},41,[65,2389,229],{"emptyLinePlaceholder":228},[65,2391,2393],{"class":67,"line":2392},42,[65,2394,2395],{},"    time.Sleep(time.Second) // give the message time to arrive\n",[65,2397,2399],{"class":67,"line":2398},43,[65,2400,1184],{},[18,2402,2404],{"id":2403},"troubleshooting","Troubleshooting",[14,2406,2407,2410,2411,2413,2414,2416,2417,2420,2421,885],{},[124,2408,2409],{},"Nothing arrives, and nothing errors."," Almost always one of three things: the\nroom does not exist, the app slug is missing its random suffix, or the same actor\nis publishing and subscribing (publishers never receive their own messages).\nAttach the ",[62,2412,747],{}," handler from Step 3 and look for ",[62,2415,716],{},", then check\nthe slug against ",[62,2418,2419],{},"GET /apps"," and the room against ",[62,2422,2423],{},"GET /apps/{appId}/rooms",[14,2425,2426,2431,2432,2435],{},[124,2427,2428,2430],{},[62,2429,716],{}," on a topic you did create."," Topics resolve as\n",[62,2433,2434],{},"app-slug/room-slug/topic-name",", and the topic name must be in the app's topic\nlist. A room's own topic list is not consulted for access, so confirm the topic\nis listed on the app.",[14,2437,732,2438,2442],{},[30,2439,2441],{"href":2440},"/docs/api-reference/errors","Error Reference"," for the full list of codes.",[18,2444,2446],{"id":2445},"next-steps","Next Steps",[23,2448,2449,2455,2461,2467],{},[26,2450,2451],{},[30,2452,2454],{"href":2453},"/docs/concepts/topics","Learn about Topics & Pub/Sub",[26,2456,2457],{},[30,2458,2460],{"href":2459},"/docs/concepts/presence","Understand Presence Tracking",[26,2462,2463],{},[30,2464,2466],{"href":2465},"/docs/concepts/qos","Configure Quality of Service",[26,2468,2469],{},[30,2470,2472],{"href":2471},"/docs/sdks/javascript","Full JavaScript SDK Reference",[2474,2475,2476],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":60,"searchDepth":225,"depth":225,"links":2478},[2479,2480,2481,2482,2483,2484,2485,2486,2487],{"id":20,"depth":225,"text":21},{"id":45,"depth":225,"text":46},{"id":113,"depth":225,"text":114},{"id":740,"depth":225,"text":741},{"id":1187,"depth":225,"text":1188},{"id":1395,"depth":225,"text":1396},{"id":1627,"depth":225,"text":1628},{"id":2403,"depth":225,"text":2404},{"id":2445,"depth":225,"text":2446},"Get started with NoLag in 5 minutes. Learn how to connect, subscribe to topics, and publish messages.","md",{},"/docs/getting-started",{"title":5,"description":2488},"docs/getting-started","L-DyMN_HjBhDUNKVcHrn_bwJlRO34jF44JlFQeX3H7E",1789869419752]