DEV Community

Cover image for Show HN: How I Built a Zero-Cost, True End-to-End Encrypted Chat App using Node.js & Web Crypto API
Levi
Levi

Posted on

Show HN: How I Built a Zero-Cost, True End-to-End Encrypted Chat App using Node.js & Web Crypto API

Hi everyone, I’m Levi.

I am a complete beginner when it comes to advanced software engineering, but I have a deep passion for coding and building things from scratch. I’ve been learning bit by bit, taking my time to understand how the web actually works under the hood.

Recently, I started exploring the concept of "Vibe Coding"—the process of building software by guiding AI with natural language, focusing on the logic, architecture, and "vibe" of the app while learning the actual syntax along the way.

Today, I want to share the very first platform I built using this approach: A zero-cost, true end-to-end encrypted (E2EE) chat application.

The Goal
I wanted to build a chat room where two people could talk without anyone—not even me as the server owner—being able to read the messages. And because I am just starting out, my budget was exactly $0.

The Tech Stack

  • Frontend: Vanilla HTML, CSS, JavaScript
  • Backend: Node.js, Express, Socket.io
  • Security: Native browser window.crypto.subtle (Web Crypto API)
  • Hosting: Render (Free Tier) & GitHub

How I Built the Encryption (The Fun Part!)
Instead of relying on heavy third-party libraries, I wanted to learn how true cryptography works directly in the browser.

Key Generation: When a user opens the app, the browser instantly generates an ECDH (Elliptic-Curve Diffie-Hellman) public/private key pair.

The Handshake: Users join a room using a simple code or a shareable link. Once both are in, they exchange their public keys via Socket.io.

The Shared Secret: Using their own private key and the friend's public key, both browsers derive a matching 256-bit AES-GCM shared secret.

Total Privacy: Every message typed is encrypted locally in the browser into unreadable ciphertext before it ever hits the network. The Node.js server only routes the ciphertext. It has no database, no logs, and no idea what the users are saying.

The "Self-Destruct" Feature
Because I don't use a database, there is zero persistent storage. To take privacy a step further, I added a self-destruct mechanism. The moment one user closes their browser tab or disconnects, the server emits a signal that forces the other user's browser to wipe all local memory, clear the chat UI, and refresh the page. No trace is left behind.

The Vibe Coding Experience
As a beginner, tackling WebSockets and Elliptic-Curve Cryptography sounded terrifying. But by using the vibe coding method, I was able to break the problem down into simple human logic: "How do two people agree on a secret password in a crowded room without anyone else hearing it?" Translating that logic into code piece-by-step made the learning curve incredibly rewarding.

Try It Out!
I would absolutely love for this community to try it, break it, and give me feedback. What security flaws did I miss? How can I write cleaner code? I am here to learn.

🔗 Live App: https://hidechat-levi.onrender.com

If you like what I’ve built as my first project, any tips, code reviews, or even a virtual coffee would mean the world to me. Thanks for reading!

Top comments (1)

Collapse
 
godaddy_llc_4e3a2f1804238 profile image
GoDaddy LLC

This is honestly a very impressive first project, especially for someone diving into cryptography and WebSockets at the same time. Building E2EE with native Web Crypto APIs instead of hiding behind giant abstractions is one of the fastest ways to actually understand how secure messaging works 🔐
I also like that you focused on architecture decisions like “server only routes ciphertext” instead of just shipping a chat UI and calling it secure.
The self-destruct mechanism is a nice touch too — very “Mission Impossible,” except instead of explosions it’s just JavaScript aggressively clearing memory 😂
What stands out most is the learning mindset here: breaking difficult systems into human logic first and translating that into code step by step.
A lot of beginners avoid security because it feels intimidating, but this is proof that curiosity + iteration beats waiting until you “feel ready.”
Definitely keep going with this — today it’s encrypted chat, tomorrow you’ll accidentally wake up maintaining your own secure protocol specification at 2 AM like the rest of us 😅