---
title: Node.js quickstart
description: Install @minip2p/node, connect to a peer, and measure a Ping RTT.
---

`@minip2p/node` requires Node.js 24 or newer and uses ES modules.

## Install

```bash
mkdir minip2p-quickstart
cd minip2p-quickstart
npm init -y
npm install @minip2p/node
```

## Run two peers

Open two terminals in this directory. In the first, create `listener.mjs`:

```ts
import { Minip2p, generateSecretKey } from "@minip2p/node";

const endpoint = Minip2p.create({
  agentVersion: "my-app/0.1.0",
  secretKey: generateSecretKey(),
  transports: {
    quic: { listen: ["/ip4/127.0.0.1/udp/4001/quic-v1"] },
  },
});

console.log("listening at");
console.log(endpoint.listenAddrs()[0]);
```

Run it and leave it running:

```bash
node listener.mjs
```

It prints an address like this:

```text
listening at
/ip4/127.0.0.1/udp/4001/quic-v1/p2p/12D3KooW...
```

Copy the complete address, including `/p2p/<peer-id>`. In the second terminal,
create `connect.mjs`:

```ts
import { Minip2p, generateSecretKey } from "@minip2p/node";

const remoteAddress = process.argv[2];
if (remoteAddress === undefined) {
  throw new Error("pass a peer multiaddress");
}

const endpoint = Minip2p.create({
  agentVersion: "my-app/0.1.0",
  secretKey: generateSecretKey(),
});

try {
  const connected = await endpoint.connectAddr(remoteAddress, {
    timeoutMs: 10_000,
  });
  await endpoint.waitPeerReady(connected.peerId, { timeoutMs: 10_000 });
  const rttMs = await endpoint.ping(connected.peerId, { timeoutMs: 5_000 });

  console.log(`connected over ${connected.path.kind}`);
  console.log(`ping: ${rttMs} ms`);
} finally {
  endpoint.close();
}
```

Run it with the address from the listener:

```bash
node connect.mjs /ip4/127.0.0.1/udp/4001/quic-v1/p2p/12D3KooW...
```

The second terminal prints output like this:

```text
connected over directDialed
ping: 4 ms
```

`connectAddr` returns the first usable path. `waitPeerReady` then waits for the
peer's Identify information before the application starts protocol work.

This listener accepts connections only from the same machine. To let a phone or
another computer connect, bind a LAN interface instead, such as
`/ip4/192.168.1.42/udp/4001/quic-v1`, and give it the printed address.

`generateSecretKey()` creates a new peer identity on every run. Load the same
secret bytes from protected storage when the peer needs a stable ID.

## Keep a service running

A running endpoint keeps the Node.js process alive. Long-running applications
should close it during shutdown. See [Endpoint lifecycle](/typescript/lifecycle)
for signal handling and identity persistence.

Next: [Connections and streams](/typescript/connections-and-streams) or
[Networking and events](/typescript/networking-and-events).
