Skip to content

Commit 30d200a

Browse files
docs: reposition around ICP, use cases, and delivery guarantees (#59)
* docs: reposition around ICP, use cases, and delivery guarantees Align the docs with the current anycable.io positioning (multi-language realtime server with delivery guarantees) instead of the older Rails + Action Cable framing. - Front door: new overview, quick start (stack picker), capabilities hub - Use-case guides: AI streaming, live dashboards, GPS dispatch, telehealth - Python / any-backend guide and an Editions page (OSS / Pro / AnyCable+) - Restructure sidebar/IA; update site metadata for Python + delivery guarantees - getting_started becomes a Quick Start pointer with a 301; fix broken links - Note Valkey alongside Redis on key pages - Fix pro.md (title, OCPP typo, dead link) and add demo app links All new pages were verified against a running anycable-go 1.6.7. * docs: add complete anycable-go server options reference Generated from `anycable-go --help` (84 options across 22 sections, each with its env var and default). Linked from Configuration and the sidebar. Helps humans find flags and prevents agents from hallucinating options. * docs: fix lint (forspell/markdownlint) and complete options reference - forspell.dict: add realtime, healthtech, fintech, telehealth, replayable, leaderboards, analytics, httpx, cron, redisx, nats, statsd, subprotocols, Disconnector - markdownlint: drop trailing '?' in overview H1 (MD026); join adjacent blockquotes in pro/broadcasting/broadcast_adapters (MD028); inline AI-streaming Python example; reword air-gapped - options reference: regenerate from current OSS v1.6.14 (97 options, was 84 from 1.6.7) and add a Pro-only options section (admin, GraphQL, long polling, OCPP, netpoll, slow drain, adaptive RPC) from a Pro build * docs: fix --broadast_key typo -> --broadcast_key (release notes) Found via the flag audit cross-checking documented flags against `anycable-go --help`. The adjacent ANYCABLE_BROADCAST_KEY confirms the fix. * docs: fix pre-existing typos found during fact-check - architecture.md: miminalize -> minimize - release_notes.md: nonderterministic -> nondeterministic, dowstreamed -> downstreamed, paramter -> parameter, peforming -> performing - forspell.dict: add Hatchbox, fastlane, downstreamed (legit terms) Found by running forspell across the full docs tree. * docs: fix OCPP typos (OCCP -> OCPP, hearbeat -> heartbeat) - ocpp.md: OCCPChannel -> OCPPChannel (the binary default is OCPPChannel) - options.md: --ocpp_heartbeat_interval / ANYCABLE_OCPP_HEARTBEAT_INTERVAL (corrected spelling; the Pro binary typo is being fixed upstream) * docs(landing): refresh homepage to reflect new positioning - Tagline now matches the site positioning (delivery guarantees, multi-language) - 'Get Started' points to the new Quick Start; add 'What is AnyCable?' link - Stack cards: add Python and Any backend (HTTP API); relabel Node.js/TS - New 'Explore' section: Capabilities, Build by use case, Editions * docs: address PR review (use-case correctness fixes) - live-dashboards: define BROADCAST_URL (was undefined NameError); scope the benchmark figure to the broadcast-throughput test; name --public_streams - ai-streaming: promote --public into the runnable dev command (step 3 uses an unsigned stream) - gps-dispatch, telehealth: make Python broadcast examples self-contained (define publish + BROADCAST_URL); OCPP described as alpha, drop vague claim - telehealth: on-premise prose links to Docker/Kubernetes, not Heroku - _redirects: drop forced 301 on /getting_started so the pointer page shows * docs: add --public to dev commands in dashboards/gps/telehealth Second-pass review: the unsigned-streamFrom-without---public issue fixed in ai-streaming was systemic. These three pages ran the server without --public but their client examples subscribe to unsigned streams, so a copy-paste reader hit rejected subscriptions. Matched the ai-streaming pattern with a local-dev-only caveat pointing to signed streams + JWT for production. * docs: fix JWT param env var and enats default; show secret export Third-pass review: - jwt_identification.md used ANYCABLE_ID_PARAM, but the binary honors ANYCABLE_JWT_PARAM (verified: ANYCABLE_ID_PARAM is ignored, param stays 'jid'; ANYCABLE_JWT_PARAM=token sets it). options.md was already correct. - options.md --enats_max_payload Default cell had a --help parsing artifact ('1048576 = 1MB) (default: 0'); real default is 0. - quickstart + python: show 'export ANYCABLE_SECRET=...' so the var isn't empty when copy-pasted. * docs: address 4th review (OCPP caveat, redirect dedup, explicit WS URLs) - options.md: inline caveat on --ocpp_heartbeat_interval noting current Pro builds spell it --ocpp_hearbeat_interval (typo) until the fix ships - _redirects: drop the no-op /getting_started 301 (the pointer page renders); keep /anycable-go/getting_started -> /quickstart - use-case JS examples: pass explicit ws://localhost:8080/cable to createCable, so standalone Node/Python readers (no action-cable-url meta tag) can copy-paste * docs: move use-case guides to a separate PR Per review feedback, the 'Build by use case' guides (AI streaming, live dashboards, GPS dispatch, telehealth + index) ship in their own PR. Removes the pages, the sidebar group, and the landing-page card here; the rest of the repositioning (front door, by-backend, capabilities, editions, options reference, fixes) stays.
1 parent 7746315 commit 30d200a

25 files changed

Lines changed: 1033 additions & 194 deletions

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ lefthook-local.yml
1111

1212
# Local Netlify folder
1313
.netlify
14+
15+
# Internal docs-rework working files (not for publication)
16+
DOCS_IMPROVEMENTS_SPEC.md
17+
FACT_CHECK.md
18+
DOCS_NOTES.md
19+
.DS_Store

docs/.vitepress/config.mts

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { availableSinceMarkdownPlugin } from './availableSinceMarkdownPlugin'
55

66
export default withMermaid(defineConfig({
77
title: "AnyCable",
8-
description: "A real-time server for Rails, Laravel, Node.js, and Hotwire applications",
8+
description: "AnyCable: a realtime server with delivery guarantees for Rails, Laravel, Node.js, Python, and any backend.",
99

1010
cleanUrls: true,
1111
ignoreDeadLinks: true,
@@ -34,10 +34,10 @@ export default withMermaid(defineConfig({
3434
['link', { rel: 'apple-touch-icon', href: '/assets/images/apple-touch-icon.png' }],
3535
['meta', { name: 'theme-color', content: '#ff5e5e' }],
3636
['meta', { property: 'og:title', content: 'AnyCable Documentation' }],
37-
['meta', { property: 'og:description', content: 'A real-time server for Rails, Laravel, Node.js, and Hotwire applications' }],
37+
['meta', { property: 'og:description', content: 'A realtime server with delivery guarantees for Rails, Laravel, Node.js, Python, and any backend.' }],
3838
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
3939
['meta', { name: 'twitter:site', content: '@any_cable' }],
40-
['meta', { name: 'keywords', content: 'ruby, rails, websockets, real-time, action-cable, anycable, hotwire, laravel' }],
40+
['meta', { name: 'keywords', content: 'anycable, websockets, real-time, realtime server, delivery guarantees, reliable streams, presence, action-cable, ruby, rails, hotwire, laravel, nodejs, python, go' }],
4141
],
4242

4343
themeConfig: {
@@ -47,54 +47,67 @@ export default withMermaid(defineConfig({
4747
},
4848

4949
nav: [
50-
{ text: 'Guide', link: '/getting_started', activeMatch: '/' },
50+
{ text: 'Guide', link: '/overview', activeMatch: '/' },
5151
{ text: 'anycable.io', link: 'https://anycable.io' },
5252
{ text: 'LLMs', link: '/llms-full.txt' },
5353
],
5454

5555
sidebar: [
5656
{
57-
text: 'Guides',
57+
text: 'Start here',
5858
items: [
59-
{ text: 'Getting started', link: '/getting_started' },
60-
{ text: 'Using with Rails', link: '/rails/getting_started' },
61-
{ text: 'Client-side usage', link: '/guides/client-side' },
62-
{ text: 'Using with JavaScript (serverless)', link: '/guides/serverless' },
63-
{ text: 'Using with Hotwire', link: '/guides/hotwire' },
64-
{ text: 'Using with Laravel', link: '/guides/laravel' },
65-
{ text: 'Broadcasting', link: '/anycable-go/broadcasting' },
66-
{ text: 'Signed streams', link: '/anycable-go/signed_streams' },
67-
{ text: 'Reliable streams', link: '/anycable-go/reliable_streams' },
68-
{ text: 'Presence', link: '/anycable-go/presence' },
69-
{ text: 'REST API', link: '/anycable-go/api' },
70-
{ text: 'JWT authentication', link: '/anycable-go/jwt_identification' },
59+
{ text: 'What is AnyCable', link: '/overview' },
60+
{ text: 'Quick start', link: '/quickstart' },
61+
{ text: 'Capabilities', link: '/capabilities' },
7162
{ text: '🔥 Troubleshooting', link: '/troubleshooting' },
7263
]
7364
},
7465
{
75-
text: 'AnyCable PRO',
66+
text: 'By backend',
7667
items: [
77-
{ text: 'Going PRO', link: '/pro' },
78-
{ text: 'Install PRO', link: '/pro/install' },
79-
{ text: 'AnyCable RPC', link: '/anycable-go/rpc' },
80-
{ text: 'Apollo GraphQL', link: '/anycable-go/apollo' },
81-
{ text: 'Binary formats', link: '/anycable-go/binary_formats' },
82-
{ text: 'Long polling', link: '/anycable-go/long_polling' },
83-
{ text: 'OCPP support', link: '/anycable-go/ocpp' },
68+
{ text: 'Rails', link: '/rails/getting_started' },
69+
{ text: 'Laravel', link: '/guides/laravel' },
70+
{ text: 'Node.js (serverless)', link: '/guides/serverless' },
71+
{ text: 'Python & any HTTP backend', link: '/guides/python' },
72+
{ text: 'Hotwire', link: '/guides/hotwire' },
73+
{ text: 'Client-side usage', link: '/guides/client-side' },
74+
]
75+
},
76+
{
77+
text: 'Capabilities',
78+
items: [
79+
{ text: 'Reliable streams & recovery', link: '/anycable-go/reliable_streams' },
80+
{ text: 'Presence', link: '/anycable-go/presence' },
81+
{ text: 'Broadcasting', link: '/anycable-go/broadcasting' },
82+
{ text: 'Signed streams', link: '/anycable-go/signed_streams' },
83+
{ text: 'JWT authentication', link: '/anycable-go/jwt_identification' },
84+
{ text: 'Broker deep dive', link: '/anycable-go/broker' },
85+
{ text: 'Pub/sub (node-node)', link: '/anycable-go/pubsub' },
86+
{ text: 'REST API', link: '/anycable-go/api' },
8487
]
8588
},
8689
{
8790
text: 'Protocols',
8891
items: [
8992
{ text: 'Server-sent events', link: '/anycable-go/sse' },
9093
{ text: 'Pusher', link: '/anycable-go/pusher' },
94+
{ text: 'Apollo GraphQL', link: '/anycable-go/apollo' },
9195
{ text: 'Durable Streams', link: '/anycable-go/durable_streams' },
9296
{ text: 'Long polling', link: '/anycable-go/long_polling' },
9397
{ text: 'OCPP support', link: '/anycable-go/ocpp' },
98+
{ text: 'Binary formats', link: '/anycable-go/binary_formats' },
9499
]
95100
},
96101
{
97-
text: 'Deployment',
102+
text: 'Editions & Pro',
103+
items: [
104+
{ text: 'Editions', link: '/editions' },
105+
{ text: 'Going Pro', link: '/pro' },
106+
{ text: 'Install Pro', link: '/pro/install' },
107+
]
108+
},
109+
{
110+
text: 'Deploy & operate',
98111
items: [
99112
{ text: 'Heroku', link: '/deployment/heroku' },
100113
{ text: 'Fly.io', link: '/deployment/fly' },
@@ -110,6 +123,11 @@ export default withMermaid(defineConfig({
110123
{ text: 'AWS ECS', link: 'https://medium.com/expsoftwareengineering/deploying-ruby-on-rails-with-anycable-using-docker-ecs-80f0da2051ba' },
111124
{ text: 'Load Balancing', link: '/deployment/load_balancing' },
112125
{ text: 'Load Testing', link: '/deployment/load_testing' },
126+
{ text: 'Instrumentation', link: '/anycable-go/instrumentation' },
127+
{ text: 'Health checking', link: '/anycable-go/health_checking' },
128+
{ text: 'Tracing', link: '/anycable-go/tracing' },
129+
{ text: 'OS Tuning', link: '/anycable-go/os_tuning' },
130+
{ text: 'Telemetry', link: '/anycable-go/telemetry' },
113131
]
114132
},
115133
{
@@ -132,20 +150,13 @@ export default withMermaid(defineConfig({
132150
]
133151
},
134152
{
135-
text: 'AnyCable-Go',
153+
text: 'AnyCable-Go (server)',
136154
items: [
137155
{ text: 'Configuration', link: '/anycable-go/configuration' },
156+
{ text: 'All server options', link: '/anycable-go/options' },
138157
{ text: 'AnyCable RPC', link: '/anycable-go/rpc' },
139-
{ text: 'Broker deep dive', link: '/anycable-go/broker' },
140-
{ text: 'Pub/sub (node-node)', link: '/anycable-go/pubsub' },
141-
{ text: 'Instrumentation', link: '/anycable-go/instrumentation' },
142-
{ text: 'Health checking', link: '/anycable-go/health_checking' },
143-
{ text: 'Tracing', link: '/anycable-go/tracing' },
144-
{ text: 'OS Tuning', link: '/anycable-go/os_tuning' },
145-
{ text: 'Signed streams', link: '/anycable-go/signed_streams' },
146158
{ text: 'Embedded NATS', link: '/anycable-go/embedded_nats' },
147159
{ text: 'Using as a library', link: '/anycable-go/library' },
148-
{ text: 'Telemetry', link: '/anycable-go/telemetry' },
149160
]
150161
},
151162
{
@@ -156,7 +167,7 @@ export default withMermaid(defineConfig({
156167
]
157168
},
158169
{
159-
text: 'Misc',
170+
text: 'Reference',
160171
items: [
161172
{ text: 'Benchmarks', link: '/benchmarks' },
162173
{ text: 'Action Cable protocols', link: '/misc/action_cable_protocol' },

docs/.vitepress/theme/layouts/LandingLayout.vue

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
/>
2020
<div class="hero-text">
2121
<h1 class="hero-title">AnyCable Documentation</h1>
22-
<p class="hero-tagline">Realtime server for reliable two-way communication</p>
22+
<p class="hero-tagline">Realtime server with delivery guarantees for Rails, Laravel, Node.js, Python, and any backend</p>
2323
</div>
2424
</div>
2525
<div class="hero-actions">
26-
<a class="btn btn-brand" href="/getting_started">Get Started</a>
26+
<a class="btn btn-brand" href="/quickstart">Get Started</a>
27+
<a class="btn btn-alt" href="/overview">What is AnyCable?</a>
2728
<a
2829
class="btn btn-alt"
2930
href="https://github.com/anycable/anycable"
@@ -47,23 +48,35 @@
4748
</a>
4849
<a class="path-card" href="/guides/laravel">
4950
<h3>Laravel</h3>
50-
<p>Integrate real-time capabilities into your Laravel app</p>
51+
<p>Drop-in replacement for Reverb or Pusher in your Laravel app</p>
52+
</a>
53+
<a class="path-card" href="/guides/serverless">
54+
<h3>Node.js &amp; TypeScript</h3>
55+
<p>Use AnyCable as a real-time server for (serverless) JS apps</p>
56+
</a>
57+
<a class="path-card" href="/guides/python">
58+
<h3>Python</h3>
59+
<p>Power realtime in Django, FastAPI, or any Python backend</p>
5160
</a>
5261
<a class="path-card" href="/guides/hotwire">
5362
<h3>Hotwire</h3>
5463
<p>Build reactive frontends with Turbo Streams and AnyCable</p>
5564
</a>
56-
<a class="path-card" href="/guides/serverless">
57-
<h3>TS/JS</h3>
58-
<p>Use AnyCable as a real-time server for (serverless) JavaScript apps</p>
65+
<a class="path-card" href="/quickstart#any-backend">
66+
<h3>Any backend</h3>
67+
<p>Pub/sub over a plain HTTP API, from any language</p>
5968
</a>
60-
<a class="path-card" href="/anycable-go/pusher">
61-
<h3>Pusher</h3>
62-
<p>Drop-in Pusher-compatible real-time server</p>
69+
</div>
70+
71+
<h2 class="explore-heading">Explore</h2>
72+
<div class="path-grid">
73+
<a class="path-card" href="/capabilities">
74+
<h3>Capabilities</h3>
75+
<p>Delivery guarantees, recovery, presence, and zero-downtime deploys</p>
6376
</a>
64-
<a class="path-card" href="/anycable-go/durable_streams">
65-
<h3>Durable Streams</h3>
66-
<p>Reliable message delivery with automatic catch-up</p>
77+
<a class="path-card" href="/editions">
78+
<h3>Editions</h3>
79+
<p>Open source, Pro, and managed AnyCable+</p>
6780
</a>
6881
</div>
6982
</div>
@@ -288,6 +301,10 @@
288301
margin: 0 0 32px;
289302
}
290303
304+
.getting-started-inner .explore-heading {
305+
margin-top: 48px;
306+
}
307+
291308
.path-grid {
292309
display: grid;
293310
grid-template-columns: repeat(3, 1fr);

docs/anycable-go/broadcasting.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ echo -n 'broadcast-cable' | openssl dgst -sha256 -hmac '<your secret>' | awk '{p
6464
## Redis Pub/Sub
6565

6666
> Enable via `--broadcast_adapter=redis` (or `ANYCABLE_BROADCAST_ADAPTER=redis`).
67+
>
68+
> [Valkey](https://valkey.io), the open-source Redis fork, works as a drop-in alternative for this and the Redis X adapter below.
6769
6870
This broadcaster uses Redis [Pub/Sub](https://redis.io/topics/pubsub) feature under the hood, and, thus, publications are delivered to all subscribed AnyCable servers simultaneously.
6971

docs/anycable-go/configuration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# AnyCable server configuration
22

3+
> Looking for a specific flag? See the [complete server options reference](./options.md) for every option and environment variable.
4+
35
You can configure AnyCable server via CLI options, e.g.:
46

57
```sh
@@ -109,6 +111,8 @@ You can specify on which port to receive broadcasting requests (NOTE: it could b
109111

110112
## Redis configuration
111113

114+
> [Valkey](https://valkey.io), the open-source fork of Redis, works as a drop-in alternative everywhere AnyCable uses Redis. Some features require recent versions: Redis-backed presence needs **Redis 7.4+** or **Valkey 9.0+**.
115+
112116
**--redis_url** (`ANYCABLE_REDIS_URL` or `REDIS_URL`)
113117

114118
Redis URL to connect to (default: `"redis://localhost:6379/5"`). Used by the corresponding pub/sub, broadcasting, and broker adapters.

docs/anycable-go/jwt_identification.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ By default, the `--secret` configuration parameter is used as a JWT secret key.
1818

1919
Other configuration options are:
2020

21-
- (_Optional_) **--jwt_param** (`ANYCABLE_ID_PARAM`, default: "jid"): the name of a query string param or an HTTP header, which carries a token. The header name is prefixed with `X-`.
21+
- (_Optional_) **--jwt_param** (`ANYCABLE_JWT_PARAM`, default: "jid"): the name of a query string param or an HTTP header, which carries a token. The header name is prefixed with `X-`.
2222
- (_Optional_) **--enforce_jwt** (`ANYCABLE_ENFORCE_JWT`, default: false): whether to require all connection requests to contain a token. Connections without a token would be rejected right away. If not set, the servers fallbacks to the RPC call (if RPC is configured) or would be accepted if authentication is disabled (`--noauth`).
2323

2424
A client must provide an identification token either via a query param or via an HTTP header (if possible). For example:

docs/anycable-go/ocpp.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ AnyCable-Go Pro supports OCPP and allows you to _connect_ your charging stations
1414
- The station sends a `BootNotification` request to initialize the connection
1515
- AnyCable transforms this request into several AnyCable RPC calls to match the Action Cable interface:
1616
1) `Authenticate -> Connection#connect` to authenticate the station.
17-
2) `Command{subscribe} -> OCCPChannel#subscribed` to initialize a channel entity to association with this station.
18-
3) `Command{perform} -> OCCPChannel#boot_notification` to handle the `BootNotification` request.
19-
- Subsequent requests from the station are converted into `OCCPChannel` action calls (e.g., `Authorize -> OCCPChannel#authorize`, `StartTransaction -> OCCPChannel#start_transaction`).
17+
2) `Command{subscribe} -> OCPPChannel#subscribed` to initialize a channel entity to association with this station.
18+
3) `Command{perform} -> OCPPChannel#boot_notification` to handle the `BootNotification` request.
19+
- Subsequent requests from the station are converted into `OCPPChannel` action calls (e.g., `Authorize -> OCPPChannel#authorize`, `StartTransaction -> OCPPChannel#start_transaction`).
2020

2121
AnyCable also takes care of heartbeats and acknowledgment messages (unless you send them manually, see below).
2222

@@ -120,7 +120,7 @@ end
120120

121121
### Single-action variant
122122

123-
It's possible to handle all OCCP commands with a single `#receive` method at the channel class. For that, you must configure `anycable-go` to not use granular actions for OCPP:
123+
It's possible to handle all OCPP commands with a single `#receive` method at the channel class. For that, you must configure `anycable-go` to not use granular actions for OCPP:
124124

125125
```sh
126126
anycable-go --ocpp_granular_actions=false
@@ -152,7 +152,7 @@ end
152152
You can send remote commands to stations via Action Cable broadcasts:
153153

154154
```ruby
155-
OCCPChannel.broadcast_to(
155+
OCPPChannel.broadcast_to(
156156
"ev/#{serial_number}",
157157
{
158158
command: "TriggerMessage",

0 commit comments

Comments
 (0)