How to Integrate BitChat with Other Applications: A Complete Developer Guide
BitChat integrates with external applications through two independent layers: the Bluetooth Mesh offline protocol via BitchatMessage binary encoding and the Nostr online protocol via the NostrCoordinator API.
Integrating BitChat into your application requires understanding its dual-transport architecture. The permissionlesstech/bitchat repository exposes clean Swift APIs for both local mesh communication and global Nostr relay messaging. This guide covers the concrete integration points, file locations, and working code samples you need to interoperate with the BitChat ecosystem.
BitChat Architecture Overview
BitChat operates on two distinct communication layers that applications can tap into independently:
- Bluetooth Mesh (offline): Local, multi-hop communication using the BitFoundation binary protocol
- Nostr Protocol (online): Global reach through Nostr relays with geohash-based channels
Both layers share the same message encoding defined in BitchatMessage.swift, ensuring seamless bridging between offline and online modes.
Core Integration Points in the Source Code
NostrIdentityBridge: Identity Generation and Key Mapping
Located at [bitchat/NostrIdentityBridge.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/NostrIdentityBridge.swift), this class handles the critical first step of any integration: establishing a Nostr-compatible identity.
The bridge generates per-device Nostr key pairs and translates between Nostr public keys and BitChat's internal peer identifiers. External clients use this to obtain ready-to-publish identities without managing cryptographic details themselves.
NostrTransport: Low-Level Relay Communication
Found in [bitchat/NostrTransport.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/NostrTransport.swift), this class manages WebSocket connections to Nostr relays with optional Tor routing.
Key capabilities for integration:
let transport = NostrTransport(
keychain: MyKeychain(),
idBridge: idBridge,
useTor: false // Set true for privacy-focused deployments
)
// Send custom events
try transport.send(event: myEvent)
// Subscribe to specific filters
transport.subscribe(to: myFilterSet)
The transport handles rate-limiting, connection recovery, and Tor fallback automatically.
ChatViewModel+Nostr: High-Level Application Hooks
The bitchat/ViewModels/Extensions/ChatViewModel+Nostr.swift file provides the recommended entry points for most integrations. These helpers wrap the coordinator complexity into actionable methods:
sendGeohash(context:)— Publish to location-based channelsswitchLocationChannel(to:)— Change active geohash subscriptionpublishNostrEvent(_:)— Send arbitrary Nostr eventsstartGeohashDM(withPubkeyHex:)— Initiate direct messaging
BitchatMessage: Binary Protocol Implementation
The [localPackages/BitFoundation/Sources/BitFoundation/BitchatMessage.swift](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/BitFoundation/Sources/BitFoundation/BitchatMessage.swift) file defines the wire format used across both transport layers. External applications encoding or decoding raw BitChat packets need this structure.
The protocol includes:
MessageTypeenumeration for payload discriminationMessagePaddingfor traffic shaping- Binary serialization via
toBinaryPayload()and corresponding deserialization
Step-by-Step Integration Flow
Follow this sequence to integrate BitChat capabilities into your application:
1. Establish Nostr Identity
import BitFoundation
let idBridge = NostrIdentityBridge(keychain: MyKeychain())
let myIdentity = try NostrIdentity.generate()
// myIdentity.npub provides the public identifier
// Private keys are securely stored via your keychain implementation
2. Configure Transport Layer
let transport = NostrTransport(
keychain: MyKeychain(),
idBridge: idBridge,
useTor: false
)
For privacy-critical applications, enable Tor routing by setting useTor: true as documented in [docs/TOR-INTEGRATION.md](https://github.com/permissionlesstech/bitchat/blob/main/docs/TOR-INTEGRATION.md).
3. Publish to Geohash Channels
let event = NostrEvent(
kind: .textNote,
content: "Hello from an external app!",
tags: [["g", "dr5rsj7"]], // Geohash precision level determines broadcast radius
createdAt: Date()
)
try transport.send(event: event)
The geohash tag g controls geographic scoping. Shorter hashes (e.g., dr5rs) cover larger regions; longer hashes (e.g., dr5rsj7) target specific neighborhoods.
4. Subscribe to Location-Based Channels
let chatVM = ChatViewModel(/* dependencies */)
await chatVM.switchLocationChannel(to: "dr5rsj7")
This activates the nostrCoordinator.subscriptions for the specified geohash and begins receiving relevant messages.
5. Send Encrypted Direct Messages
let recipientPubkey = "npub1…"
let noiseKey = try chatVM.findNoiseKey(for: recipientPubkey)
await chatVM.sendFavoriteNotificationViaNostr(
noisePublicKey: noiseKey,
isFavorite: true
)
BitChat uses Noise protocol keys for encryption, retrieved here via the coordinator's key management.
6. Bridge Mesh to Nostr (Hybrid Applications)
let binaryMsg = try BitchatMessage(
content: "Local mesh payload",
sender: myIdentity.npub,
isPrivate: false
).toBinaryPayload()
// Forward over Nostr as encapsulated binary data
let bridgeEvent = NostrEvent(
kind: .privateEnvelope,
content: binaryMsg.base64EncodedString(),
tags: [["p", recipientPubkey]],
createdAt: Date()
)
try transport.send(event: bridgeEvent)
This pattern enables store-and-forward: mesh messages reach Nostr when connectivity becomes available.
Geohash Channel Management
Geographic channels are managed through the coordinator's presence system, referenced via nostrCoordinator.presence. To monitor multiple regions programmatically:
// From GeohashPresence.swift patterns
beginGeohashSampling(for: ["dr5rs", "dr5rt", "dr5ru"])
This subscribes to all specified geohashes without UI interaction, suitable for server-side monitoring applications.
Key Files Reference
| File | Purpose | Integration Use |
|---|---|---|
ChatViewModel+Nostr.swift |
High-level API surface | Primary integration point for UI and services |
NostrIdentityBridge.swift |
Identity generation | Required for any Nostr interaction |
NostrTransport.swift |
Relay communication | Custom transport implementations |
BitchatMessage.swift |
Binary protocol | Mesh packet encoding/decoding |
ARCHITECTURE_V2.md |
System design | Deep architectural understanding |
Summary
- Two transport layers: Bluetooth Mesh (offline) and Nostr (online) share the
BitchatMessageencoding - Start with
NostrIdentityBridgefor key generation, then useChatViewModel+Nostrhelpers - Geohash channels provide location-based messaging via tags like
["g", "dr5rsj7"] - Tor support is configurable in
NostrTransportfor privacy-sensitive deployments - Binary bridging allows hybrid applications to forward mesh packets over Nostr
Frequently Asked Questions
What programming languages can integrate with BitChat?
BitChat is written in Swift, but the Nostr protocol integration works with any language that can generate valid Nostr events. The binary BitchatMessage format can be reimplemented in other languages by following the encoding rules in BitchatMessage.swift. For non-Swift environments, use standard Nostr libraries and match the event structure BitChat expects.
Do I need to run a full BitChat node for integration?
No. The modular architecture in permissionlesstech/bitchat allows selective use of components. You can instantiate NostrTransport and NostrIdentityBridge without the full UI stack. For mesh-only scenarios, import the BitFoundation package directly to handle binary message encoding.
How does BitChat handle message encryption?
BitChat uses Noise protocol keys for direct messaging, managed through findNoiseKey(for:) in the coordinator. When publishing via NostrTransport, you control encryption: use standard Nostr encryption for public notes or wrap binary payloads for private envelopes. The isPrivate flag in BitchatMessage determines handling at the receiving end.
Can I route BitChat traffic through Tor?
Yes. Set useTor: true when initializing NostrTransport. The implementation in NostrTransport.swift automatically handles Tor circuit establishment and WebSocket tunneling. See [docs/TOR-INTEGRATION.md](https://github.com/permissionlesstech/bitchat/blob/main/docs/TOR-INTEGRATION.md) for network configuration details and performance considerations.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →