Chatify
A realtime messaging app I built as a full stack TypeScript project. One to one chats with text, files, images, videos, stickers, GIFs, emojis, reactions and read receipts, with 200+ sign ups.
- Role
- Solo full stack developer
- Year
- 2024
- Realtime
- Socket.io
- Data
- Turso, S3
Two sessions side by side: mine and a sample contact. The conversation plays automatically with socket events below. Everything runs locally with sample data.
01
What it takes to feel instant
I wanted to understand what it takes to build a messaging product that feels like the ones people use every day: instant delivery, rich media, read receipts and the small chat actions you expect.
REST loads chats and history. Socket.io handles live delivery. Both sides are protected by the same Auth0 JWT.
Socket.io
From one window to the other
02
The details that make a chat complete
Beyond sending text, most of the work went into the small things.
The chat
What a conversation holds
Features
NowClickable links, images, videos and any file type with previews, plus a Tenor powered sticker and GIF picker.
NowReply to a specific message and jump back to it from the quote.
NowReact to any message with an emoji.
NowSent, delivered and read ticks, plus notifications for unseen messages.
NowPin, hide, mute, mark as unread, block, clear or delete a chat.
NowFind chats and messages, and filter shared content by files and media.
- Rich messages
- Replies
- Reactions
- Read status
- Chat actions
- Search
I built the whole thing: client, API, realtime layer, data model, media pipeline, CI and the deployment pipeline.
03
A long running server on purpose
The repo is a pnpm workspace with a React client and a Node.js API. The client is on Cloudflare Pages. Realtime connections need a process that stays up, so the API runs on AWS EC2 with PM2, deployed by a GitHub Actions pipeline.
01 · Client
React + Vite
Zustand for state and Dexie for local browser storage.
Auth0
Google, GitHub or email sign in. One JWT for REST and sockets.
02 · API
Express
REST routes guarded with express-oauth2-jwt-bearer.
Socket.io
new_message in, chat_message out, behind authSocketMiddleware.
03 · Data and infra
Turso (libSQL)
Users, chats and messages.
S3 + CloudFront
Media uploads with optional signed URLs.
EC2 + PM2
Runs the API, deployed from GitHub Actions.
Trade-offs
- 01
Socket.io on a long running server
Realtime connections need a process that stays up, so the API runs on EC2 with PM2 instead of serverless functions.
- 02
Media in S3, not in the database
Files go to object storage and only references live in Turso, which keeps the database small.
- 03
One auth model for REST and sockets
Reusing the Auth0 JWT on both paths means one place to reason about who can do what.
Try it
Chatify is live and the source is on GitHub under the MIT license.