the kettle’s on and the terminal is warm.
so let me tell you about dumpsterChat — the self-hosted chat platform i built for a group of about twelve friends because we got tired of wondering if some corporation was reading our terrible jokes. yes, the name is intentionally ridiculous. yes, the server it runs on is called SmoothBrainCollective. no, i will not be taking questions about our naming conventions. we contain multitudes. dumb, dumb multitudes.
why not just use discord?
look, discord is fine. it’s a good product. but every few months they’d change something, shove another feature nobody asked for into the sidebar, or we’d read another headline about data practices that made us squirm. we’re not paranoid — we’re just twelve people who like owning our stuff. there’s a certain warmth in knowing that every message, every emoji reaction, every embarrassing late-night rant lives on hardware we control. it’s the difference between renting an apartment and owning a house. sure, the landlord handled the plumbing, but you couldn’t knock down a wall when you felt like it.
so one weekend, fueled by an unreasonable amount of dark roast, i started building.
the stack: go in the back, react in the front
the backend is Go with Chi as the router. i picked Go because it compiles to a single binary, handles concurrency like it was born for it (it was), and doesn’t make me think about garbage collection at 2am. Chi is lightweight, composable, and doesn’t try to be a framework — it’s just a good router with sensible middleware. that’s all i wanted. i didn’t need an opinionated monolith telling me how to structure my feelings.
the frontend is Vite + React + Tailwind CSS. Vite because hot module replacement is the closest thing to magic i’ve experienced in web development. React because, love it or hate it, the ecosystem is enormous and the component model just clicks in my brain. Tailwind because i’d rather write twelve utility classes than maintain a stylesheet that grows like kudzu across the project. it’s not elegant. it’s effective. like a french press.
WebSocket for real-time messaging. no long-polling, no SSE workarounds — just a clean persistent connection that pushes messages the moment they’re sent. typing indicators, presence updates, new messages, reactions — all streamed through the same socket. the latency is low enough that it genuinely feels instant, even with our janky but beloved infrastructure.
the features nobody asked me to build but i built anyway
this is the part where scope creep became a lifestyle.
direct messages. because sometimes you need to privately tell someone their take is unhinged.
full markdown support. bold, italic, code blocks, lists, links — the whole thing. we’re degenerates, but we’re literate degenerates. writing a message with a properly formatted code block in it? chef’s kiss.
link embeds. paste a URL and it pulls the title, description, and thumbnail. youtube videos get a playable embed. it’s a small thing but it makes the chat feel alive, like it’s actually connected to the internet and not just a text box screaming into the void.
search. full-text search across messages. because three weeks from now someone’s going to say “what was that link you shared?” and we need to find it without scrolling through a thousand messages about whether a hot dog is a sandwich.
moderation tools: kick, ban, and mute. we’re friends, but we’re also twelve people with strong opinions. sometimes someone needs a time-out. the mute function was built with great affection and a specific person in mind (they know who they are, and they’ve earned it).
slowmode. for when the chat is moving too fast and people are talking over each other like a caffeine-fueled debate club. set a cooldown per channel, breathe a little, think before you type. revolutionary concept.
threads. reply chains that don’t derail the main conversation. discord got this one right and i stole it unapologetically.
forums. structured discussion channels where topics get their own threads with statuses — open, resolved, closed. great for the friend who always has a “quick question” that turns into a seventeen-message troubleshooting saga.
calendar channels. channel type for events. create events with dates, descriptions, and RSVPs. because coordinating twelve adults across three time zones via “who’s free saturday?” messages is a nightmare i refuse to live in.
docs channels. collaborative document channels for shared notes, guides, recipes, whatever. think wiki pages that live inside the chat. the friend group cookbook lives here now and it’s glorious.
role-based permissions with bitflags. roles aren’t just labels — they carry actual permission sets implemented as bitflags. each permission is a bit, roles are bitwise OR’d together, and checking access is a single bitwise AND operation. it’s fast, it’s clean, and it made me feel like a real systems programmer for about fifteen minutes. roles like admin, moderator, member — each with granular permissions for managing channels, kicking users, editing docs, creating events. the system is simple enough for twelve people but built to scale to… well, maybe thirteen people someday.
where it lives
dumpsterChat runs on a Proxmox LXC container at 172.20.0.125 on SmoothBrainCollective — my homelab server that also hosts a growing collection of services i’ve convinced myself i need. the container is lightweight, the Go binary sips memory, and the whole thing sits behind a reverse proxy with TLS. it’s not enterprise-grade infrastructure. it’s a house of cards built with love and held together by systemd services and prayer.
backups happen. i promise. mostly.
what i learned (or: things the coffee told me)
building for twelve people is liberating. you don’t need to optimize for ten thousand concurrent users when your entire user base could fit in a minivan. the queries can be a little naive. the WebSocket hub can broadcast to everyone instead of maintaining subscription trees. simplicity is a feature when your scale is small and your friends are patient.
go is genuinely fun for this kind of thing. the concurrency model with goroutines and channels maps beautifully to a chat server. each WebSocket connection is a goroutine. messages flow through channels. the whole thing hums.
react + tailwind is fast to iterate on. i could sketch a feature in the morning and have it working by lunch. the component model makes it easy to add new channel types — forums, calendars, docs — without touching the existing ones.
self-hosting is a mindset. it’s not just about running your own server. it’s about understanding every layer of the stack. when something breaks at 11pm, i know exactly where to look because i built it. there’s no support ticket, no status page, just me and the logs and another cup of coffee.
the point
dumpsterChat isn’t trying to replace discord. it’s not trying to be the next big thing. it’s a chat app for twelve friends who wanted to own their conversations, built by one person who had too much coffee and a free weekend (okay, several free weekends). it does what we need, it runs on hardware we control, and it has a name that makes us laugh every time we say it out loud.
that’s enough. that’s the whole point.
if you’ve been thinking about self-hosting something — a chat app, a wiki, a file server, whatever — just start. it doesn’t have to be perfect. it doesn’t have to scale. it just has to work for the people who use it. the rest is just more coffee and more commits.
stay warm. brew something.
-dustin