Introduction
WebSocket is a protocol that enables full-duplex, persistent connections between client and server over a single TCP socket. Unlike plain HTTP where the client must request and the server responds, a WebSocket connection stays open and both sides can send messages at any time. This makes it perfect for chat apps, live dashboards, multiplayer games, and any feature that needs real-time updates.
In this lesson you will build the smallest possible WebSocket setup: a server in Node.js using the popular `ws` library, and a browser client that connects to it and exchanges a few messages. No frameworks, no databases — just the raw protocol so you understand what is happening under the hood.
Setting Up the Project
Create a new folder for the project and initialize it. You need Node.js installed (version 18 or later is fine).
The `ws` package is a fast, widely-used WebSocket implementation for Node.js. After `npm install`, you will have a `node_modules` folder and a `package.json` that lists `ws` as a dependency.
Writing the Server
Create a file called `server.js`. The server does three things: import the library, create a WebSocket server bound to a port, and define what happens on connection and on incoming messages.
The `connection` event fires once per client that connects. The callback receives a `ws` object representing that individual client's socket. Inside the callback you attach a `message` listener. When a message arrives, `data` is a Buffer by default, so `toString()` converts it to plain text. The server then echoes the message back prefixed with `Server echo:`.
Run the server with `node server.js`. You should see the "listening" log line and nothing else until a client connects.
Writing the Browser Client
Create a file called `index.html`. A browser can open a WebSocket connection using the built-in `WebSocket` global — no library needed on the client side.
The `open` event fires when the handshake completes. After that, `ws.send('text')` sends a string message to the server. The server's echoed reply arrives as a `message` event whose `event.data` is the string the server sent.
Testing It End to End
Start the server with `node server.js`. Then open `index.html` in your browser (you can double-click it, or use a tool like `npx serve`). In the terminal you should see "A client connected" the moment the page loads. Type something in the input box and click Send. The browser log will show your message prefixed with `Server echo:`, and the terminal will log each message the server receives.
Common Mistakes
Forgetting `data.toString()` on the server side gives you a raw Buffer object instead of the readable string the client sent. Forgetting the `ws://` protocol prefix in the browser URL will throw a syntax error because the `WebSocket` constructor requires the full URL including scheme. If the server is not running, the browser's `open` event will never fire and you will see no log entries — always check the terminal first when nothing happens.
Summary
You now have a working WebSocket echo server and a browser client. The server uses `ws` to listen on port 8080, accepts connections, and echoes back any message it receives. The client opens the connection with `new WebSocket('ws://localhost:8080')` and uses `send` and `message` events to communicate. This pattern — one server, many connected clients, bidirectional messages — is the foundation every real-time feature builds on.
Lesson Checkpoint
Review what you learned and get feedback on your work.