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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ lefthook-local.yml

# Local Netlify folder
.netlify

# Internal docs-rework working files (not for publication)
DOCS_IMPROVEMENTS_SPEC.md
FACT_CHECK.md
DOCS_NOTES.md
.DS_Store
83 changes: 47 additions & 36 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { availableSinceMarkdownPlugin } from './availableSinceMarkdownPlugin'

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

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

themeConfig: {
Expand All @@ -47,54 +47,67 @@ export default withMermaid(defineConfig({
},

nav: [
{ text: 'Guide', link: '/getting_started', activeMatch: '/' },
{ text: 'Guide', link: '/overview', activeMatch: '/' },
{ text: 'anycable.io', link: 'https://anycable.io' },
{ text: 'LLMs', link: '/llms-full.txt' },
],

sidebar: [
{
text: 'Guides',
text: 'Start here',
items: [
{ text: 'Getting started', link: '/getting_started' },
{ text: 'Using with Rails', link: '/rails/getting_started' },
{ text: 'Client-side usage', link: '/guides/client-side' },
{ text: 'Using with JavaScript (serverless)', link: '/guides/serverless' },
{ text: 'Using with Hotwire', link: '/guides/hotwire' },
{ text: 'Using with Laravel', link: '/guides/laravel' },
{ text: 'Broadcasting', link: '/anycable-go/broadcasting' },
{ text: 'Signed streams', link: '/anycable-go/signed_streams' },
{ text: 'Reliable streams', link: '/anycable-go/reliable_streams' },
{ text: 'Presence', link: '/anycable-go/presence' },
{ text: 'REST API', link: '/anycable-go/api' },
{ text: 'JWT authentication', link: '/anycable-go/jwt_identification' },
{ text: 'What is AnyCable', link: '/overview' },
{ text: 'Quick start', link: '/quickstart' },
{ text: 'Capabilities', link: '/capabilities' },
{ text: '🔥 Troubleshooting', link: '/troubleshooting' },
]
},
{
text: 'AnyCable PRO',
text: 'By backend',
items: [
{ text: 'Going PRO', link: '/pro' },
{ text: 'Install PRO', link: '/pro/install' },
{ text: 'AnyCable RPC', link: '/anycable-go/rpc' },
{ text: 'Apollo GraphQL', link: '/anycable-go/apollo' },
{ text: 'Binary formats', link: '/anycable-go/binary_formats' },
{ text: 'Long polling', link: '/anycable-go/long_polling' },
{ text: 'OCPP support', link: '/anycable-go/ocpp' },
{ text: 'Rails', link: '/rails/getting_started' },
{ text: 'Laravel', link: '/guides/laravel' },
{ text: 'Node.js (serverless)', link: '/guides/serverless' },
{ text: 'Python & any HTTP backend', link: '/guides/python' },
{ text: 'Hotwire', link: '/guides/hotwire' },
{ text: 'Client-side usage', link: '/guides/client-side' },
]
},
{
text: 'Capabilities',
items: [
{ text: 'Reliable streams & recovery', link: '/anycable-go/reliable_streams' },
{ text: 'Presence', link: '/anycable-go/presence' },
{ text: 'Broadcasting', link: '/anycable-go/broadcasting' },
{ text: 'Signed streams', link: '/anycable-go/signed_streams' },
{ text: 'JWT authentication', link: '/anycable-go/jwt_identification' },
{ text: 'Broker deep dive', link: '/anycable-go/broker' },
{ text: 'Pub/sub (node-node)', link: '/anycable-go/pubsub' },
{ text: 'REST API', link: '/anycable-go/api' },
]
},
{
text: 'Protocols',
items: [
{ text: 'Server-sent events', link: '/anycable-go/sse' },
{ text: 'Pusher', link: '/anycable-go/pusher' },
{ text: 'Apollo GraphQL', link: '/anycable-go/apollo' },
{ text: 'Durable Streams', link: '/anycable-go/durable_streams' },
{ text: 'Long polling', link: '/anycable-go/long_polling' },
{ text: 'OCPP support', link: '/anycable-go/ocpp' },
{ text: 'Binary formats', link: '/anycable-go/binary_formats' },
]
},
{
text: 'Deployment',
text: 'Editions & Pro',
items: [
{ text: 'Editions', link: '/editions' },
{ text: 'Going Pro', link: '/pro' },
{ text: 'Install Pro', link: '/pro/install' },
]
},
{
text: 'Deploy & operate',
items: [
{ text: 'Heroku', link: '/deployment/heroku' },
{ text: 'Fly.io', link: '/deployment/fly' },
Expand All @@ -110,6 +123,11 @@ export default withMermaid(defineConfig({
{ text: 'AWS ECS', link: 'https://medium.com/expsoftwareengineering/deploying-ruby-on-rails-with-anycable-using-docker-ecs-80f0da2051ba' },
{ text: 'Load Balancing', link: '/deployment/load_balancing' },
{ text: 'Load Testing', link: '/deployment/load_testing' },
{ text: 'Instrumentation', link: '/anycable-go/instrumentation' },
{ text: 'Health checking', link: '/anycable-go/health_checking' },
{ text: 'Tracing', link: '/anycable-go/tracing' },
{ text: 'OS Tuning', link: '/anycable-go/os_tuning' },
{ text: 'Telemetry', link: '/anycable-go/telemetry' },
]
},
{
Expand All @@ -132,20 +150,13 @@ export default withMermaid(defineConfig({
]
},
{
text: 'AnyCable-Go',
text: 'AnyCable-Go (server)',
items: [
{ text: 'Configuration', link: '/anycable-go/configuration' },
{ text: 'All server options', link: '/anycable-go/options' },
{ text: 'AnyCable RPC', link: '/anycable-go/rpc' },
{ text: 'Broker deep dive', link: '/anycable-go/broker' },
{ text: 'Pub/sub (node-node)', link: '/anycable-go/pubsub' },
{ text: 'Instrumentation', link: '/anycable-go/instrumentation' },
{ text: 'Health checking', link: '/anycable-go/health_checking' },
{ text: 'Tracing', link: '/anycable-go/tracing' },
{ text: 'OS Tuning', link: '/anycable-go/os_tuning' },
{ text: 'Signed streams', link: '/anycable-go/signed_streams' },
{ text: 'Embedded NATS', link: '/anycable-go/embedded_nats' },
{ text: 'Using as a library', link: '/anycable-go/library' },
{ text: 'Telemetry', link: '/anycable-go/telemetry' },
]
},
{
Expand All @@ -156,7 +167,7 @@ export default withMermaid(defineConfig({
]
},
{
text: 'Misc',
text: 'Reference',
items: [
{ text: 'Benchmarks', link: '/benchmarks' },
{ text: 'Action Cable protocols', link: '/misc/action_cable_protocol' },
Expand Down
41 changes: 29 additions & 12 deletions docs/.vitepress/theme/layouts/LandingLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
/>
<div class="hero-text">
<h1 class="hero-title">AnyCable Documentation</h1>
<p class="hero-tagline">Realtime server for reliable two-way communication</p>
<p class="hero-tagline">Realtime server with delivery guarantees for Rails, Laravel, Node.js, Python, and any backend</p>
</div>
</div>
<div class="hero-actions">
<a class="btn btn-brand" href="/getting_started">Get Started</a>
<a class="btn btn-brand" href="/quickstart">Get Started</a>
<a class="btn btn-alt" href="/overview">What is AnyCable?</a>
<a
class="btn btn-alt"
href="https://github.com/anycable/anycable"
Expand All @@ -47,23 +48,35 @@
</a>
<a class="path-card" href="/guides/laravel">
<h3>Laravel</h3>
<p>Integrate real-time capabilities into your Laravel app</p>
<p>Drop-in replacement for Reverb or Pusher in your Laravel app</p>
</a>
<a class="path-card" href="/guides/serverless">
<h3>Node.js &amp; TypeScript</h3>
<p>Use AnyCable as a real-time server for (serverless) JS apps</p>
</a>
<a class="path-card" href="/guides/python">
<h3>Python</h3>
<p>Power realtime in Django, FastAPI, or any Python backend</p>
</a>
<a class="path-card" href="/guides/hotwire">
<h3>Hotwire</h3>
<p>Build reactive frontends with Turbo Streams and AnyCable</p>
</a>
<a class="path-card" href="/guides/serverless">
<h3>TS/JS</h3>
<p>Use AnyCable as a real-time server for (serverless) JavaScript apps</p>
<a class="path-card" href="/quickstart#any-backend">
<h3>Any backend</h3>
<p>Pub/sub over a plain HTTP API, from any language</p>
</a>
<a class="path-card" href="/anycable-go/pusher">
<h3>Pusher</h3>
<p>Drop-in Pusher-compatible real-time server</p>
</div>

<h2 class="explore-heading">Explore</h2>
<div class="path-grid">
<a class="path-card" href="/capabilities">
<h3>Capabilities</h3>
<p>Delivery guarantees, recovery, presence, and zero-downtime deploys</p>
</a>
<a class="path-card" href="/anycable-go/durable_streams">
<h3>Durable Streams</h3>
<p>Reliable message delivery with automatic catch-up</p>
<a class="path-card" href="/editions">
<h3>Editions</h3>
<p>Open source, Pro, and managed AnyCable+</p>
</a>
</div>
</div>
Expand Down Expand Up @@ -288,6 +301,10 @@
margin: 0 0 32px;
}

.getting-started-inner .explore-heading {
margin-top: 48px;
}

.path-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
Expand Down
2 changes: 2 additions & 0 deletions docs/anycable-go/broadcasting.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ echo -n 'broadcast-cable' | openssl dgst -sha256 -hmac '<your secret>' | awk '{p
## Redis Pub/Sub

> Enable via `--broadcast_adapter=redis` (or `ANYCABLE_BROADCAST_ADAPTER=redis`).
>
> [Valkey](https://valkey.io), the open-source Redis fork, works as a drop-in alternative for this and the Redis X adapter below.

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.

Expand Down
4 changes: 4 additions & 0 deletions docs/anycable-go/configuration.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# AnyCable server configuration

> Looking for a specific flag? See the [complete server options reference](./options.md) for every option and environment variable.

You can configure AnyCable server via CLI options, e.g.:

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

## Redis configuration

> [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+**.

**--redis_url** (`ANYCABLE_REDIS_URL` or `REDIS_URL`)

Redis URL to connect to (default: `"redis://localhost:6379/5"`). Used by the corresponding pub/sub, broadcasting, and broker adapters.
Expand Down
2 changes: 1 addition & 1 deletion docs/anycable-go/jwt_identification.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ By default, the `--secret` configuration parameter is used as a JWT secret key.

Other configuration options are:

- (_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-`.
- (_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-`.
- (_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`).

A client must provide an identification token either via a query param or via an HTTP header (if possible). For example:
Expand Down
10 changes: 5 additions & 5 deletions docs/anycable-go/ocpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ AnyCable-Go Pro supports OCPP and allows you to _connect_ your charging stations
- The station sends a `BootNotification` request to initialize the connection
- AnyCable transforms this request into several AnyCable RPC calls to match the Action Cable interface:
1) `Authenticate -> Connection#connect` to authenticate the station.
2) `Command{subscribe} -> OCCPChannel#subscribed` to initialize a channel entity to association with this station.
3) `Command{perform} -> OCCPChannel#boot_notification` to handle the `BootNotification` request.
- Subsequent requests from the station are converted into `OCCPChannel` action calls (e.g., `Authorize -> OCCPChannel#authorize`, `StartTransaction -> OCCPChannel#start_transaction`).
2) `Command{subscribe} -> OCPPChannel#subscribed` to initialize a channel entity to association with this station.
3) `Command{perform} -> OCPPChannel#boot_notification` to handle the `BootNotification` request.
- Subsequent requests from the station are converted into `OCPPChannel` action calls (e.g., `Authorize -> OCPPChannel#authorize`, `StartTransaction -> OCPPChannel#start_transaction`).

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

Expand Down Expand Up @@ -120,7 +120,7 @@ end

### Single-action variant

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:
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:

```sh
anycable-go --ocpp_granular_actions=false
Expand Down Expand Up @@ -152,7 +152,7 @@ end
You can send remote commands to stations via Action Cable broadcasts:

```ruby
OCCPChannel.broadcast_to(
OCPPChannel.broadcast_to(
"ev/#{serial_number}",
{
command: "TriggerMessage",
Expand Down
Loading
Loading