<?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: Muhammad Usman</title>
    <description>The latest articles on DEV Community by Muhammad Usman (@muhammadusman2228).</description>
    <link>https://dev.to/muhammadusman2228</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%2F4077347%2Fd7d9411c-c275-4bd7-ba1d-162a60165c9f.jpg</url>
      <title>DEV Community: Muhammad Usman</title>
      <link>https://dev.to/muhammadusman2228</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muhammadusman2228"/>
    <language>en</language>
    <item>
      <title>How I Built a Real-Time Messaging App as a CS Student from Pakistan — The Full Story</title>
      <dc:creator>Muhammad Usman</dc:creator>
      <pubDate>Sat, 15 Aug 2026 07:19:32 +0000</pubDate>
      <link>https://dev.to/muhammadusman2228/how-i-built-a-real-time-messaging-app-as-a-cs-student-from-pakistan-the-full-story-1bhl</link>
      <guid>https://dev.to/muhammadusman2228/how-i-built-a-real-time-messaging-app-as-a-cs-student-from-pakistan-the-full-story-1bhl</guid>
      <description>&lt;p&gt;I am a 7th semester BSCS student from Kasur, Pakistan.&lt;/p&gt;

&lt;p&gt;No internship. No mentor. No team. No funding.&lt;/p&gt;

&lt;p&gt;Just me, a laptop, and a stubborn refusal to only do assignments.&lt;/p&gt;

&lt;p&gt;Six months ago I decided to build something real. Not a todo app. Not a weather app. Something that actual people could open and use right now.&lt;/p&gt;

&lt;p&gt;Today, vconnect.fun is live. Real people are using it. And I want to tell you exactly how I built it, what broke, and what I would do differently.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is VConnect?
&lt;/h2&gt;

&lt;p&gt;VConnect is a real-time web messaging platform. Think WhatsApp Web but free, open, and built by one student from a small city in Punjab.&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant messaging via WebSockets&lt;/li&gt;
&lt;li&gt;Typing indicators and read receipts&lt;/li&gt;
&lt;li&gt;Voice notes and file sharing&lt;/li&gt;
&lt;li&gt;Glassmorphic UI with dark mode&lt;/li&gt;
&lt;li&gt;Online/offline status&lt;/li&gt;
&lt;li&gt;User search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stack: MongoDB, Express.js, React.js, Node.js , full MERN. Deployed on AWS EC2 with Docker and GitHub Actions for CI/CD.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Did I Build This?
&lt;/h2&gt;

&lt;p&gt;Honestly? I wanted proof.&lt;/p&gt;

&lt;p&gt;Proof that I could build something production ready. Proof that a student from Kasur could ship something that looked and worked like a funded startup product.&lt;/p&gt;

&lt;p&gt;Most of my classmates were building assignment projects that nobody ever opens again. I wanted to build something with a real domain, real users, and real infrastructure.&lt;/p&gt;

&lt;p&gt;So I started.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The core of VConnect is WebSocket communication handled by Socket.io.&lt;/p&gt;

&lt;p&gt;Here is the basic idea of how real-time messaging works in VConnect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;
&lt;span class="c1"&gt;// Server side when a message is sent&lt;/span&gt;
&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receiverId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;receiverId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Emit to the receiver if they are online&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receiverSocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getReceiverSocketId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiverId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiverSocket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiverSocket&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;newMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight here is getReceiverSocketId. I maintain a map of userId to socketId so I can target messages to specific users instead of broadcasting to everyone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;

&lt;span class="c1"&gt;// Tracking who is online&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSocketMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handshake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;userSocketMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Broadcast updated online users to everyone&lt;/span&gt;
  &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getOnlineUsers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userSocketMap&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disconnect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;userSocketMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getOnlineUsers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userSocketMap&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how the green dot works. When a user connects, their ID is stored. When they disconnect, it is removed. Everyone gets notified in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hardest Part : Read Receipts
&lt;/h2&gt;

&lt;p&gt;Typing indicators were easy. Read receipts nearly broke me.&lt;/p&gt;

&lt;p&gt;The challenge: how do you know a message was "seen"? You need to track when the receiver opens a conversation, not just when they receive a message.&lt;/p&gt;

&lt;p&gt;My solution was to emit a "markAsRead" event whenever a user opens a chat window, then update all unread messages for that conversation in the database and emit back a "messagesRead" event to update the sender's UI.&lt;/p&gt;

&lt;p&gt;It sounds simple. It took four days and three complete rewrites to get right.&lt;/p&gt;

&lt;p&gt;The lesson: real-time state synchronization is genuinely hard. Every edge case you can imagine what if the user is offline when you send? what if they open the chat before the message arrives? you have to handle all of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deployment : AWS EC2 with Docker
&lt;/h2&gt;

&lt;p&gt;This was where I went from "student project" to "production app."&lt;/p&gt;

&lt;p&gt;I containerized the backend using Docker so the environment is identical everywhere. Then I set up GitHub Actions to automatically deploy whenever I push to the main branch.&lt;/p&gt;

&lt;p&gt;The flow looks like this:&lt;/p&gt;

&lt;p&gt;Push to GitHub → GitHub Actions triggers → SSH into EC2 → Pull new image → Restart container&lt;/p&gt;

&lt;p&gt;yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simplified GitHub Actions workflow&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to EC2&lt;/span&gt;
   &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;ssh ec2-user@my-ec2-ip '&lt;/span&gt;
      &lt;span class="s"&gt;docker pull my-image:latest &amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="s"&gt;docker stop vconnect || true &amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="s"&gt;docker run -d --name vconnect my-image:latest &lt;/span&gt;
    &lt;span class="s"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting this up the first time took a full weekend. Now every deployment takes 90 seconds automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;1. Add a guest/demo mode from day one.&lt;/em&gt;&lt;br&gt;
The biggest barrier to new users is registration. If someone could try VConnect instantly without signing up, more people would actually experience it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Write tests earlier.&lt;/em&gt;&lt;br&gt;
I have almost no test coverage. Every new feature is a gamble. I am paying for this now.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3. Document the architecture as I built it.&lt;/em&gt;&lt;br&gt;
I had to reverse-engineer my own code to write this article. That is embarrassing. Write docs while the context is fresh.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Lesson
&lt;/h2&gt;

&lt;p&gt;Building VConnect taught me more than two semesters of university combined.&lt;/p&gt;

&lt;p&gt;You learn WebSockets by breaking WebSocket connections at 2 AM and figuring out why. You learn Docker by spending a Saturday on a port conflict. You learn AWS by accidentally exposing your EC2 instance to the entire internet and then panicking.&lt;/p&gt;

&lt;p&gt;The classroom teaches you concepts. Building teaches you reality.&lt;/p&gt;

&lt;p&gt;If you are a student reading this, stop waiting until you feel ready. You will never feel ready. Open a new project folder, pick something you wish existed, and start.&lt;/p&gt;

&lt;p&gt;The only way to learn to build is to build.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Try VConnect:&lt;/em&gt; vconnect.fun&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GitHub:&lt;/em&gt; github.com/muhammadusman2228&lt;/p&gt;

&lt;p&gt;If you found this useful, follow me here on Dev.to . I am documenting everything I build and learn as a CS student in Pakistan. More articles coming on CoCode (collaborative code editor with Docker sandboxing) and deploying MERN apps on AWS from scratch. &lt;/p&gt;

&lt;p&gt;Drop a comment with what you are building. I would love to see it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkxp57ksew7ejtkancsc1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkxp57ksew7ejtkancsc1.jpeg" alt=" " width="799" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>mern</category>
    </item>
  </channel>
</rss>
