A REST API for a video platform (uploads, playlists, comments, likes, subscriptions) built with TypeScript, Express, and MongoDB.
This service provides the backend for a YouTube‑style application. It implements authentication, media uploads, and social interactions while following a layered architecture and strict validation strategy.
Key characteristics:
- JWT authentication (access + refresh tokens)
- Role‑based authorization
- Cloud media storage (Cloudinary)
- Schema validation (Zod)
- Structured API responses and centralized error handling
- Modular controller/service separation
- Sign up and login
- Access and refresh tokens
- Watch history tracking
- Roles:
user,admin
- Upload video and thumbnail
- Update metadata
- Delete (owner or admin)
- View counting
- Comments and replies
- Likes on videos and comments
- Channel subscriptions
- Create and edit playlists
- Add/remove videos
- Private playlists
| Layer | Technology |
|---|---|
| Language | TypeScript |
| Runtime | Node.js |
| Framework | Express 5 |
| Database | MongoDB |
| ODM | Mongoose |
| Auth | JSON Web Token |
| Validation | Zod |
| Uploads | Multer |
| Storage | Cloudinary |
| Security | bcrypt |
src/
├── app.ts Express configuration
├── index.ts Entry point
├── db/ Database connection
├── models/ Mongoose schemas
├── routes/ API routes
├── controllers/ HTTP handlers
├── services/ Business logic
├── middlewares/ Auth, validation, uploads
├── validators/ Zod schemas
├── utils/ Errors, responses, cloud storage
└── types/ TypeScript definitions
Request flow:
Client → Routes → Middleware → Controller → Service → Database/Cloudinary
- Node.js 18+
- MongoDB (local or Atlas)
- Cloudinary account
git clone https://github.com/zoanig/video-sharing-application-backend.git
cd video-sharing-application-backend
npm installCreate .env in the project root:
(This example is for local instance)
PORT=6969
MONGODB_URI=mongodb://127.0.0.1:27017
ACCESS_TOKEN_SECRET=access_secret
REFRESH_TOKEN_SECRET=refresh_secret
CLOUDINARY_CLOUD_NAME=cloud_name
CLOUDINARY_API_KEY=api_key
CLOUDINARY_API_SECRET=api_secretnpm run devBuild:
npm run buildType‑check:
npm run checkServer: http://localhost:6969
Tokens are issued on login.
Include the access token in requests:
Authorization: Bearer <access_token>
When the access token expires, request a new one using the refresh token endpoint.
Here is your entire API structure rewritten uniformly as lists:
- POST
/api/user/signup - POST
/api/user/login - PUT
/api/user/refresh - PUT
/api/user/profile
- POST
/api/video/upload - PUT
/api/video/update/:Id - GET
/api/video/view/:Id - DELETE
/api/video/delete/:Id
- POST
/api/playlist/create - PUT
/api/playlist/:Id - DELETE
/api/playlist/:Id - GET
/api/playlist/:Id - GET
/api/playlist/getall
- POST
/api/comment/:Id - POST
/api/comment/reply/:Id - PUT
/api/comment/:Id - DELETE
/api/comment/:Id
- PUT
/api/like/video/:Id - DELETE
/api/like/video/:Id - PUT
/api/like/comment/:Id - DELETE
/api/like/comment/:Id
- PUT
/api/subscription/:Id - DELETE
/api/subscription/:Id
Files are temporarily stored locally and then uploaded to Cloudinary.
Allowed types:
- image/jpeg
- image/png
- video/mp4
- video/mkv
Successful response:
{
"statusCode": 200,
"message": "Success",
"data": {}
}Error response:
{
"statusCode": 400,
"message": "Validation Failed",
"errors": []
}| Command | Description |
|---|---|
| npm run dev | Start development server |
| npm run build | Compile or rather "transpile" TypeScript to JavaScript |
| npm run check | Type checking |
MIT License
Muhammad Hassan