A small chat server in the spirit of IRC: pick a nick, hop between channels in the sidebar, talk. Built with Phoenix LiveView and backed by SQLite, so there is no database server to run.
- Elixir 1.17+ and Erlang/OTP 26+
mix setup # fetch deps, create the SQLite db, run migrations + seeds, build assets
mix phx.server # http://localhost:4000mix setup seeds three channels to start with: #general, #random, #dev.
The database lives in atrium_dev.db (gitignored); delete it to start fresh, or
run mix ecto.reset.
Pick a nick on the splash prompt, then type in the composer at the bottom.
Anything starting with / is a command:
| Command | Effect |
|---|---|
/join #room (or /j) |
Switch to #room, creating it if it does not exist |
/nick name (or /n) |
Change your nick |
/me action |
Send an emote (* name action) |
/help |
List the commands |
New lines appear live for everyone in the channel. Opening a channel loads its last 100 messages, and the on-screen log is capped at 100 lines as you chat. Messages are limited to 2000 characters, nicks to 24 characters (letters, numbers and a few IRC-safe symbols); channel names are lowercase, up to 32 characters.
Atrium.Chat— the context. Channels and messages are Ecto schemas in SQLite.post_message/4inserts a row and broadcasts it on a per-channelPhoenix.PubSubtopic; a separate topic announces new channels so every client's sidebar stays current.AtriumWeb.ChatLive— the entire UI is one LiveView at/. It subscribes to the current channel, renders messages as a LiveView stream, and parses the slash commands.- Concurrency — the SQLite connection uses WAL journal mode so reads never
block the writer, plus a 5s
busy_timeoutso simultaneous writers wait for the lock instead of failing. Many people can talk at once without losing messages.
mix test # unit + LiveView tests, including a concurrent-write test
mix precommit # compile --warnings-as-errors, unused-deps check, format, testSet DATABASE_PATH (where the SQLite file should live) and SECRET_KEY_BASE,
then follow the standard Phoenix deployment
guides. Point DATABASE_PATH at a
persistent volume so history survives restarts.
Set both JEV_API_KEY and CHAT_RULES to moderate every message with
TypeSafe's Jev API before it's stored. CHAT_RULES
is a plain-text description of what's not allowed, e.g.:
JEV_API_KEY=sk-...
CHAT_RULES="No spam or advertising. No harassment or hate speech."Messages judged to break the rules are rejected with a flash error instead of
being posted. Leave either variable unset to disable moderation entirely; a
failed or unreachable moderation call also fails open so the chat keeps
working. See Atrium.Chat.Moderation.