<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: JT</title>
    <description>The latest articles on DEV Community by JT (@jixie30).</description>
    <link>https://dev.to/jixie30</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4118101%2F921fc06f-815c-455a-876c-73f5069f0d6b.png</url>
      <title>DEV Community: JT</title>
      <link>https://dev.to/jixie30</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jixie30"/>
    <language>en</language>
    <item>
      <title>CampusLink: A Chat Server With No Internet Needed</title>
      <dc:creator>JT</dc:creator>
      <pubDate>Thu, 10 Sep 2026 07:29:31 +0000</pubDate>
      <link>https://dev.to/jixie30/campuslink-a-chat-server-with-no-internet-needed-4a4</link>
      <guid>https://dev.to/jixie30/campuslink-a-chat-server-with-no-internet-needed-4a4</guid>
      <description>&lt;p&gt;This was the first project I've ever actually finished. Not a tutorial I followed along with, not a copy of something else — an actual thing I designed, broke, fixed, and shipped, in 72 hours, for the Hackathon Raptors Zero-Dependency Hackathon. The rule was simple to say and hard to live with: no external packages, no libraries, no shortcuts. Just the standard tools your programming language already gives you, and whatever you can build yourself on top of them.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;CampusLink&lt;/strong&gt; — a chat tool that works over WiFi without ever touching the internet. Anyone on the same network can open it in their browser, post messages, reply, react, and vote on polls, all without installing anything or making an account. Here's what actually happened while I built it, and what it taught me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shortcut I couldn't take&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I'd been allowed to use any library I wanted, I would have reached for something like cpp-httplib — a tool that gives you a working web server in about ten lines of code. It handles all the boring, invisible plumbing: accepting connections, reading what the visitor's browser is asking for, and sending back a proper response.&lt;/p&gt;

&lt;p&gt;Since I couldn't use it, I had to build that plumbing myself. And my first attempt broke almost immediately, in a way that taught me something I hadn't understood before: when your browser sends a request to a website, it doesn't all arrive in one neat package. It arrives as a stream of raw text, sometimes in pieces, and your program has to know how to keep listening until it's actually received the whole thing. My first version assumed everything showed up in one go, and it fell apart the moment a request was even slightly bigger than expected. Fixing it meant writing a small loop that keeps reading until it sees a specific marker (a blank line) that tells it "the important part is over, here comes the rest." It's a small piece of code. But it's exactly the kind of thing that quietly works in every website you've ever used, and you never think about it, because someone else already solved it for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A simple idea that turned into something bigger&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once messages could actually reach my server correctly, I wanted a way to know who posted what — without asking anyone to sign up or log in. So I gave every visitor's browser a small, invisible tag the first time they showed up (a cookie, if you've heard that word before — it's just a little note the browser quietly holds onto and shows the server again next time). That one small trick let me build a lot on top of it: knowing which messages were yours, letting people delete only their own posts, and making sure nobody could vote twice on the same poll.&lt;/p&gt;

&lt;p&gt;That same little tagging system is also what led me straight into my first real bug. If you deleted a message that had replies underneath it, the replies didn't disappear — they just became invisible forever, still sitting quietly in the storage file, never shown to anyone again, with nothing telling me anything had gone wrong. I only found this because I was testing with actual friends on their actual phones, doing the normal things real people do — not just clicking around by myself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bug that only showed up because real people were using it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testing with other people also surfaced something sharper. When someone voted on a poll, my code checked "has this person already voted?" and then saved their vote as two separate steps. If two people (or one person, clicking twice really fast) hit those two steps at almost the same moment, both could sneak past the "haven't voted yet" check before either vote actually got saved — meaning someone could vote twice by accident. The fix wasn't more checking, it was realizing that the checking and the saving needed to happen as one single, uninterruptible step, so nothing could slip through the middle. That's the moment a concept I'd only read about — protecting shared data so two things can't happen at once — actually clicked, because I needed it to fix something real, not because a textbook told me to learn it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test that changed the whole idea of the project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While I was still deep in fixing things, I ran a much smaller test that ended up mattering more than any bug fix: I checked whether two different phones, connected to our actual college WiFi with two completely different logins, could reach each other directly. I expected they couldn't — a lot of institutional networks block that on purpose, for security. I'd already built a backup plan assuming I'd need it.&lt;/p&gt;

&lt;p&gt;They could reach each other, easily. That one small test flipped the whole point of the project. It stopped being "a backup for when the internet goes down" and became something more interesting: being on the same WiFi is proof that a group of people are actually near each other, right now — and that's useful for a lot more than just internet outages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where that idea led me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once I realized that, something clicked that I hadn't set out to build at all. If reaching my server at all requires being close enough to actually be on that network, then the network itself is quietly doing something expensive biometric attendance systems get paid a lot of money to do: proving someone is physically in the room. A student sitting outside the classroom simply cannot reach a poll running on their teacher's laptop over that classroom's own WiFi.&lt;/p&gt;

&lt;p&gt;Point the exact same "one vote per device" system I'd already built — for something as small as a movie-night poll — at a "mark yourself present" button instead, and you already have the hardest, most expensive part of an attendance system solved, for free, using a phone everyone already owns. What's still missing is turning that presence into someone's actual, provable identity — right now a student in the room could still type a friend's name for someone who isn't there. That's a smaller, more solvable problem than the one I'd already stumbled into an answer for. I didn't get to build that part in 72 hours. But it's genuinely the direction I want to take this project next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I actually walked away with&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used to think frameworks and libraries just saved you typing. What I actually learned is that they quietly absorb a long list of small, easy-to-miss mistakes, because someone already made those mistakes before you and fixed them. Building this without any of that meant I had to make those mistakes myself, one at a time, in the order life handed them to me — a broken parser, a bug hiding inside a feature I thought was finished, a race condition that only appeared once real people showed up, and an accidental idea I never planned for, sitting quietly inside a test I almost didn't bother running.&lt;/p&gt;

&lt;p&gt;None of it went the way I expected going in. All of it taught me more than following a tutorial ever has.&lt;/p&gt;

&lt;p&gt;Project: &lt;a href="https://dev.tourl"&gt;github.com/jigmat30/CampusLink&lt;/a&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>showdev</category>
      <category>software</category>
    </item>
  </channel>
</rss>
