PhoenixNectar - a Swift 6 client for Phoenix Channels

I'd like to share PhoenixNectar, a Swift 6 client for Phoenix Channels, the real-time WebSocket layer of the Phoenix web framework (Elixir).

If you're building an iOS or macOS app that talks to a Phoenix backend over WebSockets, this is for you. It's designed around Swift's modern concurrency model from the start (actors, async/await, and AsyncStream) rather than wrapping a callback-based API.

It builds on the great work of SwiftPhoenixClient by David Stump and Daniel Rees, which has been the go-to Swift client for years. PhoenixNectar takes a different approach by embracing Swift’s modern concurrency model rather than the JS-style callback API.

Quick example

import PhoenixNectar

struct ChatMessage: Codable, Sendable {
   let body: String
}

let client = try Socket(endpoint: "wss://api.example.com/socket")
try await client.connect()

let channel = try await client.joinChannel("room:lobby")

// Inbound events as an AsyncStream
let posted = Event<ChatMessage>("message:posted")
for try await message in await channel.subscribe(to: posted) {
   print(message.body)
}

// Typed push with an awaited reply
let send = Push<ChatMessage, ChatMessage>("message:send")
let reply = try await channel.push(send, payload: ChatMessage(body: "hello"))

What makes it tick

  • Actor-owned runtime — all socket and channel state lives inside actors, so it's fully safe under Swift 6 strict concurrency with no @unchecked Sendable workarounds

  • Typed payloadsPush<Request, Response> and Event<T> give you compile-time safety on your channel messages via Codable

  • AsyncStream subscriptions — observe channel events and connection state changes with for await loops

  • Auto reconnect and rejoin — transport loss, heartbeat timeouts, and server closes all trigger automatic reconnect with configurable backoff; joined channels are rejoined automatically

  • Auth token refreshauthTokenProvider and connectParamsProvider closures are re-evaluated on every reconnect

Supports iOS 16+, macOS 15+, tvOS 18+, watchOS 11+. Available as a Swift package.

Feedback and contributions welcome!

1 Like