Phoenix
The official JavaScript client for Phoenix Channels — multiplexed WebSocket realtime with automatic reconnection and presence tracking.
Repository Health
Technical Analysis
Phoenix is the official JavaScript client library for Phoenix Channels, the realtime communication layer built into the Phoenix web framework for Elixir. It manages a single multiplexed WebSocket connection to a Phoenix backend, letting you join topic-based channels, push and receive events, and track connected users through the Presence API — all with automatic reconnection, exponential backoff, and a long-polling fallback when WebSockets aren’t available.
Distributed as the phoenix npm package straight from the phoenixframework/phoenix monorepo, this client pairs a small, dependency-free API surface with production-tested reliability: it ships in every new Phoenix project’s asset pipeline and powers realtime features (chat, live dashboards, collaborative editing, presence indicators) across the Elixir ecosystem, while working equally well from any JavaScript frontend regardless of build tool.
What You Get
- Socket class managing one multiplexed WebSocket connection with automatic reconnect and exponential backoff
- Channel abstraction for joining topics, pushing events, and handling ok/error/timeout replies
- Presence helper for syncing and diffing which users/clients are connected to a channel
- LongPoll transport fallback for environments where WebSockets are blocked or unavailable
- Pluggable serializers and encode/decode hooks for custom message formats
Common Use Cases
- Building live chat rooms and comment threads that update instantly for every connected client
- Powering realtime dashboards and metrics displays pushed from a Phoenix backend
- Tracking which users are online or editing and showing presence indicators in collaborative apps
- Streaming server-pushed notifications and events to a JS frontend without polling
Under The Hood
Architecture
Phoenix.js is organized as a small set of cooperating ES6 classes rather than a monolithic client: Socket (assets/js/phoenix/socket.js) owns the single WebSocket/LongPoll transport and connection lifecycle, Channel (channel.js) represents one joined topic and delegates message framing to Push (push.js) objects that expose chainable .receive("ok"|"error"|"timeout", cb) hooks, Presence (presence.js) layers a diff-based sync algorithm on top of channel events, and Serializer/Ajax/Timer/constants/utils provide encoding, the long-poll fallback transport, backoff scheduling, and shared constants respectively. Channels register themselves with their parent socket and rely on the socket’s onOpen/onError hooks to drive their own rejoin timers, so reconnection and rejoin logic is decentralized to each channel rather than centralized in the socket — a design that keeps failure handling local to whichever topic actually needs to recover. Because every channel is multiplexed over one socket connection, changing the core Socket class’s message-dispatch contract would ripple through Channel, Push, and Presence simultaneously, making it the one abstraction the rest of the library is built around.
Tech Stack
The client is dependency-free vanilla JavaScript (ES6 classes, no runtime dependencies) built from the assets/js/phoenix source tree and published from the same phoenixframework/phoenix monorepo that ships the Elixir framework. The mix assets.build task compiles the JS source into the formats declared in package.json’s exports/main/module/unpkg fields — a CommonJS bundle, an ES module, and a minified UMD build for CDN use via unpkg/jsdelivr. Testing runs on Jest (with jest-environment-jsdom and mock-socket to simulate WebSocket behavior in Node), linting runs through ESLint with the @stylistic and eslint-plugin-jest plugins, and CI runs npm test on Node 24 alongside the Elixir test suite for the wider Phoenix repo.
Code Quality
The assets/test/ directory holds six spec files (socket, channel, presence, longpoll, serializer, and socket-over-HTTP tests) totaling roughly 249 test cases covering reconnection backoff, channel join/error/timeout transitions, presence diffing, and the long-poll transport, plus a test.coverage npm script for coverage reporting. Error handling favors explicit state machines over exceptions — Channel and Socket track state via enums (CHANNEL_STATES, SOCKET_STATES) and route failures through onError/onClose callback hooks rather than throwing, which suits a long-lived connection object. Naming is consistent and public classes/methods carry extensive JSDoc comments, though the library ships no TypeScript declaration files of its own — type coverage for TS consumers currently comes from the community-maintained @types/phoenix package rather than from this repo.
API Design
The public API optimizes for a small number of composable, chainable primitives rather than configuration objects: joining a channel returns a Push you chain .receive("ok"|"error"|"timeout", cb) calls onto, and the same pattern is reused for every server round-trip (join, leave, custom events), so there’s exactly one interaction idiom to learn. Presence layers a listBy-customizable diff/sync model on top of plain channel events instead of inventing a separate presence protocol, keeping the mental model consistent with the rest of the library. Getting started requires only new Socket(endpoint).connect() and socket.channel(topic) — no build step, framework binding, or scaffolding is required, and automatic reconnection/backoff is opt-out rather than something the caller has to wire up themselves.
Used by 2 apps in this directory
CodeSandbox
Code Editors · Developer Tools
Instantly ready browser-based IDE that runs full npm dependency resolution and transpilation entirely client-side, with no server needed.
Operately
AI Assistants · Project Management · Productivity
The open source company operating system that unifies OKRs, projects, and team execution with built-in accountability cadences.