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 channels
  • switchLocationChannel(to:) — Change active geohash subscription
  • publishNostrEvent(_:) — Send arbitrary Nostr events
  • startGeohashDM(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:

  • MessageType enumeration for payload discrimination
  • MessagePadding for 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 BitchatMessage encoding
  • Start with NostrIdentityBridge for key generation, then use ChatViewModel+Nostr helpers
  • Geohash channels provide location-based messaging via tags like ["g", "dr5rsj7"]
  • Tor support is configurable in NostrTransport for 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:

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 →