Esposter
Esposter

Esbabbler

Esbabbler is Esposter's messaging module: a Discord-like experience with rooms, 1:1 and group direct messages, drop-in audio/video calls, role-based moderation, and web push notifications.

Design rule: match Discord by default. Behaviour, structure, naming, defaults, and where each setting lives all follow Discord unless visual styling (Vuetify-defined) or the storage constraints below force a divergence.

Key concepts

  • Room — the container for a conversation. Rooms and direct messages share one rooms table, distinguished by RoomType (Room | DirectMessage). Membership lives in usersToRooms.
  • Storage split — relational data (rooms, roles, bans, friends, settings, scheduled jobs) lives in Postgres; high-volume, time-ordered data (messages, moderation log) lives in Azure Table Storage with partitionKey = roomId and a reverse-ticked timestamp rowKey so newest rows sort first. See messaging.
  • Real-time — in-process Node EventEmitters (messageEventEmitter, roomEventEmitter, callEventEmitter, …) drive tRPC subscriptions; Azure Web PubSub handles webhook delivery. Subscriptions are the source of truth for store mutations.
  • RBAC — permissions are a bigint bitfield on room roles; every privileged procedure is gated through a permissions-aware procedure builder. See RBAC.
  • Call session — a call is anchored to a callSessionsInMessage row (12-character shareable id), not to a route. Room calls and standalone /calls/[id] share-link calls use the same session model. See calls.

Pages

PageCovers
messagingMessage storage, send flow, message types, real-time fan-out
message list renderingPer-item weight budget, single-instance menu/dialogs, emoji index
message list scrollingPresent detection, jump-to-present, newer-page anchor compensation
emojiOne emoji index — picker, reactions, : autocomplete, tones
custom emojiPer-room uploads — count cap, id-keyed tag, content node
file & mediaImage thumbnails, per-room attachment limits, attachment browsing
message searchRight-sidebar search — filter chips, free text, search history
friends and DMsFriend requests, blocking, 1:1 and group direct messages
RBACRoles, permission bitfield, hierarchy, procedure guards
moderationAdmin actions, word filter, bans/timeouts, audit log
automod actionsWord-filter reject/warn/timeout actions via the admin machinery
moderator notesPrivate, append-only per-member moderator notes
threadsThread pane, its composer, thread calls, split view, thread route
thread followsFollow threads, notify-on-reply, Followed Threads drawer
invitesInvite links with expiry and max-use options
nicknamesPer-room nicknames and display-name resolution
mention badgesMention-only unread counts in the room sidebar
profiles and presenceProfile card/editing and Online/Idle/DND/Offline presence
callsLiveKit sessions, membership boundary, knock lobby
call viewCall surface, prejoin/ready room, tiles, control bar
screen shareScreen-share tracks, presenter layout, moderation
picture-in-pictureDocument PiP pop-out of the active call
per-user volumePer-participant in-call volume slider (client-only)
user settingsMessage-scoped user settings dialog + userSettingsInMessage
room settingsRoom settings dialog — Discord categories + permission gating
room UIRoom-shell polish — member grouping, resizable sidebars, density
voice & video settingsVoice & Video panel and live LiveKit application
push-to-talkHold-to-talk keybind, mic gate, release delay
push notificationsWeb push delivery and recipient filtering
slash commands/command registry, picker, execution model
scheduled messages/remind + /schedule jobs and the Service Bus worker
drafts & sentCross-room Drafts / Scheduled / Sent view
offline cacheIndexedDB offline mirror of Pinia state
webhooksInbound webhooks and their app-user bot identities
deferredIdeas deferred, each with a revisit trigger
rejectedIdeas decided against
roadmapOpen work — every item links its proposal

Shipped log

Chronological, one line per feature group.

  • Core messaging — polls (/poll), emoji reactions, quote replies, typing indicators, edit/delete own messages, drafts, thread view, message grouping, jump-to-present, ↑-to-edit, code blocks, audio messages, file/image upload, rich link previews.
  • Search & navigation — Ctrl+K command palette, filtered search (from:/in:/before:/after:), pinned messages list, unread room dot, jump-to-message, Copy Message Link, Mark Unread From Here.
  • Slash commands/me /flip /shrug /tableflip /unflip /roll /topic /remind /schedule.
  • Friends & DMs — friends system, blocked users, 1:1 + group DMs, group-DM participant management, DM calls.
  • Mentions & notifications@here, @everyone, role mentions, mention highlighting, per-room notification preference, friend-request push notifications, mention badges (sidebar mention counts), thread follows with notify-on-reply and a Followed Threads drawer.
  • Presence & profiles — Online/Idle/DND/Offline status, custom status message, profile card, profile editing (biography + avatar SAS upload), room profile image.
  • Rooms — categories with drag-reorder, read-only/announcement channels, slowmode, per-room nicknames, welcome screen, join/leave system messages, invite expiry & max uses.
  • Moderation — RBAC roles/permissions, force-mute, kick, ban/unban, timeout, warn, softban, word filter, automod word-filter actions (reject/warn/timeout), private moderator notes, audit log with action/actor/target filters.
  • Calls — persistent per-room drop-in audio, LiveKit migration, video, screenshare, call lobby (knock & admit), deafen, raise-hand, call-health indicator, call-end duration system message, Document PiP pop-out, per-user volume, push-to-talk.
  • Integrations & infra — inbound webhooks, offline message cache, scheduled messages (Service Bus worker + listing/cancel UI), Sent tab via Search index.
  • Store hygiene — subscription-vs-caller ownership audit: every remote-visible message-store transition is owned by its subscription handler, caller-side mutations kept only for optimistic-with-revert or actor-excluded emits, locked in with idempotence tests.
  • File & media — one shared SAS upload service, client-side image thumbnails rendered inline with the original in a lightbox, per-room attachment limits (max size + allowed MIME categories) in the Moderation settings, and a room's attachments browsable through the has: file search filter.
  • Settings — message-scoped user-settings dialog (Voice & Video / Notifications / Keybinds) backed by userSettingsInMessage, applied live to LiveKit calls; push-to-talk keybind + release delay; room settings Discord-parity IA (category groups, Roles rename, Members/Invites tabs, Integrations + Moderation groups).
  • Custom emoji — per-room uploaded emoji through the room's own settings panel: one roomEmojis table, a ManageEmojis bit with Administrator repinned to the column's ceiling so nothing shifts again, a count cap in place of any metering, custom:{id} reactions and an id-keyed content node that resolves to its image on render.
  • Emoji — both emoji libraries retired for one in-repo index: a composition-API picker rendering native unicode with Discord's category rail, recents and single global skin tone, MiniSearch relevance shared with the composer's : autocomplete, and the Options API runtime, the CDN sprite sheet and the second dataset gone with them.
  • Room UI polish — role-grouped member list with role-colored names, resizable persisted sidebars, Cozy/Compact message display (Appearance settings), room-list/search empty states, mobile bottom action bar, category drag-reorder with keyboard support.