Skip to main content
Create one OfflineProtocol instance for the app process. Register event handlers synchronously after construction, request platform permissions, then call start(). The quickstart contains a complete messaging module. Reuse that instance for documents and service handlers.

Startup

  1. Construct the instance with a stable appId and profile.
  2. Attach receive, delivery, identity and diagnostic handlers.
  3. Obtain platform permissions.
  4. Await start() and handle failure.
  5. Read localAddress() or observe identity_ready.
  6. Wait for discovery and the required session before starting the workflow.
The constructor subscribes to native events. Most events are not replayed to listeners attached later. In particular, attach the application’s durable receive handler before startup rather than after the UI mounts.

Running

Keep the protocol alive while operations are pending. Track message_delivered and message_failed as terminal send outcomes; keep deferred, retrying and undeliverable messages pending. Read getState() using the exported ProtocolState string enum. DataStore and MeshServices use the live native protocol instance. Creating either helper does not start another protocol or grant access to a peer.

Background execution

OS background policies affect transports and JavaScript execution. Qualify the actual device and release build. Android’s optional registerMeshWakeTask requires both the manifest opt-in and a handler registered at module scope; the application restores configuration and receive handlers before restarting the mesh. See production deployment.

Shutdown

Stop producing new application work, persist it, and await stop() before destroy(). Do not destroy immediately after a send and assume an acknowledgment has been processed. Logout and state deletion are separate application decisions.

Shared helpers

DataStore requires encryption and initialized MLS storage. start() can warn rather than throw when MLS initialization fails: check that localAddress() is non-null before sending. Media transfers settle on media_sent or media_send_failed. Use stop() for a restartable stop. destroy() removes listeners and the native subscription: construct a new instance and re-register listeners afterward. On logout, call wipePersistedState() when deleting the device identity is intended, and clear application-owned storage separately. iOS Keychain state otherwise survives reinstall.

Event replay boundaries

internet_session_superseded and mesh_stopped_by_user are held for late listeners. message_received, file_received and message_decryption_failed use a bounded inbound buffer of 256 events; the oldest is dropped when full. Replay runs asynchronously and handlers must tolerate duplicate delivery. This buffer is not durable application storage. Register receive handlers immediately after construction and persist the records your workflow needs.