Harshit Sharma
All work

Web AppQ2 2022Lead

Jsswire

Chat application connecting students with fellows and seniors across their campus.

A rendered network of glassy spheres radiating outward from one bright central node, in blues and cyans.

The build

A real-time extension of Jssconnect — and the project that taught me which of my assumptions were load-bearing.

Problem

Jssconnect was request-response: students opened a page, took what they needed, and left. What it couldn't do was put a first-year in touch with a senior who'd already solved the thing they were stuck on. That conversation was happening in group chats the platform couldn't see.

Constraints

  • It had to sit on top of an app that wasn't built for it. Jssconnect was stateless by design. Real-time isn't.
  • One identity, not two. Making students sign in again for chat would have killed it. The existing Passport session had to carry over.
  • Scoped to one campus. Presence and rooms only make sense if the population is bounded — an open chat would have been a different, worse product.

Approach

Socket.IO for rooms and direct threads, with the handshake sharing the Express session so the socket knows who is connecting without a second auth path:

js
io.on("connection", (socket) => {
  socket.on("join", ({ room, user }) => {
    socket.join(room);
    presence.touch(user, room);              // TTL-backed
    io.to(room).emit("presence", presence.of(room));
  });
  socket.on("disconnecting", () => presence.drop(socket));
});

Tradeoffs

  • Rooms are cheap; presence is not. Joining a room is one line. Knowing who's actually online is the hard part — a closed laptop lid doesn't fire a disconnect, so users linger as "online" for as long as the transport allows. Heartbeats plus a short server-side TTL got presence honest enough to display, at the cost of a background timer that's always running.
  • Sharing the Express session with the socket handshake. Avoided the one thing I least wanted to maintain — a second auth path. It also couples the chat to the host app's session store permanently.
  • Messages as documents keyed by room, paged by timestamp. Simple and correct, and it degrades: once a thread gets long, every scroll-up is a fresh query.

Outcome

The feature shipped and students used it. The schema is the part I'd redraw first — an append-only log per conversation with a cached tail, and read receipts as their own small collection instead of a field mutated on every open.

Decisions

  • Retrofitting onto Jssconnect over building a separate app. Chosen because the users, the identity, and the trust were already there — a chat app with nobody in it is worthless. Against it: every real-time assumption had to fit inside a codebase built on the opposite one.
  • Socket.IO over raw WebSockets. Chosen for rooms, reconnection, and transport fallback out of the box, which on a campus network mattered. Against it: a heavier client and a protocol that isn't quite WebSocket when you need to debug it.
  • TTL-based presence over trusting disconnect events. Chosen because the disconnect event is a lie often enough to be visible. Against it: presence is now eventually consistent, and a user can appear online for a few seconds after they've gone.

Stack

  • Node.js
  • Express.js
  • Socket.IO
  • MongoDB
  • Passport.js
  • Materialize CSS
  • The Lecture Lense workspace — a lecture playing above a chaptered time rail, the corrected transcript on the left, and a chat answer on the right with a timestamp citation.

    Lecture Lense

    Turns any recording into searchable, timestamp-cited notes.

  • Chitter's landing page — headline, a Join Chitter Now button, and a phone mockup of the feed.

    Chitter

    A mini social app that lets users sign up, log in and post whatever is on their mind.

  • A live Heckfree profile — avatar and the handle meharshit above seven stacked link rows, on a peach-to-purple gradient.

    Heckfree

    Users get a public profile that showcases all of their links in one place.

esc

Pages

Home/
Work/work
Blog/blog
About/about
Uses/uses
Contact/contact
Bucket list/bucket-list
Guestbook/guestbook
Résumé/resume
Privacy/privacy
Terms/terms

Projects

Lecture LenseQ3 2026
ChitterQ1 2023
HeckfreeQ3 2022
CoscholarsQ3 2022
JsswireQ2 2022
JssconnectQ1 2022
QuizTownQ4 2021
IplheatQ2 2021
TechkartQ4 2020

Posts

Passport.js auth patterns I keep reaching for7 min read
How To Create A README For GitHub Profile3 min read
↑↓ navigate↵ openesc close