# How Location-Based Channels Work in BitChat's Nostr Transport

> Discover how BitChat uses Nostr transport for location-based channels. Learn about geohash mapping to unique Nostr identities for efficient, decentralized communication.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: how-to-guide
- Published: 2026-08-23

---

**BitChat implements location-based channels by mapping each geographic cell (geohash) to a unique, short-lived Nostr identity that serves as the destination address for all Nostr traffic belonging to that location.**

BitChat's peer-to-peer messaging protocol leverages geographic proximity through an innovative approach to location-based channels in its Nostr transport layer. By deriving unique Nostr public keys from geohash coordinates, the system creates logical broadcast channels without exposing precise user locations. This architecture, implemented in the `permissionlesstech/bitchat` repository, allows participants in the same geographic cell to communicate through standard Nostr relays while maintaining cryptographic privacy.

## Geohash-to-Identity Mapping for Location Channels

The core mechanism converts geographic cells into cryptographic identities. Each geohash represents a bounded geographic area, which BitChat translates into a deterministic Nostr public key (hex format). This **geohash-derived identity** functions as a shared mailbox for all participants within that cell.

In [`bitchat/Services/NostrTransport.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/NostrTransport.swift), the transport layer treats these derived identities as logical Nostr channels. Rather than broadcasting precise GPS coordinates, users address messages to the hex-encoded public key representing their current geohash cell. This approach ensures that all participants sharing the same geographic region automatically subscribe to the same logical channel through the Nostr protocol.

## Core Implementation in NostrTransport.swift

The `NostrTransport` class contains a dedicated **Geohash Helpers** section that manages message routing for location-based communications according to the source code in [`bitchat/Services/NostrTransport.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/NostrTransport.swift).

### Sending Private Messages to Geohash Channels

The `sendPrivateMessageGeohash(_:toRecipientHex:from:messageID:)` method constructs and dispatches Nostr private-message events to geohash-derived recipients. This function accepts a hex-encoded public key representing the target geohash cell rather than an individual user's key.

```swift
// Create a geohash channel (e.g., city-level "u4pruy")
let cityChannel = GeohashChannel(level: .city, geohash: "u4pruy")

// Initialize transport with required dependencies
let transport = NostrTransport(
    keychain: keychainHelper,
    idBridge: nostrIdentityBridge
)

// Send location-based private message to the geohash identity
transport.sendPrivateMessageGeohash(
    content: "Hello nearby friends!",
    toRecipientHex: "abcdef1234567890...", // hex derived from geohash
    from: myNostrIdentity,
    messageID: UUID().uuidString
)

```

### Delivery Acknowledgements and Read Receipts

BitChat also routes delivery confirmations through the same geohash identities. The `sendDeliveryAckGeohash` and `sendReadReceiptGeohash` methods enqueue paced acknowledgements sent to the per-geohash Nostr identity, ensuring that presence indicators and message status updates remain synchronized within the geographic cell.

```swift
// Send delivery acknowledgement for a geohash DM
transport.sendDeliveryAckGeohash(
    for: messageID,
    toRecipientHex: "abcdef1234567890...",
    from: myNostrIdentity
)

```

Both sender and recipient identities derive from the shared geohash, creating a symmetric trust model where geographic proximity determines channel access.

## Protocol Specifications and Supporting Files

The location-based channel architecture extends beyond transport implementation into protocol design. According to [`docs/GeohashPresenceSpec.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/GeohashPresenceSpec.md), the system defines specific Nostr event kinds for geohash-based presence heartbeats, establishing the wire format for geographic rendezvous.

Additional components include:

- **[`localPackages/BitFoundation/Sources/BitFoundation/PeerCapabilities.swift`](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/BitFoundation/Sources/BitFoundation/PeerCapabilities.swift)**: Documents the capability flag bridging local mesh channels to geohash-cell rendezvous points on Nostr
- **[`localPackages/BitFoundation/Sources/BitFoundation/MessageType.swift`](https://github.com/permissionlesstech/bitchat/blob/main/localPackages/BitFoundation/Sources/BitFoundation/MessageType.swift)**: Enumerates Nostr message kinds used for signed geohash bulletin-board posts, distinguishing location-based broadcasts from direct messages

These files collectively ensure that BitChat's Nostr transport correctly interprets geographic boundaries as cryptographic channel boundaries.

## Summary

- BitChat maps each geohash geographic cell to a unique Nostr public key, creating deterministic location-based channels without exposing precise coordinates
- The [`NostrTransport.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrTransport.swift) file implements geohash-specific methods including `sendPrivateMessageGeohash`, `sendDeliveryAckGeohash`, and `sendReadReceiptGeohash` for routing traffic to geographic identities
- All participants in the same geohash cell share a common Nostr "channel" through the hex-encoded public key derived from their location
- The protocol uses standard Nostr private-message events (kind definitions specified in [`GeohashPresenceSpec.md`](https://github.com/permissionlesstech/bitchat/blob/main/GeohashPresenceSpec.md)) to deliver chat content and presence heartbeats to geohash-derived destinations

## Frequently Asked Questions

### How does BitChat convert geographic coordinates into Nostr identities?

BitChat converts geographic coordinates into geohash strings (such as "u4pruy" for city-level precision), then deterministically derives a Nostr public key from that geohash value. This hex-encoded public key serves as the destination address for all messages intended for participants in that geographic cell, effectively turning the geohash into a shared mailbox identifier within the Nostr protocol.

### What Nostr event kinds are used for location-based messages?

According to [`GeohashPresenceSpec.md`](https://github.com/permissionlesstech/bitchat/blob/main/GeohashPresenceSpec.md), BitChat uses specific Nostr event kinds for geohash-based presence heartbeats and private messages. The standard private-message event kind carries chat content to geohash-derived recipients, while dedicated presence event kinds handle geographic rendezvous announcements and heartbeat signals that maintain channel liveness.

### Can users receive messages from multiple geohash channels simultaneously?

Yes. Since each geohash maps to a unique Nostr public key, clients can subscribe to multiple hex-encoded identities concurrently. Users moving between cells automatically derive new channel identities based on their current geohash, allowing seamless handoff between location-based channels while maintaining conversation history through the underlying Nostr relay network.

### How does the transport layer prevent location tracking via Nostr metadata?

The `NostrTransport` class ensures that precise coordinates never appear in Nostr events. Instead, messages address only the geohash-derived hex string, and the transport derives both sender and recipient identities from the shared geohash context. This design means that Nostr relays and observers see only the hashed geographic cell identifier rather than GPS coordinates, preserving location privacy while enabling geographic clustering.