Building FocusHub: My Deep Dive Into Real-Time Django, WebSockets & Productivity Design
A breakdown of the journey building FocusHub—a real-time virtual study room platform with live chat, Pomodoro sessions, lo-fi music, and gamified study tracking—powered by Django, PostgreSQL, Channels, and Render.
Published on: July 1, 2025

Building FocusHub wasn’t a weekend hack project—it was an end-to-end crash course in designing production-ready web apps with real-time components. From setting up Django Channels to deploying WebSocket-enabled apps on Render, I hit every wall, fought every 403, and learned more in 3 weeks than most textbooks could teach in a semester.
This post walks through what I built, how it works, and what it taught me.
🎯 What is FocusHub?
FocusHub is a virtual productivity space where users can:
- Join real-time study rooms and chat with others via WebSockets
- Use a Pomodoro timer to track sessions
- Listen to lo-fi music embedded from curated static tracks
- Rate their productivity via session-end prompts & visual dashboards
- View session history, notes, and time breakdowns
- Track weekly study progress and heatmaps
🔧 Major Features and How They Work
💬 Real-Time Study Rooms (Django Channels + ASGI)
This was my first dive into ASGI with Django for WebSockets. Traditional WSGI just wouldn’t cut it.
- Used Daphne instead of Gunicorn
- Set up
rooms.routingfor WebSocket logic - Chat functionality via channel layers and async consumers
Lesson: ASGI needs a whole different setup—`asgi.py`, middleware, routing—debugging async stack traces was brutal but worth it.
⏲️ Pomodoro Timer & Session Logs
Each session is logged with a model tracking start and end time, auto-calculating duration. The timer frontend syncs with backend logs.
Lesson: I nearly cried over “False min” showing up in the dashboard—fixed it with a clean `@property` decorator and proper `total_seconds()` handling.
🎵 Lo-fi Music Integration
- Static MP3 tracks served from assets
- Used WhiteNoise for static file serving on Render
- Fixed a bunch of 404s from incorrect paths
Lesson: Never forget to configure `STATICFILES_DIRS`, `STATIC_ROOT`, and run `collectstatic`. Ever.
🧠 Gamified Productivity Ratings
- Streak tracking and session streaks
- Leaderboards for most productive rooms and users
- Study consistency visualized via heatmaps
- Weekly stats: hours, session counts, and durations
Lesson: Little visual nudges (like streak counters) go a long way in engagement and habit-building.
📊 Recent Sessions Timeline
The dashboard shows your most recent sessions including room title, duration, and notes—great for accountability.
🏗️ The Deployment Journey (aka The Struggles)
ModuleNotFoundError: app– from Render’s default `gunicorn app:app`- 404s from missing
collectstatic web: command not found– due to `web:` in `startCommand`403 CSRF– fixed with `CSRF_TRUSTED_ORIGINS`auth_user does not exist– forgot `migrate` 🤦♂️- No predeploy scripts – so I hacked
migrateinto `asgi.py`
Lesson: Render’s free tier is amazing but has limitations. You learn dirty deployment hacks fast—and that’s a superpower in itself.
🧠 Tech Stack
- Frontend: HTML, TailwindCSS, JS
- Backend: Django, Channels, PostgreSQL
- Real-Time: ASGI, Daphne, WebSockets
- Hosting: Render (free tier)
- Static Files: WhiteNoise
💡 Final Thoughts
This project made me appreciate how much goes into building even a “simple” platform. From backend logic to UI to deployment and devops—everything matters.
You can try the live site 👉 FocusHub
Or check out the code on GitHub (or DM me on LinkedIn).
— Rohit