Skip to content

Reference

The site generates the function-level API reference from Gleam docs metadata. Start with the two core APIs:

beryl · beryl/channel

Use this page to find a module, choose how to send a message, inspect Phoenix frames, or select a compatible client.


ModuleWhat it doesWhen to use it
berylStart and stop raw-dispatch socket systems, configure them, and broadcast eventsBuilding or stopping a beryl socket system
beryl/channelValidate handlers, start them under a supervisor, and define typed callbacks, senders, and actionsRecommended programming model for apps with several topic features
beryl/socketInput, Next, Effect, ConnectInfo, and Sender typesWriting your app's init and update functions
beryl/bridgeForward an external OTP actor's message stream into socket.Info(...)Bridging domain actors to one socket without hand-rolled forwarders
beryl/topicTopic parsing, wildcard matching, segment extractionDynamic routing, multi-tenant patterns
beryl/pubsubDistributed PubSub backed by Erlang pg, with typed subscribers and topic joins/leavesBroadcasts across nodes and custom background subscribers
beryl/presenceOTP actor wrapping the presence CRDT, plus opaque Diff accessorsTracking who is online
beryl/presence/wirePhoenix-compatible presence state and diff encodersSending presence payloads to Phoenix clients
beryl/groupNamed sets of topics for bulk broadcastRooms with multiple sub-topics
beryl/errorShared opaque error helpersHandling beryl-owned startup errors
beryl/snapshotLocal runtime snapshotsReporting connected sockets, memberships, and active topics
beryl/wirePhoenix-compatible codec and Dynamic→JSON helpersPhoenix clients, payload relays, protocol debugging
beryl/wire/codecPluggable codec contract for text and binary framesCustom wire formats
beryl/transportPublic interface for socket setup, incoming messages, and rate limitingWriting a custom transport package
beryl/transport/originOrigin and Phoenix version checksValidating WebSocket upgrades
beryl/transport/serverShared connection and frame handling for any WebSocket serverImplementing a WebSocket transport
beryl_mistMist WebSocket upgrade and request handler integration (separate beryl_mist package)Wiring beryl to a Mist HTTP server
beryl_eweEwe WebSocket transport integration (separate beryl_ewe package)Wiring beryl to an Ewe HTTP server

GoalAPINotes
Accept a joinsocket.AcceptJoin(ref, reply) from socket.JoinSends the join phx_reply and subscribes the socket to the topic
Reject a joinsocket.RejectJoin(ref, reason) from socket.JoinFails the join immediately; unanswered joins are rejected automatically too
Reply to an incoming messagesocket.ReplyOk(ref, payload) or socket.ReplyError(ref, payload) from socket.Message(..., Some(ref))Sends phx_reply; replies are keyed by ref, not by event name
Push to the current socket onlysocket.Push(topic, event, payload)Server-originated push on a topic this socket already joined
No responsesocket.Next(model, [])Continue without outgoing frames or side effects
Broadcast to all sockets on a topicsocket.Broadcast(topic, event, payload) inside update, or beryl.broadcast(sockets, topic, event, payload) outside itAll subscribers, including the sender
Broadcast, excluding sendersocket.BroadcastFrom(topic, event, payload) inside update, or beryl.broadcast_from(sockets, socket_id, topic, event, payload) outside itExcludes one socket ID; preserved across PubSub nodes
Send a typed server-side message to one socketsocket.notify(sender, message)Store ConnectInfo.self from init; delivered later as socket.Info(message)
Broadcast presence diffberyl.broadcast_presence_diff(sockets, topic, diff)Phoenix-shaped presence_diff; application diffs use cluster delivery, replica-view diffs stay node-local

The channel layer provides topic-scoped versions through ordered channel.Action(Active) lists. These actions include push, broadcast, broadcast_from, reply_ok, reply_error, and the presence actions. They use the same core effects.


With wire.phoenix_codec(), beryl uses the Phoenix Channels JSON array format. Each frame has five elements:

[join_ref, ref, topic, event, payload]
FieldTypeDescription
join_refstring or nullReference from the original phx_join frame; null for server-initiated pushes
refstring or nullPer-message reference echoed in the reply; null for pushes
topicstringThe channel topic, e.g. "room:lobby"
eventstringEvent name
payloadobjectArbitrary JSON object
EventDirectionMeaning
phx_joinclient → serverRequest to join a topic
phx_leaveclient → serverUnsubscribe from a topic
phx_replyserver → clientReply to a client message
phx_errorserver → clientJoin rejected or channel error
phx_closeserver → clientChannel closed by server
heartbeatclient → serverKeep-alive ping (topic "phoenix")

The server sends this frame in response to a client message. socket.ReplyOk and socket.ReplyError use phx_reply with the original ref.

[join_ref, original_ref, "topic:name", "phx_reply", {"status": "ok", "response": <your_payload>}]

A join reply uses the join_ref as both join_ref and ref:

["1", "1", "room:lobby", "phx_reply", {"status": "ok", "response": {}}]

The client sends heartbeats on the "phoenix" topic; beryl replies immediately:

// client →
[null, "ref", "phoenix", "heartbeat", {}]
// server →
[null, "ref", "phoenix", "phx_reply", {"status": "ok", "response": {}}]

The payload uses the Phoenix presence diff format. The joins and leaves objects use the presence key, usually the user ID. Each value has a metas array:

{
"joins": {
"user:42": { "metas": [{ "phx_ref": "abc123", "online_at": 1234567890 }] }
},
"leaves": {
"user:99": { "metas": [{ "phx_ref": "xyz789" }] }
}
}

broadcast_presence_diff encodes only named topic entries (entries with an explicit key). Anonymous entries are excluded.


With wire.phoenix_codec(), beryl uses the standard Phoenix wire format. You can use any compatible WebSocket client:

ClientNotes
phoenix.jsOfficial JS client; full support
Phoenix Swift / Kotlin clientsCommunity Phoenix clients; wire-compatible
Plain WebSocketUse the JSON array format directly; no reconnect logic

You must set the WebSocket upgrade path. Pass the path to beryl/transport/server.default_config(path). The Phoenix JS client adds /websocket to the socket endpoint. If the client uses "/socket", mount the handler at "/socket/websocket". See the WebSocket Transport guide.


beryl follows Semantic Versioning but is not yet 1.0. Until the 1.0 release:

  • Minor version bumps (0.x → 0.x+1) may include breaking changes to the public API.
  • Patch version bumps (0.x.y → 0.x.y+1) fix bugs without intentional breakage.
  • Public API is defined as the exports of the modules listed in the module map above, including beryl/channel.
  • The internal modules beryl/app_supervisor, beryl/connection_limit, beryl/internal, beryl/log, beryl/rate_limit, beryl/runtime, and beryl/telemetry are intentionally hidden from downstream packages. Transports integrate through the public beryl/transport SPI.

Check GitHub releases before upgrading to a new minor version.