Live team chat. You join a workspace, open a channel, and messages show up as they are sent.
I built this to learn WebSockets. The rest of the app exists so that socket has somewhere real to live.
Live: chatonhuddle.vercel.app. Web on Vercel, API on Coolify, Postgres on Supabase. How that is wired: deploy.
- Email and password accounts, optional GitHub OAuth
- Workspaces, channels, and invite links that expire in 7 days
- Message history over REST, live chat over WebSocket
- Acks, reconnect with backoff, and a session that can actually be revoked
- Redis pub/sub when you run more than one API process. Without it, each process talks only to its own sockets
Not built: presence, typing, and DMs in the UI. The REST DM endpoints exist. The socket answers not_supported.
| Layer | Choice |
|---|---|
| Runtime | Bun + TypeScript |
| API | Express 5 |
| Realtime | ws on the same HTTP server |
| Database | PostgreSQL via Prisma |
| Frontend | React 19 + Tailwind v4 |
| Local infra | Docker Compose (Postgres, Redis, optional API image) |
You need Bun and Docker (for Postgres).
git clone https://github.com/shubhook/huddle.git
cd huddle
bun install
cp apps/server/.env.example apps/server/.env
# set JWT_SECRET to 32+ random characters: openssl rand -base64 48
docker compose up postgres -d
bun run db:generate
bun run db:migrate
bun run devOpen http://localhost:3008. The API is http://localhost:3000.
Full env, Compose, GitHub OAuth, and the smoke check live in the setup guide.
apps/server HTTP API + WebSocket
apps/web React client (hash routes, port 3008)
packages/protocol socket frame schemas shared by the API and the client
docs/ setup and how each piece works
- Setup
- Deploy
- Architecture
- Auth and sessions
- Workspaces and channels
- Realtime
- Web client
- HTTP and WebSocket API
- Security
Package notes: apps/server, apps/web.
Work in progress. The socket has validation, acks, reconnect, heartbeats, and Redis fan-out. Next is presence and DMs over the socket.
