DEV Community

Cover image for I rebuilt my 28-year-old IRC network from scratch in Go and WebAssembly
Selçuk Karayel
Selçuk Karayel

Posted on

I rebuilt my 28-year-old IRC network from scratch in Go and WebAssembly

In 1998 I opened an IRC network for Turkish chatters called Yudum.NET. It started on HybridIRC, moved to UnrealIRCd, and for more than two decades it ran on the same kind of software almost every Turkish IRC network still runs today: an old C daemon, a pile of Tcl/mIRC-script bots, and a web chat bolted on the side.

This year I threw all of that away and wrote the whole thing again. Alone.

Here's a 4-minute tour of what came out of it:

You can also just open it and type — no account needed: https://www.yudum.net/webchat/

Why rewrite something that works?

Because it didn't, really. Not for the people I wanted to keep.

Classic IRC is great if you already know it. For everyone else, it's a black window, a list of nicknames and a set of commands to memorise. Voice, images, games, "who is this person?" — all of that lived somewhere else: Discord, WhatsApp, Instagram. People came, looked around, and left for the app where their friends were.

I didn't want to turn IRC into Discord. I wanted the opposite: keep the channel, the nick list and the plain-text soul of IRC, and put everything else inside it — so nobody has to leave the chat to do anything.

The shape of it: one binary

The whole platform is a single Go binary:

  • An IRC daemon — regular IRC clients (mIRC, HexChat, IRCCloud…) still connect as they always have.
  • Services — NickServ, ChanServ, plus a social service that handles friends, follows, groups and the feed.
  • The website — profiles, feed, Discover, games, radio pages, help centre, all in Turkish and English.
  • The webchat — served by the same process.

There is one database (SQLite), one identity and one admin panel. Your nickname is your site account; a friend you add in chat is a friend on the website. A post you share on the site shows up in the chat's feed.

Running everything in one process sounds old-fashioned, but for a solo developer on one VPS it's a gift: no network hops between services, no "which service is down?", one place to look when something breaks.

The webchat is WebAssembly — and there is no plain JavaScript

This was the decision that surprised people most.

The webchat — chat, feed, profiles, games, voice rooms, streaming controls — is written in Go and compiled to WebAssembly with TinyGo. The site's own interactive bits and the admin panel are two more WASM modules. Apart from the tiny loader that boots WASM, there's no hand-written JavaScript shipped to the browser.

Why?

  • One language. The same Go types describe a message on the server and in the browser. The game engine that validates a move on the server is the same code that draws the table in the chat.
  • A strict Content-Security-Policy. No inline scripts, no onclick attributes, no eval. Every click goes through a small event-delegation layer inside WASM. On a chat site where anyone can type anything, this closes a whole family of XSS mistakes by design.
  • It's harder to lift. Not a security feature, just a nice side effect.

The trade-offs are real: TinyGo's syscall/js has sharp edges (numbers coming back as strings, 32-bit ints, very careful memory use), the WASM file is several megabytes, and a full build takes minutes. But the result is one codebase I can hold in my head.

Features, without leaving the chat

Everything below opens inside the chat window:

  • Social feed — posts, likes, comments, trends, 24-hour picture statuses.
  • Discover — news, videos, films and series, a TV guide, football score predictions, quizzes and polls.
  • Table games — Backgammon, 101 Okey, Checkers, Mangala and Pişti. When a table has an empty seat, the channel bot announces it and people join with one click.
  • Voice rooms and calls — join a voice channel, raise your hand for the floor, or call a friend 1-to-1.
  • Live streaming — stream your camera, your screen or the game you're playing, with viewers chatting next to the stream.
  • Radio — our station YudumFM plays at the top of the chat: request songs, vote on what's playing.
  • Moderation — kick, ban, voice, op, kill… all behind a right-click (or long-press on mobile). No command memorising.

And none of this breaks plain IRC. Someone on mIRC sees normal channel messages; they just can't be called on video. (The server politely tells you that instead of spamming them with signalling junk — a bug I fixed only this week.)

The part nobody sees: staying up

Here's the honest lesson of this rewrite.

I spent months shipping features, and the community barely noticed. What they did notice was every restart. On IRC, a restart means everyone gets disconnected at once, and for some people that's the moment they close the tab and don't come back.

So the most valuable work turned out to be boring:

  • Zero-downtime web deploys. During a release, a short-lived bridge process keeps serving HTTP while the new binary starts, so the website and webchat never go blank. IRC connections still drop once — that's the next thing to solve.
  • Batching. Templates, styles, translations, WASM and settings can all change without a restart. Go code changes are collected and shipped together, deliberately, instead of "just one more quick deploy".
  • Settings in the database, not in code. Nearly every limit, text and toggle is editable from the admin panel and takes effect within seconds.

The next big piece is a built-in bouncer, so your connection stays in the channel even when your browser tab doesn't.

What I'd tell someone doing the same

  1. Features don't bring people back; reliability keeps them. I'd have done the zero-downtime work first if I could go back.
  2. Keep the old door open. Old users still connect with the IRC client they've used for 20 years. Nothing new was allowed to break that.
  3. One process is fine. Until it isn't — but for a community of this size, it very much still is.
  4. Guest access matters. Being able to type in a channel within ten seconds, without signing up, is still the best onboarding there is.

If you've ever run an IRC network, a forum or any small community that refuses to die — I'd love to hear how you keep it alive. And if you want to poke at the result, drop by: https://www.yudum.net 👋

Top comments (2)

Collapse
 
devanti profile image
DEV ANTI •

woоow

‍​‍

Collapse
 
yudumnet profile image
Selçuk Karayel •

Thanks! 😄 28 years of the same community and a lot of late nights — glad it shows. Feel free to drop into the chat, no account needed: yudum.net/webchat/