---
title: "Subway | DJ Petersen"
description: "A web IRC client with server-side sessions, plugin hooks, and history that survives disconnects and machine switches."
canonical: "https://www.thedjpetersen.com/projects/subway/"
---

Project2012–2014Archived

# Subway

A web IRC client with server-side sessions, plugin hooks, and history that survives disconnects and machine switches.

## The story

Throughout college, my friends and I lived on IRC. It was our group chat before modern group chat existed. The constant pain was context loss: switching machines meant losing your scroll position, your unread state, and the momentum of whatever conversation you were in.

I had just discovered , and the idea of shipping real-time behavior straight to the browser felt transformative. Around the same time, [Paul Irish posted a public challenge](https://gist.github.com/paulirish/1928551#31-improve-design-of-webchat-irc-client-qwebirc) to improve web IRC clients. Subway started as a direct response to item #31 on that list.

Over two years of intermittent development it grew from a proof of concept into the client I used daily: history that persisted across sessions, plugin-driven behavior, desktop highlights, and reconnect logic built to recover work rather than drop it. The IRC session lived on the server, so closing a laptop mid-conversation stopped costing anything.

The repository is archived now, and that's the right status. The stack reads like a time capsule — Backbone.js, jQuery, Underscore — and group chat moved on. But for two years it did exactly what I built it for, and a proof of concept that becomes your daily client is the best outcome a proof of concept can have.

## How it works

Two questions drove the architecture: how messages moved, and how sessions recovered.

*Message flow and session recovery*

```
sequenceDiagram
    participant Browser as Browser UI (Backbone.js + jQuery)
    participant Bridge as Socket.io bridge (Node.js)
    participant Session as IRC session layer
    participant History as Persistent history

    Browser->>Bridge: connect over Socket.io
    Bridge->>Session: bind IRC session and join channels
    Session->>History: read recent messages
    History-->>Browser: rehydrate scrollback and unread state
    Session-->>Browser: stream events (join, part, topic, message)
    Session->>Session: plugin hooks fire on highlights
    Note over Browser,Session: On disconnect, the server-side session stays up, queues missed events, and replays them on resume
```

*The browser talks to a Node.js bridge over Socket.io; the IRC session and its history live server-side, so a disconnect loses nothing.*

## Demo

Simulated replay — a reconstruction of original behavior; transcript and activity are stagedSubway — browser IRC proof of concept, 2012

This replay is a reconstruction of original behavior from the Subway project: socket negotiation, persistent history restore, plugin-driven notifications, and reconnect recovery on a Node.js + Socket.io stack.

Bootingdj@irc.thedjpetersen.com•Replay DemoTopicSubway PoC: proving IRC can feel native in the browser05:36 AMsubway-botSourcedconnected to irc.thedjpetersen.com over WebSocket transport05:36 AMsubway-botSourcedrestored 42 lines from prior browser session05:36 AMariMemoryswitching laptops without losing scrollback is huge.05:36 AMlenaMemoryand unread counts survive refresh now. that never worked in qwebirc.SendPulling history and plugin manifests from storage…

*Each event in the timeline carries a provenance badge — Sourced, Memory, or Inferred — marking whether it comes from the repository, from what I remember, or from a plausible reconstruction.*

## Artifacts & further reading

1. \[1\][GitHub](https://github.com/thedjpetersen/subway)github.com
2. \[2\][Paul Irish's gist, item #31](https://gist.github.com/paulirish/1928551#31-improve-design-of-webchat-irc-client-qwebirc)gist.github.com

  the challenge that prompted the project
3. \[3\][How Claude Code and I Built a €18/Month Kubernetes Platform](https://www.thedjpetersen.com/llm-thoughts/own-infrastructure-part-1)internal
