The token-hashing commit (57aec2c) never updated ServeWS to hash tokens
before querying the sessions table. Cookie and message-frame auth both
compared raw tokens against stored hashes, so every WS connection failed.
Also moved reconnectDelay to module scope so the exponential backoff
survives across connect() calls, and resets on successful open.
Dumpster
A chaotic, self-hosted Discord-like platform for ~12 degenerates.
Built for fun, maintained with pride, named with intent.
Quick Start
git clone ssh://git@git.dustin.coffee:2222/hobokenchicken/dumpsterChat.git
cd dumpsterChat
docker compose -f docker/compose.yml up
That's it. Visit http://localhost to register and start chatting.
For optional features, copy .env.example to .env and set Giphy, MinIO, LiveKit, or VAPID keys.
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Go, Chi router, pgx, gorilla/websocket |
| Frontend | React 18, TypeScript, Vite, Tailwind CSS, Zustand |
| Database | PostgreSQL 16 |
| Cache | Valkey (Redis-compatible) |
| File storage | MinIO (S3-compatible) |
| Voice/video | LiveKit |
| TURN | coturn |
| Reverse proxy | Caddy |
| Auth | Argon2id + WebAuthn passkeys |
Features
- Registration + login (Argon2id)
- Server + channel CRUD
- Messaging with WebSocket real-time delivery
- Cursor-based message pagination
- User profiles (display name, bio, accent color, status, avatar/Gravatar)
- File uploads (MinIO)
- Giphy GIF search + trending
- Terminal/Gruvbox dark aesthetic
- Voice/video rooms (LiveKit)
- Online presence (online/idle/dnd/offline)
- Typing indicators
- Message reactions (emoji picker, counts)
- Message replies/threads
- PWA with service worker
- Invite link system
- @mention autocomplete
- Threads (reply chains)
- Forum channels (threaded topics)
- Calendar (events, RSVPs)
- Docs (wiki with markdown sidebar)
- Lists (kanban todo/in_progress/done)
- Scheduling / availability (per-server slots)
- Audit log (event tracking)
- Blocks (user-level blocking)
- Dark/light mode toggle
- Mobile-responsive layout (bottom nav, drawer)
- Bot framework (token auth, CRUD, WebSocket gateway, bot store)
- Built-in bot runner (server-managed bots, no SSH needed)
- Built-in bot: Steam Free Games (polls Steam API, auto-posts)
- Bot message badges (green name + BOT tag in chat)
- Slash commands (registration, autocomplete)
- Incoming webhooks (create, execute)
- Example bots (modbot, welcome bot, steamfree)
- TUI client (Bubbletea, vim-style, voice support)
- Roles & permissions system
- Push notification backend (VAPID)
- Push notification frontend (subscribe toggle in settings)
- WebAuthn passkey scaffolding
- WebAuthn frontend (register/login buttons)
- WebAuthn backend (full begin/finish flow)
- REST API documentation (Swagger UI at /docs)
- Push notification mention parsing and dispatch
- Inline markdown formatting toolbar (B/I/S/code/spoiler)
- GIF picker and kaomoji in DMs
- Restore last active channel on login
Project Structure
dumpsterChat/
├── cmd/
│ ├── server/ # Main API + WebSocket gateway
│ ├── migrate/ # Database migration CLI
│ └── tui/ # Terminal client (Bubbletea)
├── internal/
│ ├── auth/ # Registration, login, sessions, profiles
│ ├── channel/ # Channel CRUD handlers
│ ├── config/ # Environment-based config
│ ├── db/ # PostgreSQL connection + schema migrations
│ ├── gateway/ # WebSocket hub + client fanout
│ ├── giphy/ # Giphy API client (search + trending)
│ ├── message/ # Message CRUD + WS broadcast
│ ├── middleware/ # Session auth middleware
│ ├── server/ # Server CRUD + membership
│ ├── upload/ # MinIO file upload + serve
│ ├── voice/ # LiveKit voice/video integration
│ ├── reaction/ # Message reactions
│ ├── invite/ # Server invite links
│ ├── bot/ # Bot framework, auth, commands, runner
│ ├── webhook/ # Incoming webhooks
│ ├── dm/ # Direct messages (conversations)
│ ├── push/ # Push notification sender (VAPID)
│ ├── permissions/ # Permission bitflags and checker
│ ├── moderation/ # Mute, ban, kick, slowmode, audit log
│ ├── thread/ # Threaded conversations
│ ├── forum/ # Forum channel topics
│ ├── calendar/ # Events + RSVPs
│ ├── docs/ # Wiki documents
│ ├── lists/ # List kanban items
│ ├── availability/ # Scheduling/availability
│ └── block/ # User blocking
├── examples/ # Example bots
│ ├── modbot/ # Moderation bot
│ ├── welcome/ # Welcome message bot
│ └── steamfree/ # Steam free games bot (standalone)
├── web/ # React frontend (PWA)
│ ├── src/
│ │ ├── components/ # Layout, ChatArea, LoginForm, UserSettings, GiphyPicker, VoiceChannel, VoicePanel, VoiceControls, TypingIndicator, ReactionBar, EmojiPicker, ReplyBar, MentionPopup, InviteModal, JoinServer, MobileNav, MobileDrawer, ThemeToggle, InstallPrompt, BotManager, CommandManager, SlashCommandPopup
│ │ ├── stores/ # Zustand (auth, server, channel, message, ws, voice, presence, typing, push, bot)
│ │ └── lib/ # API client, WebSocket client
│ └── tailwind.config.js
├── docker/ # Docker Compose, Dockerfile, Caddyfile, LiveKit config
├── Makefile # Build targets
└── .env.example # Environment template
Environment Variables
See .env.example for the full list. Key variables:
| Variable | Description | Required |
|---|---|---|
DUMPSTER_HOST |
Server bind address | No (default: localhost) |
DUMPSTER_PORT |
Server port | No (default: 8080) |
DUMPSTER_SECRET |
Session signing secret | No (auto-generated in Docker) |
POSTGRES_* |
Database connection | No (defaults in compose) |
LIVEKIT_* |
Voice/video server | No |
GIPHY_API_KEY |
Giphy API key for GIF search | No |
MINIO_* |
File upload storage | No |
VAPID_PUBLIC_KEY |
Web push public key | No (generate with go run ./cmd/keygen) |
VAPID_PRIVATE_KEY |
Web push private key | No |
VAPID_SUBJECT |
Contact for VAPID JWT (e.g. admin@your.domain) |
No |
Push Notifications
Web push uses VAPID keys. Generate a keypair:
go run ./cmd/keygen
Copy the output into your .env. Set VAPID_SUBJECT to your email address without the mailto: prefix (the library adds it automatically).
Users are prompted to enable notifications on login. On iOS, the prompt requires a tap gesture, so a banner appears instead of a silent auto-subscribe. On Android, notifications deliver through FCM when Chrome is running (even in background). Ensure Chrome battery optimization is set to Unrestricted for reliable delivery when the PWA is closed.
Wiki
Full documentation: dumpsterChat wiki
Production Deploy (SBC / 172.20.0.125)
App lives at /opt/dumpsterChat. systemd unit name is dumpster.service (not dumpsterChat).
# Build locally
CGO_ENABLED=0 go build -o dumpster-server ./cmd/server
(cd web && npm run build)
# Ship binary + web assets
scp dumpster-server root@172.20.0.125:/tmp/dumpster-server-new
rsync -av --delete web/dist/ root@172.20.0.125:/opt/dumpsterChat/web/dist/
ssh root@172.20.0.125 '
install -m 755 /tmp/dumpster-server-new /opt/dumpsterChat/dumpster-server
systemctl restart dumpster
systemctl is-active dumpster
'
Logs: journalctl -u dumpster -f
Health: curl -s http://127.0.0.1:8080/ (or your API health route)
Public: Caddy → dumpster.dustin.coffee → 172.20.0.125:8080
License
AGPLv3