BODY/DOUBLE is an accountability-partner web app inspired by Omegle. Sign up, set your focus preferences, get paired with another person in real time, and work together through a Pomodoro-style session — then take a short break and choose to stay matched or find someone new.
Live demo: https://body-double.onrender.com
- Account auth — Email/password signup and login with Passport and secure sessions
- Focus preferences — Choose work type (studying, coding, writing, editing) and camera on/off before matching
- Real-time matching — Socket.io queue pairs users into a shared room
- Video or text sessions — Camera-on users join a WebRTC video room with chat; camera-off users get a text-only focus room
- Pomodoro flow — 25-minute focus timer, then a 5-minute break room with options to stay together or rematch
- Responsive UI — EJS views with shared layout partials and custom CSS
| Layer | Technology |
|---|---|
| Frontend | EJS, CSS3, Vanilla JavaScript |
| Backend | Node.js, Express |
| Database | MongoDB (Mongoose) |
| Auth | Passport Local, express-session, bcrypt, connect-mongo |
| Realtime | Socket.io |
| Video | WebRTC (signaling over Socket.io) |
| Hosting | Render |
- Visit the landing page and create an account (or log in)
- Set your preferences on
/filters - Join the match queue on
/match - When paired, you’re sent to
/videoChat/:roomIdor/textChat/:roomId - After the focus timer, continue to
/breakand choose stay or find new
body-double/
├── server.js # Express + Socket.io entry point
├── config/ # Database, Passport, and local .env
├── routes/ # Express route definitions
├── controllers/ # Request handlers
├── models/ # Mongoose models (User, Filters, Post)
├── middleware/ # Auth, Multer, Cloudinary
├── views/ # EJS templates and partials
└── public/ # Static CSS and images
- Node.js (v18+ recommended)
- A MongoDB Atlas cluster (or local MongoDB)
- (Optional) Cloudinary credentials if you use image upload routes
git clone https://github.com/NaimaBogran/body-double.git
cd body-doublenpm installCreate config/.env (this is the path the app loads):
PORT=3000
DB_STRING=mongodb+srv://<user>:<password>@<cluster>.mongodb.net/?appName=<app>
SESSION_SECRET=a_long_random_string
# Optional — used by legacy post/upload routes
CLOUD_NAME=
API_KEY=
API_SECRET=
# Optional — production only
NODE_ENV=developmentNotes
- Prefer a MongoDB Atlas region close to you (for example, AWS
us-east-1) so local and hosted connections are reliable - In Atlas Network Access, allow your IP for local development, and
0.0.0.0/0if you deploy to Render (dynamic IPs) - Never commit
config/.env
npm startThis runs nodemon server.js. Open http://localhost:3000.
You should see MongoDB Connected: ... in the terminal when the database connection succeeds.
- Push your code to GitHub (do not commit secrets)
- Create a Web Service on Render pointed at this repo
- Suggested settings:
- Build command:
npm install - Start command:
node server.js
- Build command:
- Add the same environment variables from
config/.envin the Render Environment tab (DB_STRING,SESSION_SECRET, etc.) - Set
NODE_ENV=production - Ensure Atlas Network Access allows Render to connect (typically
0.0.0.0/0on free tiers)
A Procfile is included with web: node server.js for production-style starts.
| Method | Path | Description |
|---|---|---|
| GET | / |
Landing page |
| GET/POST | /signup |
Create an account |
| GET/POST | /login |
Sign in |
| GET | /logout |
End session |
| GET/POST | /filters |
Work type + camera preferences |
| GET | /match |
Match queue |
| GET | /videoChat/:roomId |
Video focus session |
| GET | /textChat/:roomId |
Text focus session |
| GET | /break |
Break timer + rematch choices |
| GET | /about |
About the creator |
| GET | /pomodoroPage |
Pomodoro technique overview |
MIT

