apps/chat, a Slack/Discord-style realtime chat app that shows how a normal production app fits into Zomg.
The app has:
- A Bun TypeScript API with REST setup/history endpoints and a websocket realtime API.
- PostgreSQL persistence for users, sessions, workspaces, channels, memberships, messages, mentions, reactions, pins, read receipts, and file metadata.
- Files stored on a Zomg data volume mounted at
/data/files. - A compact React + shadcn frontend that exercises the API.
- Fast integration tests that boot a temporary local PostgreSQL server and drive the public HTTP/WebSocket API in parallel.
App layout
just verify-chat-app starts disposable PostgreSQL with initdb, creates an isolated schema per test, starts the real Bun server on random ports, then runs bun test --jobs=8. The tests do not call private functions; they register users, create workspaces/channels, open websockets, send messages, upload files, search, react, pin, and check permissions through the public API.
Runtime architecture
Use three pieces in Zomg:| Piece | Zomg primitive | Why |
|---|---|---|
chat-db | zomg pg Postgres service | Durable relational state and fast snapshots/clones |
chat-files | zomg data volume | Uploaded files survive app box deletion |
chat-app | zomg service on a box | Named process, logs, restart, publish |
/data, so the app stores file bytes under /data/files. It’s kept separate from the app root filesystem on purpose: deleting or recreating chat-app does not delete uploads.
Create the backing services
Select a target first:Copy and build the app
Package only the app source:Start and publish the app service
Run the web/API process as a named service:zomg service publish, unpublish, restart, and stop; avoid zomg exec --bg for the app process.
Blue/green deploy
For the next build, copy new source into the same box, install/build, then run the new version as a second service on a different port:zomg service publish chat-app web --as chat --port 8080.
Snapshots and backups
Before risky migrations, snapshot both durable stores:zomg pg snapshot captures database state; zomg data snapshot captures uploaded file bytes.
API surface
The HTTP API handles setup, history, search, and file transfer:| Endpoint | Purpose |
|---|---|
POST /api/auth/register | Create a user and bearer token |
POST /api/workspaces | Create a workspace |
POST /api/workspaces/:id/members | Add a workspace member |
POST /api/workspaces/:id/channels | Create public/private/DM channels |
GET /api/channels/:id/messages | Read channel history |
POST /api/channels/:id/messages | Persist a message |
PATCH /api/messages/:id / DELETE /api/messages/:id | Edit and soft-delete messages |
POST /api/messages/:id/reactions | Add emoji reactions |
POST /api/messages/:id/pin | Pin a message |
POST /api/channels/:id/read | Mark read receipts |
GET /api/search?workspaceId=...&q=... | Search readable messages |
POST /api/files / GET /api/files/:id | Upload and download files |
/api/ws?token=<token>.
Client messages include:
connection.ready, channel.subscribed, message.created, message.updated, message.deleted, typing.updated, presence.updated, reaction.added, reaction.removed, message.pinned, message.unpinned, and read.updated.
File uploads outlive the app
Use the explicitzomg data create and zomg data attach commands for the file volume, since uploaded files are app data that should outlive any one version of the app.