What Is the Role of the `client` Directory in BitChat?

The client directory in BitChat houses all Swift code responsible for the user-facing application, including UI rendering, state management, local data persistence, and Nostr network communication.

BitChat is a decentralized messaging application built on the Nostr protocol. The client directory—located under the bitchat/ package—serves as the comprehensive implementation of the end-user experience. Understanding its architecture is essential for developers contributing to the codebase or building compatible Nostr clients.

Core Responsibilities of the client Directory

The client directory consolidates six primary responsibilities that together deliver a fully functional decentralized chat application.

UI Rendering with SwiftUI

The client implements all visual interfaces using SwiftUI view hierarchies and supporting view controllers. This includes chat threads, contact lists, settings panels, and media viewers. The ViewSmokeTests.swift file in bitchatTests/ provides foundational test scaffolding that validates UI component initialization and lifecycle behavior.

State Management via View Models

Conversation state, message queues, and authentication tokens are managed through dedicated view-model classes. The ChatViewModelTests.swift file demonstrates how ChatViewModel implementations handle:

  • Message threading and ordering
  • Real-time synchronization with the Nostr relay
  • User authentication state transitions

These view models serve as the intermediary between SwiftUI views and the underlying data layer.

Local Message Persistence

The client maintains local storage for conversations, message drafts, and cached media through the ConversationStore implementation. The ConversationStoreTests.swift test suite verifies:

  • CRUD operations on conversation records
  • Draft preservation across app restarts
  • Media file association with message metadata

This persistence layer ensures offline functionality and rapid message retrieval.

Nostr Network Layer

Network communication is orchestrated through a thin wrapper around the Nostr protocol. The primary implementation resides in bitchat/Nostr/NostrRelayManager.swift, which manages:

  • WebSocket connection lifecycle to multiple relays
  • Event signing with secp256k1 key pairs
  • NIP-13 proof-of-work negotiation
  • Subscription filtering and event deduplication

Supporting files include NostrProtocol.swift for event structure definitions and NostrIdentity.swift for cryptographic identity management.

Audio and Voice Message Support

Voice note capture, encoding, and playback—including XChaCha20-Poly1305 encryption—are implemented in modules under bitchat/Voice*/. The VoiceRecorderTests.swift file validates audio pipeline integrity, covering:

  • Permissions-based microphone access
  • Opus encoding configuration
  • Encryption key derivation from conversation contexts

System Share Extension Integration

The bitchatShareExtension/ package contains ShareViewController.swift, which provides a minimal bridge between iOS's system share sheet and the main client. This enables users to share URLs, images, and text from external applications directly into BitChat conversations.

Key Implementation Example: Sending a Message

Below is a representative pattern showing how client components collaborate to publish a message:

import Foundation

// Acquire the singleton relay manager from the client directory
let relayManager = NostrRelayManager.shared

// Establish connection to a public Nostr relay
try await relayManager.connect(to: URL(string: "wss://relay.damus.io")!)

// Create and sign the event using the local identity
let event = try await NostrIdentity.shared.createTextNoteEvent(content: "Hello, Nostr!")

// Publish through the client's network layer
try await relayManager.publish(event)

This pattern demonstrates the client's role in bridging user intent with decentralized network participation.

Key Files and Their Purposes

File Path Responsibility
bitchat/Nostr/NostrRelayManager.swift WebSocket connection management and event publishing
bitchat/Nostr/NostrProtocol.swift Nostr event structure and JSON serialization
bitchat/Nostr/NostrIdentity.swift Key pair generation and event signing
bitchatTests/ChatViewModelTests.swift Validation of conversation state management
bitchatTests/ConversationStoreTests.swift Local persistence layer verification
bitchatTests/ViewSmokeTests.swift UI component lifecycle testing
bitchatTests/VoiceRecorderTests.swift Audio capture and encryption testing
bitchatShareExtension/ShareViewController.swift System share sheet integration

Relationship to Repository Structure

The client directory operates alongside other top-level components:

  • docs/ — Architecture specifications including ARCHITECTURE_V2.md
  • Test targets — bitchatTests/ validates client functionality
  • Share extension — Separate bundle ID but functionally dependent on client data models

The modular separation allows independent testing of network, storage, and UI concerns while maintaining tight integration for production builds.

Summary

  • The client directory contains all Swift implementation for the BitChat user application, distinguishing it from relay infrastructure or protocol specifications
  • UI rendering, state management, and local persistence form the core user experience layer
  • NostrRelayManager.swift serves as the primary gateway to decentralized network communication
  • Share extension integration extends client functionality into the broader iOS ecosystem
  • Comprehensive test coverage in bitchatTests/ validates each subsystem's behavior

Frequently Asked Questions

What protocol does the BitChat client use for message transport?

The BitChat client implements the Nostr protocol, a decentralized note-and-relay system using WebSocket connections. As implemented in NostrRelayManager.swift, the client connects to user-configurable relays, publishes signed events, and maintains subscription filters for incoming messages.

How does the BitChat client handle offline message access?

Local persistence through ConversationStore enables offline functionality. The client stores conversation metadata, message content, and media references in on-device storage, allowing message history access without active relay connections. Synchronization resumes automatically when connectivity returns.

What cryptographic methods secure voice messages in the client?

Voice messages use XChaCha20-Poly1305 authenticated encryption, as implemented in the voice processing modules tested by VoiceRecorderTests.swift. Encryption keys are derived from conversation-specific context, ensuring that voice content remains confidential to conversation participants.

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 →