A backend REST API for a video-sharing platform — built with Node.js, Express.js, MongoDB, and Mongoose, featuring JWT authentication, Cloudinary-powered media storage, playlists, comments, likes, and channel analytics.
Repository: github.com/Sohaib-Arshid/Streamify
Streamify is the backend for a YouTube-style video platform. Users can register, upload videos, organize them into playlists, like and comment on content, search across the catalog, and view aggregate statistics for their own channel. Authentication is handled with short-lived access tokens and long-lived refresh tokens delivered as httpOnly cookies, and all media (avatars, cover images, video files, thumbnails) is offloaded to Cloudinary rather than stored on the API server.
This README documents the project exactly as implemented in the current source — see API_DOCUMENTATION.docx for the complete endpoint reference, including a few known inconsistencies worth being aware of before you build a client against it.
- Authentication — Register, login, logout, and JWT access/refresh token rotation
- User Profiles — Avatar & cover image uploads, account detail updates, password change
- Channel Pages — Public channel profile with subscriber counts (aggregation-based)
- Video Management — Upload, list, search, update, delete, and publish/unpublish videos
- Watch History & View Counting — Per-user watch history with one-time-per-user view increments
- Playlists — Create, update, delete playlists; add/remove videos
- Comments — Create, list (paginated), update, and delete comments per video
- Likes — Toggle like/unlike on videos with a live like count
- Search — Case-insensitive keyword search across video titles and descriptions
- Dashboard — Aggregate channel statistics: views, likes, subscribers, top & recent videos
⚠️ Note: TheSubscriptionmodel exists and is used to read subscriber counts, but there is currently no Subscribe/Unsubscribe endpoint in the codebase — see the Architecture documentation for details.
| Category | Technology |
|---|---|
| Runtime | Node.js |
| Framework | Express.js |
| Database | MongoDB + Mongoose |
| Authentication | JSON Web Tokens (JWT), bcrypt |
| File Uploads | Multer (local temp storage) |
| Media Hosting | Cloudinary |
| Pagination Plugin | mongoose-aggregate-paginate-v2 |
| Containerization | Docker |
| Hosting / Deployment | Railway |
| API Testing | Postman |
Streamify follows a layered structure:
Client → Express App (CORS, body parsing, cookies) → Router → Middleware (Auth / Multer) → Controller → Mongoose Model → MongoDB
↳ Cloudinary (media)
For the full breakdown — request lifecycle, JWT flow, Multer/Cloudinary flow, and module-by-module wiring — see ARCHITECTURE.docx in the documentation set.
src/
├── app.js # Express app, middleware, route mounting
├── index.js # Entry point — env config, DB connect, server start
├── constans.js # DB_NAME constant
├── db/index.js # Mongoose connection logic
├── controllers/ # Business logic per feature
│ ├── user.controller.js
│ ├── video.controller.js
│ ├── playlist.controller.js
│ ├── comment.controller.js
│ ├── dashboard.controller.js
│ └── search.controller.js
├── models/ # Mongoose schemas
│ ├── user.models.js
│ ├── video.models.js
│ ├── playlist.models.js
│ ├── comment.models.js
│ ├── like.models.js
│ └── subscription.models.js
├── middlewares/
│ ├── auth.middleware.js # verifyJWT
│ └── multer.middlewares.js # File upload config
├── routes/
│ ├── user.routes.js # Also wires Comment + Like endpoints
│ ├── video.routes.js
│ ├── playlist.routes.js
│ ├── dashboard.routes.js
│ └── search.routes.js
├── utils/
│ ├── ApiError.js
│ ├── ApiResponse.js
│ ├── asyncHandler.js
│ └── cloudinary.js
└── postman/
└── streamify.postman_collection.json
Dockerfile
docker-compose.yml
.dockerignore
ℹ️ The source provided for this documentation did not include a
package.json. Generate one and install the dependencies actually imported across the codebase:
git clone https://github.com/Sohaib-Arshid/Streamify.git
cd Streamify
npm init -y
npm install express cors cookie-parser dotenv mongoose mongoose-aggregate-paginate-v2 bcrypt jsonwebtoken multer cloudinary
mkdir -p public/tempAdd "type": "module" to package.json — every source file uses ES-module import/export syntax.
Create a .env file at the project root:
PORT=3000
MONGODB_URI=mongodb+srv://<user>:<password>@<cluster-url>
CORS_ORIGIN=http://localhost:3000
ACCESS_TOKEN_SECRET=your_access_token_secret
ACCESS_TOKEN_EXPIRY=1d
REFRESH_TOKEN_SECRET=your_refresh_token_secret
REFRESH_TOKEN_EXPIRY=10d
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secretFull explanations for each variable (and a note about a dotenv path quirk in index.js) are in SETUP_GUIDE.docx.
node src/index.js
# or, with a "dev": "node src/index.js" script in package.json
npm run devVerify it's running:
curl http://localhost:3000/api/v1/health
# → { "status": "OK", "message": "Server is running" }All routes are prefixed with /api/v1.
| Module | Base Path | Description |
|---|---|---|
| Auth & Users | /api/v1/users |
Register, login, logout, tokens, profile, watch history, comments, likes |
| Videos | /api/v1/videos |
Upload, list, search, update, delete, publish toggle |
| Playlists | /api/v1/playlists |
Playlist CRUD, add/remove video |
| Dashboard | /api/v1/dashboard |
Channel analytics |
| Search | /api/v1/search |
Keyword video search |
| Health | /api/v1/health |
Liveness check |
👉 For every endpoint's method, auth requirement, request/response shape, and validation rules, see API_DOCUMENTATION.docx.
Postman
"name": "streamify",
"_collection_link": "https://go.postman.co/collection/52978744-89c32e09-fc57-4557-b414-7213bf380117?source=collection_link"
Add screenshots of your API responses (Postman), or a connected frontend, here:
docs/screenshots/
├── postman-collection.png
├── register-response.png
└── dashboard-stats.png
A ready-to-import collection is included at src/postman/streamify.postman_collection.json, covering user, video, playlist, comment, dashboard, and search requests.
Set up a Postman environment with a server variable pointing at http://localhost:3000/api/v1, then run register → login first (Postman will persist the auth cookies automatically for later requests).
Streamify is fully containerized with a Dockerfile, docker-compose.yml, and .dockerignore, so the API can be built and run in an isolated, reproducible environment without installing Node.js or MongoDB tooling directly on the host machine.
- Ensures the app runs the same way on every machine (dev, CI, or production)
- Removes the need to manually install Node.js, npm, or system dependencies locally
- Makes it trivial to hand off the project to another developer or deploy it to any container-based host
- Matches the exact environment used by the Railway deployment described below
docker build -t streamify-backend .docker run --env-file .env -p 8000:8000 streamify-backendOr, running it as a named container:
docker run --name streamify-container --env-file .env -p 8000:8000 streamify-backendBuild and start the container with Compose:
docker compose up --buildRun in detached mode (in the background):
docker compose up -ddocker compose downdocker psOnce running, the API is available at:
http://localhost:8000
Docker uses the exact same environment variables as the local (non-containerized) application — see the 🔐 Environment Variables section above. Pass them in via --env-file .env when using docker run, or through the environment/env_file config in docker-compose.yml.
Streamify is deployed on Railway and is currently live at:
🔗 https://streamify-production-24e2.up.railway.app
Railway is connected directly to the project's GitHub repository, so deployments are automatic — no manual build or upload step is required.
- Push code to GitHub.
- Railway automatically detects new commits.
- Railway builds the Docker image.
- Railway injects the environment variables.
- Railway starts the container.
- MongoDB Atlas connects.
- The API becomes available online.
Railway is linked to the GitHub repository, so every time new commits are pushed to the connected branch, Railway automatically triggers a rebuild and redeploys the updated Docker image — there is no need to manually rebuild or restart the service.
All environment variables must be configured inside Railway's project settings before deployment. These are the same variables used locally and in Docker:
PORT
MONGODB_URI
ACCESS_TOKEN_SECRET
ACCESS_TOKEN_EXPIRY
REFRESH_TOKEN_SECRET
REFRESH_TOKEN_EXPIRY
CLOUDINARY_CLOUD_NAME
CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET
CORS_ORIGINThe deployed API connects to a MongoDB Atlas cluster, so no self-hosted database is required in production. Make sure the Atlas cluster's network access rules allow connections from Railway.
| Platform | Railway |
| Live URL | https://streamify-production-24e2.up.railway.app |
| Database | MongoDB Atlas |
| Deployment Trigger | Automatic, on push to GitHub |
Full checklist in DEPLOYMENT_GUIDE.docx.
- Add a Subscribe/Unsubscribe endpoint (the
Subscriptionschema already exists but has no controller/route) - Add a global Express error-handling middleware so
ApiErrorreaches clients as structured JSON - Fix the compound-uniqueness bugs on
LikeandSubscriptionschemas (seeDATABASE_SCHEMA.docx) - Add automated tests (no test suite is currently present)
- Add request validation middleware (e.g.
zod/joi) instead of manualifchecks per controller - Add rate limiting on authentication endpoints
This is currently a personal/learning project. Issues and pull requests are welcome — please open an issue describing the change before submitting a PR.
No license file is currently included in the repository. Add a LICENSE file (e.g. MIT) to clarify usage terms for others.
Sohaib Arshid
- GitHub: @Sohaib-Arshid
- Portfolio: sohaib-arshid-developer-portfolio.vercel.app
- LinkedIn: sohaib-arshid-008172418
This README is one of seven documents generated for this project. The rest go deeper on specific areas:
| Document | Contents |
|---|---|
API_DOCUMENTATION.docx |
Every endpoint: method, auth, params, body, validation, responses, errors |
ARCHITECTURE.docx |
MVC structure, request lifecycle, JWT/Multer/Cloudinary flows, error handling |
DATABASE_SCHEMA.docx |
All 6 MongoDB collections, fields, relationships, ER overview, known schema bugs |
SETUP_GUIDE.docx |
Full local setup walkthrough with troubleshooting |
DEPLOYMENT_GUIDE.docx |
Production configuration, security checklist, deployment steps |
PROJECT_WORKFLOW.docx |
Step-by-step flow for every feature (registration → upload → engagement) |