FluxyChat

Concepts

Rooms, primitives, and how people and agents share one room Durable Object.

FluxyChat is the realtime room for your product: a Cloudflare Durable Object plus D1. Chat and presence share a JSON WebSocket; Yjs uses a second binary connection to the same object. Your auth, your backend, your data model stay yours. We mint member JWTs (or a public-room guest session) and fan out events.

Think of a room as the artifact in your app: a document, a board, a deal, a classroom, a vehicle dispatch view. Map roomId to that artifact.

Building blocks

ConceptFluxyChat
ProjectTenant. API keys (fc_…, server-only), rooms, agents, quotas.
RoomOne Durable Object. Chat JSON WebSocket; Yjs is a second binary connection on the same /ws/room/:id route.
PrimitivesPresence, Broadcast, Storage, Feeds, Threads, Chat, Polls, Derived, Visibility.
UsersHumans (member JWT or guest) and AI (copilot, room peer, workflow).
FeaturesComments, multiplayer editors, notifications, copilots, AI collaboration.
PlatformWorker, dashboard, @fluxy-chat/sdk, react, ui, ui-kit, vue, svelte.

Primitives (pick the right one)

PrimitiveMeansAPIStored?
PresenceNow: who is here, cursors, selections, agentStatussendCursor, useMyPresence / presence_patch, presenceMembersNo
BroadcastPulse: one-shot signalssendClientEvent / useBroadcastEventNo
StorageThe documentFluxyYjsProvider, useStorage, useMutation, LiveFileYes (Yjs on the room DO)
FeedsActivity / agent / n8n logsuseFeeds, POST /rooms/:id/feedsYes (D1, ≠ chat)
ThreadsContextual commentsuseThreads, /comment-threadsYes
ChatTimeline + nested repliesuseChat, useThread, parentIdYes
PollsBallots on the timeline (and /polls records)createPoll / votePoll, POST /polls isAnonymousYes
DerivedLate-joiner JSON bag (not a CRDT)setDerivedState / derivedStateYes (DO storage)
VisibilityWho may see a chat linevisibility / visibleTo on sendYes (D1)

Do not put 60 Hz pointers on Broadcast. Do not mix Feeds with messages. Do not mix comment pins (useThreads) with chat parentId replies (useThread). Do not hide private lines only in the UI. Set visibility on send.

Wire limits and v1 non-goals: Wire protocol.

Two kinds of AI

KindAPIWrites
Copilot (side panel)RegisterAiKnowledge + useAiChat + <AiChat />Local UI only (keyless mock)
Room peerinvokeAgent on useChatChat messages
WorkflowAPI key POST …/feeds/…/messagesFeed + server_event

Auth

Browser: publishableKey (pk_) on FluxyRealtimeProvider (anonymous JWT via POST /tokens/anonymous), member JWT, or FluxyChatClient.joinPublicRoomAsGuest(workerUrl, publicRoomId) (stable guestKey in localStorage). Guest writes are on by default; set PUBLIC_GUEST_READ_ONLY=true to lock.
Server: project API key (fc_…) mints member JWTs (POST /auth/token). pk_ is rejected there (403). Never put fc_… in the client.

Verticals on the same bus

IoT, fleet, game ticks, voice stage, deal quorum: all server_event or chat on the same room WebSocket. Gallery has a copy-paste app for each.

Next: Getting started · CLI and examples

On this page