What Are the Two Transport Layers Used by BitChat? A Deep Dive Into the Hybrid Architecture

BitChat uses a dual-transport architecture combining Bluetooth Mesh Network for offline peer-to-peer communication and the Nostr Protocol for internet-based global messaging.

The open-source messaging application developed by permissionlesstech/bitchat implements a sophisticated hybrid network stack that eliminates single points of failure. By leveraging both local mesh networking and decentralized relay infrastructure, BitChat achieves offline resilience without sacrificing global reach. The following sections dissect each transport layer with reference to the actual Swift implementation and routing logic found in the source repository.

Bluetooth Mesh Network: The Offline Transport Layer

BitChat’s primary transport for local communication operates entirely without internet connectivity. This layer establishes direct device-to-device links using Bluetooth Low Energy (BLE) with advanced mesh capabilities.

Core Implementation in BLEService.swift

The Bluetooth functionality resides in bitchat/Services/BLE/BLEService.swift, which manages device discovery, connection handshakes, and packet transmission. The service implements the Noise protocol for encryption, ensuring all BLE communications remain private even across multiple hops.

// BLEService.swift – sending a packet
func send(_ packet: BitchatPacket, to peer: PeerID) {
    // Packet is already Noise-encrypted
    let data = packet.toBinaryData()
    peripheral.writeValue(data, for: characteristic, type: .withResponse)
}

Technical Specifications

The Bluetooth transport layer exhibits several distinct characteristics critical for mesh operation:

  • Multi-hop routing supporting up to 7 hops between devices, extending range beyond direct Bluetooth limits
  • Compact binary packets encrypted with the Noise protocol to minimize overhead while maintaining security
  • Automatic peer discovery with duty-cycled power management to preserve battery life during passive scanning
  • Adaptive power use that scales transmission strength based on proximity and signal quality

This architecture enables encrypted messaging in environments with no cellular or Wi-Fi coverage, such as remote locations or disaster scenarios.

Nostr Protocol: The Internet Transport Layer

When local mesh connections prove insufficient, BitChat falls back to the Nostr Protocol, a decentralized network of websocket relays that provides global message delivery without centralized servers.

Relay Management via NostrRelayManager.swift

The Nostr integration centers on bitchat/Nostr/NostrRelayManager.swift, which handles websocket connections, relay selection, and message forwarding. Unlike traditional client-server messaging, this transport routes encrypted payloads through public Nostr relays while preserving sender anonymity.

// NostrRelayManager.swift – sending over Nostr
func send(_ payload: ChatMessage, to pubKey: Data) {
    let envelope = PrivateEnvelope(message: payload, recipientKey: pubKey)
    let event = NostrEvent(kind: 1059, content: envelope.serialized)
    relayConnection?.send(.data(event.encode()), completionHandler: { _ in … })
}

Encryption and Event Structure

BitChat wraps messages in a custom private-envelope format using XChaCha20-Poly1305 encryption before insertion into Nostr events. These payloads transmit as kind-1059 events, a specific event type dedicated to encrypted direct messages within the Nostr ecosystem. The system supports location-based channels derived from geohash coordinates, enabling regional broadcasting without exposing precise GPS coordinates.

Additional protocol definitions reside in bitchat/Nostr/NostrProtocol.swift, which structures the Nostr-specific data types and event handling logic required for relay communication.

How BitChat Intelligently Routes Between Transport Layers

BitChat implements a smart routing algorithm that dynamically selects the optimal transport based on network availability, latency requirements, and privacy preferences.

Bluetooth-First Strategy

The application prioritizes BLE connections whenever possible due to lower latency and enhanced privacy. When BLEService.shared.isConnected(to: recipientID) returns true, messages transmit directly through the encrypted Bluetooth link. This path supports real-time chat, voice bursts, and file transfers without internet exposure.

// Prepare a chat payload
let payload = ChatMessage(text: "Hello, world!", channel: .local)

// Try Bluetooth first
if BLEService.shared.isConnected(to: recipientID) {
    BLEService.shared.send(payload, to: recipientID)
} else {
    // Fallback to Nostr
    NostrRelayManager.shared.send(payload, to: recipientPublicKey)
}

Nostr Fallback and Message Queuing

If no BLE route exists—such as when the recipient is out of Bluetooth range—the system automatically encrypts the payload using the private envelope format and forwards it via NostrRelayManager.shared. When both transports become unavailable simultaneously, BitChat queues messages locally and resumes delivery automatically upon reconnection to either network.

The routing intelligence is validated through bitchatTests/Services/MessageRouterTests.swift, which verifies correct transport selection under various network conditions and ensures message integrity across layer transitions.

Summary

  • BitChat transport layers consist of Bluetooth Mesh Network for offline local communication and Nostr Protocol for internet-based global delivery.
  • The Bluetooth layer in BLEService.swift uses Noise-encrypted BLE with multi-hop routing up to 7 hops, requiring no central infrastructure.
  • The Nostr layer in NostrRelayManager.swift routes XChaCha20-Poly1305 encrypted payloads through websocket relays using kind-1059 events.
  • Intelligent routing prioritizes Bluetooth for speed and privacy, falling back to Nostr for long-distance communication, with local queuing when offline.
  • Both transports operate without phone numbers, accounts, or centralized servers, maintaining user anonymity across all communication paths.

Frequently Asked Questions

Does BitChat require an internet connection to send messages?

No, BitChat does not require internet connectivity for local messaging. The Bluetooth Mesh Network transport enables direct peer-to-peer communication between nearby devices without any internet access. However, to reach recipients outside Bluetooth range, the application falls back to the Nostr Protocol which requires an internet connection to access public relays.

How does BitChat ensure message privacy across both transport layers?

Both transport layers implement end-to-end encryption using distinct but complementary schemes. The Bluetooth layer encrypts packets using the Noise protocol, while the Nostr layer wraps messages in XChaCha20-Poly1305 private envelopes before transmission. This dual-encryption approach ensures that relay operators cannot read message contents, and Bluetooth sniffers cannot decrypt local traffic.

What happens if a recipient moves out of Bluetooth range during a conversation?

BitChat automatically detects connection loss and transparently switches to the Nostr transport layer. The MessageRouter logic queues any undelivered messages and attempts Nostr delivery using the recipient's public key. Once the recipient comes back within Bluetooth range, subsequent messages resume over the encrypted BLE link without user intervention.

Can BitChat work in airplane mode?

Yes, BitChat maintains full functionality in airplane mode provided Bluetooth remains enabled. The Bluetooth Mesh Network operates independently of cellular and Wi-Fi radios, allowing continued messaging with nearby peers. Location-based channels and file transfers function normally within the local mesh, though global Nostr relay access requires disabling airplane mode or enabling Wi-Fi.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →