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

> Discover the role of the `client` directory in BitChat. It contains all Swift code for the user interface, state management, data persistence, and Nostr communication.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: deep-dive
- Published: 2026-08-01

---

**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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift) for event structure definitions and [`NostrIdentity.swift`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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:

```swift
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`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrRelayManager.swift) | WebSocket connection management and event publishing |
| [`bitchat/Nostr/NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrProtocol.swift) | Nostr event structure and JSON serialization |
| [`bitchat/Nostr/NostrIdentity.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrIdentity.swift) | Key pair generation and event signing |
| [`bitchatTests/ChatViewModelTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/ChatViewModelTests.swift) | Validation of conversation state management |
| [`bitchatTests/ConversationStoreTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/ConversationStoreTests.swift) | Local persistence layer verification |
| [`bitchatTests/ViewSmokeTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/ViewSmokeTests.swift) | UI component lifecycle testing |
| [`bitchatTests/VoiceRecorderTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/VoiceRecorderTests.swift) | Audio capture and encryption testing |
| [`bitchatShareExtension/ShareViewController.swift`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/VoiceRecorderTests.swift). Encryption keys are derived from conversation-specific context, ensuring that voice content remains confidential to conversation participants.