Skip to content

Repository files navigation

actor-chat

One real-time chat app, built three ways — to study how the actor model maps onto different language/runtime ecosystems. All implementations speak the same WebSocket protocol, persist to the same kind of Convex backend, authenticate with the same Clerk setup, and are driven by the same React frontend, so you can run any one behind an identical UI.

ImplementationActor runtimeHTTP/WSPortStatus
go-actor-chat/anthdm/hollywoodecho + coder/websocket8080working
rust-actor-chat/hand-rolled tokio (mpsc/oneshot)axum8090working
zig-actor-chat/InkListhttpz + websocket.zig8100working

Each subproject has its own detailed README and run guide. Go and Rust ship self-contained convex/ + web/; the Zig server reuses those (point VITE_WS_URL_ZIG at :8100).

The shared design

All servers are stateless real-time relays. Ephemeral state — room presence and typing indicators — lives in the actors; durable state — users, rooms, memberships, messages — lives in Convex. The React client reads message history straight from Convex (reactive queries) and uses the WebSocket only for sending, presence, and typing.

 Browser (React + Vite)
│ │
│ Clerk │ WebSocket (?token=<Clerk JWT>)
│ + Convex ▼
│ reactive ┌──────────────────────────────────────────┐
│ queries │ actor server (Go :8080 / Rust :8090 / │
│ │ Zig :8100) │
│ │ │
│ │ validate Clerk JWT → resolve user │
│ │ per-connection writer (owns socket) │
│ │ per-room actor (presence/typing)│
│ │ lazy room registry │
│ └───────────────────┬──────────────────────┘
▼ │ HTTP (/api/query, /api/mutation)
Clerk ▼
Convex (users, rooms, memberships, messages)

Three actor roles in all three: a per-connection writer that owns socket writes (so they serialize through one mailbox), a per-room actor that single-owns presence and typing and broadcasts updates, and a registry that spawns rooms lazily and evicts them when idle. The blocking socket read runs off the actor in all three.

Shared WebSocket protocol

One JSON envelope per message, discriminated by type.

  • Inbound:join, leave, send, typing_start, typing_stop, ping
  • Outbound:ack, error, presence_update, typing_update, pong (Rust and Zig also send a hello frame on connect)

Go vs. Rust vs. Zig at a glance

Concerngo-actor-chatrust-actor-chatzig-actor-chat
Actor runtimeanthdm/hollywoodhand-rolled tokio::mpscInkList
HTTP / WebSocketecho + coder/websocketaxumhttpz + websocket.zig
Wire protocolone Frame structserde tagged enumsone Frame struct
Request/responseengine.Requestoneshotfunc payloads / threads
Room registrymutex map + engine registryArc<Mutex<HashMap>>mutex map + actor ids
JWT / JWKSgolang-jwt + keyfuncjsonwebtokenstd RSA + JWKS fetch
Convex clientnet/httpreqweststd.http.Client
Idle evictionSendRepeat + Poisonselect! + intervalInkList sendEvery

The point of the repo: see the same actor shapes expressed through a framework (Go), hand-rolled async primitives (Rust), and a Zig actor library (InkList).

Running them / A-B-C comparison

See each subproject's README for full setup (Convex deploy + Clerk JWT template + env):

Because they speak the same protocol, you can point the React frontend at any backend from the implementation picker shown right after sign-in (Go :8080, Rust :8090, Zig :8100). Choice is remembered for the signed-in session (sidebar badge to switch); signing out clears it so the picker returns. Override URLs with VITE_WS_URL_GO / VITE_WS_URL_RUST / VITE_WS_URL_ZIG.

Each backend is a separate process — start the ones you want to compare:

# Go :8080
(cd go-actor-chat && make run)
# Rust :8090
(cd rust-actor-chat && cargo run)
# Zig :8100
(cd zig-actor-chat && zig build run)
# Frontend (any one copy is enough)
(cd rust-actor-chat/web && bun dev)

Repository layout

actor-chat/
├── go-actor-chat/ Go + Hollywood implementation (server, convex/, web/)
├── rust-actor-chat/ Rust + tokio implementation (server, convex/, web/)
├── zig-actor-chat/ Zig + InkList implementation (server; reuse Go/Rust web)
└── README.md (this file)

License

MIT — see LICENSE.

About

Several implementations of chat apps using the actor model to implement in different languagess

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages