Build offline peer-to-peer messaging

Last updated

Send and receive messages device-to-device with no server in the path. This guide covers how inbound and outbound messaging works on the mesh, how DORS relays across hops, and how encryption and delivery guarantees come for free.

What you will build

A messaging flow that subscribes to inbound messages, joins the mesh, and sends encrypted messages to peers, relayed across up to 8 hops with acknowledgment and retry, all with no server, no broker, and no DNS.

How messaging works on the mesh

On the internet, sending a message means handing it to infrastructure: a server accepts it, stores it, and forwards it. Offline messaging removes the middle entirely. A message goes from one device to another directly, and if the two are not in radio range, other devices relay it.

That relay is the DORS mesh: BLE, WiFi Direct, and internet running concurrently with automatic failover, carrying messages across up to 8 hops with acknowledgment, retry, and deduplication. Every session is encrypted with MLS (RFC 9420) by default, so confidentiality is the baseline, not an add-on.

Prerequisites

Steps

1
SUBSCRIBE TO INBOUND MESSAGES

Register a message_received handler on the protocol before joining the mesh. Every delivered message surfaces through this one event, with the sender identity and the content, so your UI can render conversations as they arrive.

2
JOIN THE MESH

Call start(). The device advertises itself and begins discovering peers over BLE, WiFi Direct, and internet at once. DORS chooses transports and fails over automatically, so a link dropping mid-conversation does not drop the conversation.

3
SEND A MESSAGE

Call sendMessage with a recipient, content, and a priority. Priority lets urgent traffic move ahead of bulk traffic on a constrained link. The message is MLS-encrypted end to end before it leaves the device.

4
LET DORS DO THE ROUTING

If the recipient is not in direct radio range, DORS relays the message hop by hop across up to 8 hops, with acknowledgment, retry, and deduplication built in. You do not write routing code; it is the default path.

Sending a message

The send path is the same one from the quickstart: subscribe to message_received, join the mesh, then call sendMessage() with a recipient, content, and priority.

TypeScript
// npm install @offline-protocol/mesh-sdk
import { OfflineProtocol, MessagePriority } from '@offline-protocol/mesh-sdk';

const protocol = new OfflineProtocol({ appId: 'my-app', userId: 'user123' });

protocol.on('message_received', (event) =>
  console.log(`From ${event.sender}: ${event.content}`));

await protocol.start();

await protocol.sendMessage({
  recipient: 'user456',
  content: 'Hello!',
  priority: MessagePriority.High,
});

Delivery receipts, message metadata, and the full event and option set are in the API reference. When in doubt, follow the documentation rather than guessing at method names.

What you get

A messaging layer that keeps working when the internet is down: encrypted by default, delivered across the mesh with acknowledgment and retry, and prioritized so urgent traffic moves first. Pair it with OfflineID verification to know exactly who you are talking to before a message is read.

Next steps

Offline messaging FAQ

Is there a server anywhere in the message path?

No. Messaging is fully peer-to-peer. Messages travel device-to-device over the mesh and relay through other devices when needed. There is no server, no broker, and no DNS in the path, so it works with the internet entirely offline.

How are messages encrypted?

Every session is encrypted by default with MLS (RFC 9420), the same standard used for large-group messaging security, with key rotation across peers. You do not turn encryption on; it is the default path.

What happens if the recipient is out of direct range?

DORS relays the message across up to 8 hops through other devices, with acknowledgment, retry, and deduplication. A peer several hops away, with no direct radio contact, still receives the message.

Can I prioritize urgent messages?

Yes. Each message carries a priority, so time-sensitive traffic can move ahead of bulk traffic on a constrained link. See the API reference for the full set of options.

Messaging that survives the internet going down. No server. No broker.

Read the docs All guides