docs: reposition around ICP, use cases, and delivery guarantees#59
Conversation
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.
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.
1b9d068 to
fc1a098
Compare
- 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
Found via the flag audit cross-checking documented flags against `anycable-go --help`. The adjacent ANYCABLE_BROADCAST_KEY confirms the fix.
- 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.
- 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)
irinanazarova
left a comment
There was a problem hiding this comment.
Strong repositioning PR with accurate, well-verified core content, but three copy-paste/accuracy issues in the use-case pages should be fixed before merge. I read every new page top-to-bottom, traced the reader journeys, and cross-checked flags, defaults, and the signing/JWT code against the source pages. CI is green on a base equal to current master (no rebase risk).
Correctness
🔴 live-dashboards.md:42 — BROADCAST_URL is undefined
def publish(stream, payload):
httpx.post(BROADCAST_URL, json={"stream": stream, "data": json.dumps(payload)})BROADCAST_URL is referenced as a global but never defined or imported, so a copy-paste reader hits a NameError on the first publish. The sibling page does it correctly: ai-streaming.md:49 uses url = os.environ["ANYCABLE_BROADCAST_URL"]. Define it the same way here, and reuse the same env var name for cross-page consistency.
🔴 live-dashboards.md:71-73 — benchmark figures contradict the rest of the docs
The page claims "1M messages to 10K subscribers at a 4 ms median, against 155 ms for default Socket.IO." The canonical figure everywhere else is 3 ms median / 11 ms p99 at 10,000 subscribers (Pro) (capabilities.md:107, overview.md:41). The "4 ms," the "155 ms" Socket.IO number, and the "1M messages" framing appear in no other page or in benchmarks.md, and the (Pro) qualifier is dropped here. Reuse the exact figure and the Pro caveat from capabilities.md, or drop the specific numbers and link to the benchmark.
🔴 ai-streaming.md:34-37 + :85 — dev command omits --public, client uses an unsigned stream
The shown command is anycable-go --presets=broker --broadcast_adapter=http; --public lives only in an inline comment, not in the runnable command. Step 3 then subscribes with a plain, unsigned cable.streamFrom('ai/conversation/...'). Per signed_streams.md, unsigned streamFrom is rejected unless --public/--public_streams is set. A reader who copy-pastes the command verbatim gets rejected subscriptions. Promote --public into the shown dev command (as quickstart.md already does), or state explicitly that step 3 requires it.
Concerns and inconsistencies
🟡 PR body overstates the Node signing claim
The body says signed-stream signing was verified "Node + Python, byte-identical." On guides/python.md the JS block (:78-81) is a client-side streamFromSigned subscription, not signing code; only Python signing is demonstrated there. The Node signing example lives in signed_streams.md:116-121 (verified correct). Accurate overall, but the page shows less than the body implies.
🟡 publish() helper is defined only in live-dashboards.md
It is called in gps-dispatch.md:43 and telehealth.md:71 with no definition or back-reference. Each page should stand alone; inline the helper or point back to its definition.
🟡 quickstart.md:101 — promised output may not match
The page shows the client logging received { text: 'Hello, world!' } (a parsed object), but broadcasting.md:131 documents data as a string. Whether @anycable/web auto-parses the payload determines if this is right. Confirm the decoder behavior, or soften the claim.
🟡 gps-dispatch.md:98-99 — OCPP overstated
"AnyCable Pro also speaks OCPP and other WebSocket subprotocols." Per ocpp.md, OCPP is alpha and v1.6-only, and there is no documented list of "other WebSocket subprotocols." Drop the vague clause and consider noting OCPP is alpha.
🟡 telehealth.md:36 — on-premise prose links to the Heroku guide
The sentence is about self-hosting and isolated environments but links to deployment/heroku.md (a managed PaaS). Link to a general/self-host deployment page or the deployment index.
🟡 getting_started.md pointer is shadowed by a forced redirect
getting_started.md was rewritten into a helpful pointer page, but _redirects adds /getting_started /quickstart 301!. The ! forces the redirect even though the page exists, so the pointer body is never served. Either drop the ! (so the pointer shows) or trim the page to a minimal stub. The in-page anchor links (#install, #any-backend) do resolve.
🟡 Valkey/Redis presence version floor is unverified
configuration.md and reliable_streams.md consistently state Redis-backed presence needs Redis 7.4+ or Valkey 9.0+. The two pages agree, but please confirm the Valkey 9.0+ floor is correct.
🟡 live-dashboards.md:91-92 — names "public streams" without the flag
Unlike the signed-streams note above it, this line does not name --public_streams / ANYCABLE_PUBLIC_STREAMS or link signed_streams.md. Add the flag or link.
Verified correct (spot-checks)
- 🟢 All internal links and anchors resolve across every new page (overview, quickstart, capabilities, use-cases ×5, python, editions), and all 9 new pages are wired into the
config.mtssidebar. - 🟢 Signing code is byte-identical to
signed_streams.mdfor both Node and Python (HMAC-SHA256, base64,{encoded}--{digest}). JWT auth matchesjwt_identification.md(extclaim,exp, HS256). Protobuf example matchesbinary_formats.md. - 🟢 Flags/defaults verified against source:
--public(default false),--presence_ttl15s,--presets=broker,--broadcast_adapter=http, port8090behavior,--pusher_secretfalling back to--secret. - 🟢 The 4 repointed broken links (laravel, serverless, rpc, non_rails) all resolve now; the serverless one was a malformed non-link.
pro.md/ocpp.mdOCCP→OCPP fixes and thearchitecture.mdtypo fix are correct. - 🟢 ICP framing is consistently strong: any-backend/standalone pub/sub leads, Python and Node shown side by side, Rails content explicitly labeled rather than assumed.
Recommendation
Ship after the three 🔴 items (live-dashboards.md undefined BROADCAST_URL, live-dashboards.md benchmark figures, ai-streaming.md --public). The benchmark inconsistency is the gating one, since it states a different latency than two other pages in the same set. The 🟡 items are worth a pass but do not block.
- 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
- 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
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.
irinanazarova
left a comment
There was a problem hiding this comment.
Re-review on 4868299: the three first-round 🔴 items are resolved, and a consistency sweep surfaced one more instance of the same class, now fixed. Ship it.
Base sanity: PR base 7746315 equals current origin/master, cut from current master, no rebase risk. CI green (forspell/lychee/markdownlint/rubocop).
Accuracy
🔴 → fixed this pass — unsigned streamFrom without --public was systemic
The first review caught this only in ai-streaming.md. Tracing the same reader journey across the sibling pages, live-dashboards.md, gps-dispatch.md, and telehealth.md all ran anycable-go --presets=broker --broadcast_adapter=http (no --public) and then subscribed with unsigned cable.streamFrom('...'). Per signed_streams.md, those subscriptions are rejected without --public/--public_streams, so a copy-paste reader hit rejected subscriptions on three more pages. Fixed in 4868299: --public promoted into each dev command with a local-dev-only caveat pointing to signed streams + JWT for production.
Verified fixed (first-round items)
- 🟢
live-dashboards.mdBROADCAST_URLis now defined fromos.environ["ANYCABLE_BROADCAST_URL"], consistent with the sibling pages. - 🟢
live-dashboards.mdbenchmark figure is scoped to the broadcast-throughput test (10K subs, 1M msgs, 40 publishers) and explicitly distinguished from the latency numbers, no longer reads as a contradiction. - 🟢
ai-streaming.mddev command includes--publicwith the unsigned-stream caveat. - 🟢
gps-dispatch.md/telehealth.mdPython broadcast blocks are now self-contained (import os, json, httpx+BROADCAST_URL+publish), runnable as written. - 🟢 OCPP claim narrowed to "EV-charging, OCPP WebSocket protocol (alpha)"; vague "other subprotocols" dropped.
- 🟢
telehealth.mdon-premise prose links to Docker/Kubernetes, not Heroku. - 🟢
_redirects: forced301!on/getting_starteddropped, so the pointer page renders; the#install/#any-backendanchors resolve.
Reader experience
A dashboards reader now runs the server with --public, defines publish with a real BROADCAST_URL, and subscribes with streamFrom('market/AAPL') — the full copy-paste sequence reaches a working result. Same for the GPS-dispatch and telehealth journeys.
Recommendation
Ship it. No remaining 🔴. The deep per-page read of the existing (non-PR) pages continues separately as noted in the PR body.
irinanazarova
left a comment
There was a problem hiding this comment.
Strong, accurate repositioning PR. The new front-door pages (overview, quickstart, capabilities), the four use-case guides, the Python guide, and the generated options reference are technically sound and well wired into the IA. I found no broken links, no dead-end instructions, and no code that won't run. Two small reference-table nits and a couple of reader-experience notes, all below the merge line.
Accuracy
Cross-checked the load-bearing claims against the actual source pages, not memory:
- 🟢 Signing algorithm (
quickstart.md,guides/python.md): Node and Python HMAC-SHA256 snippets are byte-identical tosigned_streams.md(standard base64 of the JSON-encoded name,--separator, hex digest). - 🟢 JWT (
guides/python.md):?jid=param,extclaim with JSON-encoded identifiers,--jwt_secret,--enforce_jwtall matchjwt_identification.md. - 🟢 Broadcasting: port
8090,/_broadcast,{"stream","data"}payload,201 Created, "moves off main port when no auth configured" all matchbroadcasting.md. - 🟢 Protocol/feature names:
actioncable-v1-ext-json,confirm_history/reject_history,presence.join/info(),{type, id, info}event shape,--presets=broker,--presence_ttldefault 15s,--history_limit100 /--history_ttl300 — all verified againstreliable_streams.md,action_cable_protocol.md,broker.md,presence.md,options.md. - 🟢 Benchmark numbers internally consistent across
overview↔capabilities↔editions.
🟡 --jwt_param env var contradicts the existing JWT page
anycable-go/options.md lists the env as ANYCABLE_JWT_PARAM, but the existing anycable-go/jwt_identification.md documents the same flag's env as ANYCABLE_ID_PARAM. One is wrong, and the PR now ships both. options.md is generated from --help, so it's the likelier-correct one (i.e. jwt_identification.md may be stale), but this should be reconciled. It slipped the verification pass because the examples use the jid query param, never the env var.
🟡 Mangled default cell in the options table
anycable-go/options.md, --enats_max_payload row — the Default column reads 1048576 = 1MB) (default: 0, a --help parsing artifact where description text leaked into the column. The real default is 0. Worth cleaning since this page is the precise lookup reference.
Reader experience
- 🟢 Python persona, end-to-end: homepage Python card → architecture diagram → run server → JWT issue → stream signing → HTTP broadcast. Each step maps to a real reference page; the flow works copy-paste.
- 🟡
$ANYCABLE_SECRETis referenced but never set in an example. Bothquickstart.md(Secure it) andguides/python.md(step 1) invokeanycable-go --jwt_secret=$ANYCABLE_SECRET ...and require a ≥32-byte key, but no snippet showsexport ANYCABLE_SECRET=.... A newcomer copy-pasting with the var unset starts the server with an empty secret. A one-lineexportbefore the run command closes it.
Links / lint / spelling / structure
- 🟢 Every internal link added by the new pages resolves; the three cross-page anchors slugify correctly (
reliable_streams#resumed-sessions-vs-disconnect-callbacks,configuration#slow-drain-mode,broadcasting#securing-http-endpoint). - 🟢 All repointed old links land on existing quickstart anchors (
#install,#any-backend); docsify-style?id=and bare-bracket broken links are properly fixed.getting_started→/quickstart301 and OCCP→OCPP redirect are in_redirects. - 🟢 OCCP→OCPP fixes in
ocpp.md/pro.mdcorrect; no orphanedoccp.md; gps-dispatch's "OCPP (currently alpha)" matchesocpp.md. - 🟢 All new pages + use-case index wired into the
config.mtssidebar; cards removed from the landing (Pusher, Durable Streams) still live under Protocols, so nothing is orphaned. - 🟢
forspell.dictadditions cover the new terms; therelease_notes.md/architecture.mdtypo fixes are all genuine. - 🟢 Base is current (cut from latest
master); all fourdocs-lintchecks green.
Recommendation
Ship after the two reference-table fixes (--jwt_param env reconciliation and the --enats_max_payload default cell), both confined to options.md/jwt_identification.md. The $ANYCABLE_SECRET export is a nice-to-have, not a gate. Everything else is accurate and reader-ready.
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.
irinanazarova
left a comment
There was a problem hiding this comment.
Re-review on 1fcd769: both 🟡 reference-table items fixed (one verified against the running binary), plus the optional secret-export note. Ship it.
Fixed
🟡 → fixed — --jwt_param env var reconciled (verified empirically)
Confirmed against anycable-go directly rather than picking a side:
ANYCABLE_JWT_PARAM=token→ startup logsJWT authentication is enabled (param: token)ANYCABLE_ID_PARAM=token→ logsparam: jid(ignored)
So options.md was correct and jwt_identification.md was stale. Fixed jwt_identification.md to ANYCABLE_JWT_PARAM. No other ANYCABLE_ID_PARAM references remain in the docs.
🟡 → fixed — --enats_max_payload default cell
The Default cell held a --help parsing artifact (1048576 = 1MB) (default: 0) where the binary's help text carries two (default: ...) fragments. Real default is 0; cell now reads 0 with the description "(0 uses the NATS default of 1MB)".
🟢 (optional, done) — $ANYCABLE_SECRET export
Both quickstart.md (Secure it) and guides/python.md (step 1) now show export ANYCABLE_SECRET=$(openssl rand -hex 32) before the run command, so a copy-paste reader doesn't start the server with an empty secret. Note the ≥32-byte guidance is satisfied by the hex-32 value.
CI green (forspell/lychee/markdownlint/rubocop); base still equals current master.
Recommendation
Ship it. No remaining 🔴 or 🟡 from any of the three review passes.
irinanazarova
left a comment
There was a problem hiding this comment.
Strong, carefully-verified repositioning PR. The IA restructure, new front-door pages, and use-case guides are accurate, internally consistent, and cleanly wired into the sidebar. I traced links, anchors, code snippets, and the benchmark numbers across pages and found no blockers, just two small decisions worth making before merge.
Branch state
- 🟢 PR base
7746315is even withorigin/master(zero commits since). No rebase risk. - 🟢 CI green: forspell, lychee, markdownlint, rubocop all pass.
Accuracy
🟢 Facts cross-checked against source, not memory
- Port 8090 default for the HTTP broadcast endpoint when no auth is set: confirmed in
broadcasting.md. The quickstart, Python guide, and all use-case pages use it consistently. ANYCABLE_JWT_PARAM(thejwt_identification.mdfix fromANYCABLE_ID_PARAM): matches the generated--helpreference inoptions.md(--jwt_param→ANYCABLE_JWT_PARAM). Correct.- Signed-stream algorithm is byte-identical between the Node and Python snippets (
base64(JSON.stringify(name))+--+ HMAC-SHA256 hex). The PR-body claim holds. - Protobuf snippet in
capabilities.mdmatchesbinary_formats.mdexactly (@anycable/protobuf-encoder,actioncable-v1-protobuf). - All cross-page anchors resolve, including the ones under lychee-excluded paths that CI does not check:
reliable_streams.md#resumed-sessions-vs-disconnect-callbacks,configuration.md#slow-drain-mode,signed_streams.md#public-unsigned-streams,broadcasting.md#securing-http-endpoint, plusbroker.mdandruby/http_rpc.mdexist. - Benchmark numbers are consistent across
overview.md,capabilities.md,editions.md, andpro.md(822,037 Pro / 821,877 OSS; ~18 KB / ~34 KB; 100% delivery vs 13-15% loss).live-dashboards.mdeven preempts the apparent latency-vs-throughput conflict with an explicit note.
🟡 OCPP heartbeat flag spelling diverges from the shipped Pro binary
options.md documents --ocpp_heartbeat_interval / ANYCABLE_OCPP_HEARTBEAT_INTERVAL (corrected spelling). The PR body notes the current Pro binary actually emits the misspelled --ocpp_hearbeat_interval and the docs assume a binary fix. A reader on a current Pro build who copies the documented flag would hit an "unknown flag" error. This is self-flagged, so not a blocker, but since it's the one row where the reference knowingly doesn't match the shipped artifact, I'd add a short inline caveat in that table row (or confirm the fixed binary has shipped before merge).
🟡 getting_started has both a pointer page and a 301 redirect
getting_started.md is gutted to a "This page has moved" pointer with links, and _redirects adds /getting_started → /quickstart 301. Netlify serves a matching static file before applying non-forced redirect rules, so the file wins: the redirect never fires and readers see the pointer page, not /quickstart. That's functional, but the two mechanisms express opposite intent (the redirect comment says "merged into the Quick Start"). Pick one: keep the pointer and drop the /getting_started redirect line, or delete the pointer content and rely on the 301.
Reader experience
- 🟢 Traced the any-backend quickstart end-to-end (install →
--public --broadcast_adapter=http→streamFrom('chat/1')→curlbroadcast → client logs the parsed payload). It reaches a working round trip with the$pubsubchannel and stream identifier consistent withsigned_streams.md. - 🟢 Traced the Python guide (run server → issue
ext-claim JWT → sign stream →httpx.postbroadcast). Each of the three moving parts is internally consistent and matches the standalone model. - 🟡 (low priority) The use-case JS snippets use
createCable({ protocol: 'actioncable-v1-ext-json' })with no URL. That matches existing house style (presence.md,reliable_streams.md), so it's consistent, but those existing usages sit in Rails-flavored contexts with anaction-cable-urlmeta tag, whereas these pages target standalone Node/Python readers who have none. Consider passing the explicit URL (as the quickstart does) for this persona, or it can stay as-is for consistency.
Links / lint / spelling
- 🟢 New pages all wired into
config.mts(overview, quickstart, capabilities, editions, python, options, and the four use-cases + index). Nav front door repointed to/overview. - 🟢
_redirectscovers the restructure including the new/occp → /ocppand/getting_started//anycable-go/getting_started → /quickstartrules. No leftoverOCCP/occpreferences in source. - 🟢 forspell dict additions look right for the new jargon; CI confirms.
Nits
- 🟢
capabilities.mdsays signing is "identical across Ruby, Node, Python, and PHP";python.mdsays "Ruby, Node, and PHP" (drops Python in the Python guide). Trivial wording symmetry, optional. - 🟢
--versionshows1.6.7in quickstart whileoptions.mdis generated from1.6.14; explained in the PR body, so acknowledged rather than flagged.
Recommendation
Ship after two quick decisions: (1) resolve the getting_started pointer-vs-301 duplication, and (2) add an inline caveat on the --ocpp_heartbeat_interval row (or confirm the fixed Pro binary shipped). Both are minor; nothing here blocks on accuracy or broken links.
- 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
irinanazarova
left a comment
There was a problem hiding this comment.
Re-review on 1e934e5: both 🟡 decisions resolved and the low-priority reader-experience nit applied. Ship it.
Fixed
🟡 → fixed — getting_started pointer vs 301
Removed the no-op /getting_started → /quickstart 301 line from _redirects (Netlify served the pointer file before the non-forced rule anyway, so it never fired). Kept the pointer page as the single mechanism, and kept /anycable-go/getting_started → /quickstart 301 (that nested path has no static file, so it redirects correctly). The two mechanisms no longer express opposite intent.
🟡 → fixed — OCPP heartbeat flag caveat
Added an inline caveat to the --ocpp_heartbeat_interval row in options.md: current Pro builds (≤ 1.6.14-pro) spell it --ocpp_hearbeat_interval / ANYCABLE_OCPP_HEARBEAT_INTERVAL (the known typo), so a reader on a current build sees the working spelling instead of hitting "unknown flag." The corrected name stays documented as the target.
🟡 (low priority) → applied — explicit WebSocket URL for the standalone persona
The four use-case JS snippets now pass createCable('ws://localhost:8080/cable', { protocol: 'actioncable-v1-ext-json' }). These pages target standalone Node/Python readers with no action-cable-url meta tag, so the explicit URL makes them copy-paste-runnable rather than relying on a meta tag that doesn't exist in that context. Matches the quickstart.
The two 🟢 wording nits (Python-in-the-list symmetry, 1.6.7 vs 1.6.14 version) are left as-is, both acknowledged in earlier passes as cosmetic.
CI green (forspell/lychee/markdownlint/rubocop); base still even with current master.
Recommendation
Ship it. Four review passes, no open 🔴 or 🟡.
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.
Soul/house-style review (post-#59): - drop the decorative architecture ASCII diagram (the intro already states the flow: issue a token, sign streams, POST broadcasts; AnyCable owns the socket) - drop the meta '## Verified behavior' section (docs shouldn't narrate their QA) - add a 'That's it.' payoff after the broadcast step No content/accuracy change; tightens the guide toward the house style.
Summary
Aligns the documentation with the current anycable.io positioning, a multi-language realtime server whose differentiator is delivery guarantees, rather than the older "faster Action Cable for Rails" framing the docs carried.
What's included
New front door
overview.md— what AnyCable is, value prop, the two integration styles, editionsquickstart.md— stack picker (any backend / Rails / Laravel / Node / Python), standalone pub/sub as a first-class pathcapabilities.md— maps each homepage promise to its docs, with benchmark numbersMulti-language & editions
guides/python.md— Python and any-HTTP-backend patheditions.md— OSS / Pro / AnyCable+ with a feature matrixReference & structure
anycable-goserver options reference (/anycable-go/options), generated from--help(OSS v1.6.14 + a Pro-only section)description/OG/keywords updated for Python + delivery-guarantee languageFixes (incl. fact-check pass)
getting_started.md→ Quick Start pointer; repointed 4 long-broken linkspro.md/ocpp.mdOCCP→OCPP typos;--broadast_key,ANYCABLE_ID_PARAM→ANYCABLE_JWT_PARAM, and several prose typos across the treeVerification
Every new page was checked against a running anycable-go (1.6.7; options reference regenerated on 1.6.14): standalone pub/sub round trips, signed-stream signing (Python, byte-identical to the Node example in
signed_streams.md), message recovery via history replay, presence (real@anycable/coreSDK), and Python JWT auth (including verifyingANYCABLE_JWT_PARAMis the honored env var). Production build passes, forspell/markdownlint are clean across the tree, and all internal links resolve.Notes
OCCPsection header,--ocpp_hearbeat_interval); docs use the corrected spelling with an inline caveat for current builds.