Getting Started
Get up and running with NoLag in under 5 minutes.
Prerequisites
- A NoLag account (sign up free)
- Node.js 18+ (for the JavaScript SDK)
You create your app and access tokens in Step 2, so nothing else is needed up front.
Step 1: Install the SDK
Install the NoLag SDK for your preferred language:
npm install @nolag/js-sdkStep 2: Create an App, a Room, and Two Access Tokens
You need three kinds of thing:
- an app, a container for your rooms, carrying the list of topics it allows
- a room inside that app, the namespace your topics live in
- two actors, client identities whose access tokens authenticate the connections
Why two actors? A publishing actor never receives its own message, so one token that subscribes and then publishes hears nothing. This guide uses one actor to publish and another to subscribe.
In the dashboard:
- Log in to the NoLag Dashboard and create a project.
- Create an app inside the project, with
messagesin its topic list. - Add a room to the app, and note its slug.
- Open the Actors section, create two actors, and copy both access tokens.
Or over the REST API. This is the path to use from a script or an AI agent
that sets everything up on its own. The only bootstrap secret is a project-scoped
API key, created once in the dashboard;
everything else is an API call, through the SDK's NoLagApi client or plain
curl:
import { NoLagApi } from '@nolag/js-sdk'
const api = new NoLagApi(process.env.NOLAG_API_KEY) // nlg_live_...
// 1. Create an app and declare the topics it allows. The slug that comes back
// is not the one you sent (see the note below), so read it from the response.
const app = await api.apps.create({
name: 'My App',
slug: 'my-app',
topics: ['messages'],
})
console.log(app.slug) // e.g. "my-app-a3f9": this is what you pass to setApp()
// 2. Create a room in that app. Clients cannot subscribe to a room that does not exist.
await api.rooms.create(app.appId, { name: 'General', slug: 'general' })
// 3. Create two actors. Each access token is shown once; keep both.
const publisher = await api.actors.create({ name: 'Publisher', actorType: 'service' })
const subscriber = await api.actors.create({ name: 'Subscriber', actorType: 'user' })
console.log(publisher.accessToken, subscriber.accessToken)Save the tokens now. An actor's access token is only returned when the actor is created. It is never shown again.
App slugs always get a random suffix. NoLag appends four random characters to
every app slug to keep it unique within the project, so a requested slug of
my-app comes back as something like my-app-a3f9. Read the slug field from the
create response and pass that value to setApp(). Room slugs are different: they
are stored exactly as you supply them.
Rooms must exist before you subscribe. Rooms are never created implicitly.
Subscribing to a room that has not been created returns an unknown_topic error
(code 42940) instead of delivering messages. If you skip the error handler in
Step 3, this looks like total silence: connect(), subscribe(), and emit()
all appear to succeed and no message ever arrives.
See the REST API Reference for the full app, room, and actor endpoints.
Step 3: Connect to NoLag
Attach an error handler before you connect. Subscribe and publish calls do not
throw: the broker reports problems such as an unknown topic or a permission
refusal on the error event, so without a handler a misconfigured app simply
goes quiet. Broker errors arrive as NoLagServerError, with code, topic and
hint; transport failures arrive as a plain error.
This first client is the subscriber:
import { NoLag, NoLagServerError } from '@nolag/js-sdk'
// Create client and connect
const client = NoLag('subscriber_access_token')
// Attach this first: server-side errors arrive here, not as thrown exceptions
client.on('error', (err) => {
if (err instanceof NoLagServerError) {
console.error(`NoLag ${err.error} (${err.code}) on ${err.topic}: ${err.hint}`)
} else {
console.error('NoLag error:', err)
}
})
await client.connect()
console.log('Connected to NoLag!')Step 4: Subscribe to a Topic
Topics are channels for messages. Subscribe to receive messages published to a topic.
Pass the app slug exactly as the create response returned it, suffix included, and the slug of a room that already exists:
// Set up app and room, then subscribe.
// 'my-app-a3f9' is the slug returned when the app was created.
const room = client.setApp('my-app-a3f9').setRoom('general')
room.subscribe('messages')
// Listen for messages
room.on('messages', (data) => {
console.log('Received:', data)
})Step 5: Publish a Message
Publish from a second connection, authenticated with the publisher's token.
Publishers never receive their own messages, so an emit() on the connection
that subscribed in Step 4 would deliver nothing:
const publisher = NoLag('publisher_access_token')
await publisher.connect()
// Publish a message
publisher.setApp('my-app-a3f9').setRoom('general').emit('messages', {
text: 'Hello, World!',
sender: 'user-123',
timestamp: Date.now()
})Complete Example
Here's a complete example in your preferred language. It assumes the app, room, and two actors from Step 2 already exist. One actor subscribes and a different actor publishes, because publishers never receive their own messages.
import { NoLag, NoLagServerError } from '@nolag/js-sdk'
const APP_SLUG = 'my-app-a3f9' // the slug returned when you created the app
// Surface broker errors: subscribe and emit never throw
const logErrors = (err: Error) => {
if (err instanceof NoLagServerError) {
console.error(`NoLag ${err.error} (${err.code}) on ${err.topic}: ${err.hint}`)
} else {
console.error('NoLag error:', err)
}
}
// One actor subscribes...
const subscriber = NoLag('subscriber_access_token')
subscriber.on('error', logErrors)
await subscriber.connect()
const inbox = subscriber.setApp(APP_SLUG).setRoom('general')
inbox.subscribe('messages')
inbox.on('messages', (data) => {
console.log('Received:', data)
})
// ...and a different actor publishes
const publisher = NoLag('publisher_access_token')
publisher.on('error', logErrors)
await publisher.connect()
publisher.setApp(APP_SLUG).setRoom('general').emit('messages', { text: 'Hello, World!' })Troubleshooting
Nothing arrives, and nothing errors. Almost always one of three things: the
room does not exist, the app slug is missing its random suffix, or the same actor
is publishing and subscribing (publishers never receive their own messages).
Attach the error handler from Step 3 and look for unknown_topic, then check
the slug against GET /apps and the room against GET /apps/{appId}/rooms.
unknown_topic on a topic you did create. Topics resolve as
app-slug/room-slug/topic-name, and the topic name must be in the app's topic
list. A room's own topic list is not consulted for access, so confirm the topic
is listed on the app.
See the Error Reference for the full list of codes.