> For the complete documentation index, see [llms.txt](https://dnotifier.gitbook.io/product-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dnotifier.gitbook.io/product-docs/platform-guides/nodejs.md).

# Node.js

Use the DNotifier JavaScript SDK in **Node.js** for backend services, workers, CLI tools, and server-side realtime or AI integrations. Node has no built-in WebSocket client — you must inject one when using `transport: "ws"`.

## Requirements

| Requirement           | Version / notes                                                          |
| --------------------- | ------------------------------------------------------------------------ |
| Node.js               | 18 or later recommended                                                  |
| npm / yarn / pnpm     | Any recent version                                                       |
| DNotifier credentials | `appId` and `secret` from [app.dnotifier.com](https://app.dnotifier.com) |

→ [Install — JavaScript / TypeScript](/product-docs/getting-started/installation/javascript-typescript.md)

***

## Install

```bash
npm install @dnotifier-realtime/dnotifier
```

For WebSocket transport, also install the `ws` package:

```bash
npm install ws
```

{% hint style="info" %}
The `ws` package is a **peer-style dependency** for Node WebSocket use. It is listed as a dependency of the SDK but you import and pass it explicitly as `WebSocketImpl`.
{% endhint %}

***

## WebSocketImpl and the `ws` package

Browsers expose `WebSocket` globally. **Node.js does not.** The SDK's `WebsocketTransport` accepts a constructor via `WebSocketImpl`:

```js
import WebSocket from "ws";
import { DNotifier } from "@dnotifier-realtime/dnotifier";

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "ws",
  userId: "backend-worker-1",
  WebSocketImpl: WebSocket,
  onConnected: () => console.log("Connected"),
  onMessage: (msg) => console.log(msg.payload.toJSON()),
  onDisconnected: () => console.log("Disconnected"),
});

await notifier.connect();
```

### Why injection?

* Keeps the SDK bundle small in browser builds (no `ws` bundled for the web)
* Lets you use a compatible WebSocket implementation in tests or custom environments
* Matches Node ESM/CJS patterns — you control the import

### What happens without WebSocketImpl?

If `transport: "ws"` and no `WebSocketImpl` is passed, the SDK throws:

```
No WebSocket implementation provided
```

{% hint style="warning" %}
`WebSocketImpl` is **required** for `transport: "ws"` in Node. For AI, RAG, and workflows only, use `transport: "http"` — no WebSocket package needed.
{% endhint %}

***

## HTTP transport (no WebSocket)

Server-side AI assistants, cron jobs, and workflow runners typically use HTTP:

```js
import { DNotifier } from "@dnotifier-realtime/dnotifier";

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "http",
  userId: "api-server",
  onConnected: () => {},
  onMessage: () => {},
  onDisconnected: () => {},
});

await notifier.connect();

const response = await notifier.sendAI({
  senderId: "api-server",
  message: { text: "Summarize this ticket." },
});
```

→ [Choose your transport](/product-docs/getting-started/choose-transport.md)

***

## ESM and CommonJS

The package is ESM-first (`"type": "module"`):

```js
import { DNotifier } from "@dnotifier-realtime/dnotifier";
import WebSocket from "ws";
```

Legacy CommonJS:

```js
const { DNotifier } = require("@dnotifier-realtime/dnotifier");
const WebSocket = require("ws");
```

TypeScript types ship in `dist/dnotifier.d.ts` — no separate `@types` package.

***

## Environment variables

Load credentials from the environment, never hard-code secrets:

```js
const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "ws",
  userId: process.env.DNOTIFIER_USER_ID ?? "service-account",
  WebSocketImpl: WebSocket,
  onConnected: () => {},
  onMessage: () => {},
  onDisconnected: () => {},
});
```

Use `.env` with `dotenv` in development; use your host's secret manager in production.

→ [Credentials & environment](/product-docs/getting-started/credentials.md)

***

## Typical Node.js architectures

### Realtime gateway service

A long-running Node process holds a WebSocket connection per logical user or device:

| Piece        | Transport | Role                              |
| ------------ | --------- | --------------------------------- |
| Chat relay   | `ws`      | Forward messages between user IDs |
| AI API route | `http`    | `sendAI`, `search`, `runWorkflow` |

Many teams run **two SDK instances** — one per transport — sharing the same `appId` and `secret`.

### Worker / queue consumer

A worker connects as a service `userId`, receives jobs via `onMessage`, and responds with `send()`:

```js
onMessage: async (msg) => {
  const job = msg.payload.toJSON();
  if (job?.type === "process") {
    await notifier.send({
      senderId: "worker-1",
      receiverId: msg.metadata.sender,
      data: { type: "result", status: "done" },
    });
  }
},
```

### Serverless note

{% hint style="warning" %}
WebSocket connections are **persistent**. Short-lived serverless functions (AWS Lambda, Cloud Functions) are a poor fit for `transport: "ws"`. Use `transport: "http"` in serverless handlers, or run a dedicated realtime service on a long-lived host.
{% endhint %}

***

## Custom WebSocket URL

Override the WebSocket URL only when DNotifier has provided a dedicated host:

```js
const notifier = new DNotifier({
  // ...
  url: "wss://YOUR_HOST",
  WebSocketImpl: WebSocket,
});
```

→ [Endpoints & custom URL](/product-docs/reference/endpoints.md)

***

## Graceful shutdown

Close the socket when your process exits:

```js
process.on("SIGTERM", async () => {
  notifier.disconnect();
  process.exit(0);
});
```

→ [Connection lifecycle](/product-docs/realtime-communication/connection-lifecycle.md)

***

## Debugging tips

| Symptom                                | Check                                  |
| -------------------------------------- | -------------------------------------- |
| `No WebSocket implementation provided` | Add `WebSocketImpl: WebSocket`         |
| `Authentication Failed`                | Verify `appId` / `secret` in dashboard |
| Connection drops under load            | Review plan limits and chunk sizes     |
| `WebSocket not connected` on `send()`  | Await `connect()` before sending       |

→ [Debugging](/product-docs/operations/debugging.md) · [Troubleshooting](/product-docs/operations/troubleshooting.md)

***

## Next steps

* [Your first connection — JavaScript / TypeScript](/product-docs/getting-started/first-connection/javascript-typescript.md)
* [Browser platform guide](/product-docs/platform-guides/browser.md)
* [Production checklist](/product-docs/operations/production-checklist.md)
