Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This page shows you how to use Wheels channels — a pub/sub layer on top of [Se
**You'll learn:**

- What channels add on top of the low-level SSE API
- Where Wheels stands on WebSockets — and why channels are SSE-only by design
- Where Wheels stands on WebSockets — SSE-only in core by design, with an optional `wheels-websockets` package on top
- How to publish with `publish()` and subscribe with `subscribeToChannel()`
- When to use the memory adapter versus the database adapter
- How to deliver the `WheelsSSE` JavaScript client to the browser (it is not auto-served)
Expand All @@ -36,7 +36,7 @@ Everything flows one way: server to client.

## The WebSocket story

Wheels does not ship WebSocket support. There is no bidirectional channel, no binary framing, no presence tracking, and no `cfwebsocket` integration. Channels are one-directionalserver to client — over SSE, and that is a deliberate design choice, not a stopgap:
The framework core ships channels over SSE only — one-directional, server to client. That is a deliberate design choice, not a stopgap:

- **Plain HTTP.** SSE rides an ordinary long-lived GET request. Every proxy, load balancer, and firewall that speaks HTTP passes it through; WebSockets need their own upgrade handshake and protocol support at every hop.
- **Free reconnection.** The browser's `EventSource` reconnects automatically and resends `Last-Event-ID` so you can resume. With WebSockets you write that yourself.
Expand All @@ -46,7 +46,22 @@ AdonisJS made the same call with its Transmit package — SSE-only, no WebSocket

For the client-to-server direction, use what you already have: an ordinary HTTP POST. The action saves whatever it needs to and calls `publish()` to fan the result out to subscribers. The [chat room pattern](#chat-room) below is exactly this — and it covers most "I need WebSockets" use cases.

Native WebSocket support is being scoped on the roadmap — follow [issue #2962](https://github.com/wheels-dev/wheels/issues/2962).
### Optional WebSocket transport: the `wheels-websockets` package

When you do want events delivered over a real WebSocket, the first-party [`wheels-websockets`](https://github.com/wheels-dev/wheels-websockets) package (v0.2.0) adds an opt-in WebSocket transport on top of channels:

```bash title="illustrative — install the package"
wheels packages add wheels-websockets
```

Your app keeps calling `publish()` exactly as before. Where the engine can serve WebSockets, connected browsers get the event over a socket; everywhere else, nothing changes and SSE channels keep working. Engine support:

- **RustCFML** — native transport, supported since v0.1.0.
- **Lucee 6.2+** — via the official [lucee/extension-websocket](https://github.com/lucee/extension-websocket), verified live as of v0.2.0. This is the verified stock-Lucee path today.
- **Lucee 7** — needs an engine at 7.0.2.7 or newer *and* a jakarta-compatible release of the websocket extension, which hasn't been published yet. Until it ships, the package detects the situation, logs one warning, and channels keep working over SSE.
- **Adobe CF / BoxLang** — no WebSocket backend yet (demand-gated on [discussion #3286](https://github.com/wheels-dev/wheels/discussions/3286)); channels degrade gracefully to SSE.

The package's `WheelsRealtime` JavaScript client falls back to the stock `WheelsSSE` client automatically, so you get one subscription API on every engine. Installing the package on an unsupported engine is always safe — it logs one line and stays on SSE.

## Quick start

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ SSE (Server-Sent Events) is a one-way channel from server to client over plain H
- **SSE:** server → client only, plain HTTP, built-in auto-reconnect, passes through every proxy and firewall that speaks HTTP.
- **WebSockets:** bidirectional, separate `ws://` protocol, richer feature set but harder to deploy behind a reverse proxy and requires its own connection lifecycle.

Use SSE when the client only needs to listen — notifications, live dashboards, progress bars, log tailing, incremental search results. Reach for WebSockets when the client also needs to pushbut note that Wheels itself ships no WebSocket layer; for the higher-level pub/sub option built on SSE (and the full story on what does and doesn't exist), see [Channels](/v4-0-0/digging-deeper/channels/).
Use SSE when the client only needs to listen — notifications, live dashboards, progress bars, log tailing, incremental search results. Reach for WebSockets when the client also needs to push. The framework core ships no WebSocket layer, but the optional [`wheels-websockets`](https://github.com/wheels-dev/wheels-websockets) package adds a WebSocket transport for channels (`wheels packages add wheels-websockets`) with automatic SSE fallback — for the higher-level pub/sub option built on SSE and the full WebSocket story, see [Channels](/v4-0-0/digging-deeper/channels/).

## One-shot SSE response

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ The 3.x getting-started spine was built on CommandBox. Here's how each old step
| `box install cfwheels-base-template` | **Slug changed** — `box install wheels-base-template` (the `cfwheels-`-prefixed slug is dead; see below) |

<Aside type="caution" title="The `cfwheels-base-template` slug is gone — use `wheels-base-template`">
If your 2.x muscle memory is `box install cfwheels-base-template`, that command no longer works. The pre-rebrand `cfwheels-`-prefixed ForgeBox slugs (`cfwheels-base-template`, `cfwheels`) are **deprecated and unmaintained** — `cfwheels-base-template` still resolves on ForgeBox but errors on its missing `cfwheels` core dependency and leaves an unrunnable skeleton. The framework rebranded to **Wheels** at 3.0, and the supported 4.x slugs dropped the prefix:
If your 2.x muscle memory is `box install cfwheels-base-template`, that command no longer works. The pre-rebrand `cfwheels-`-prefixed ForgeBox slugs are **dead** — `cfwheels-base-template` has been unlisted from ForgeBox entirely, so `box install cfwheels-base-template` fails with `entry slug invalid or does not exist`. The framework rebranded to **Wheels** at 3.0, and the supported 4.x slugs dropped the prefix:

- `cfwheels-base-template` → [`wheels-base-template`](#supported-install-the-framework)
- `cfwheels` → `wheels-core`
- `cfwheels-cli` → the standalone [`wheels` CLI](/v4-0-0/start-here/installing/) (the ForgeBox `cfwheels-cli` module is the pre-rebrand CommandBox CLI; even its renamed successor, the `wheels-cli` slug, is [deprecated](#not-supported-via-commandbox-the-wheels-cli-feature-set))

Install the modern slug instead:

Expand Down
Loading