Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/barcode8/VideoHub/llms.txt

Use this file to discover all available pages before exploring further.

VideoHub’s backend is a standard Node.js application — no special toolchain required. By the end of this guide you will have the API running locally, a user account registered, and a valid JWT access token ready to use against any protected endpoint.

Prerequisites

Before you begin, make sure you have:
  • Node.js 18 or higher — the backend uses ES Modules ("type": "module") and modern async patterns
  • MongoDB — a MongoDB Atlas free-tier cluster or a local mongod instance on port 27017
  • Cloudinary account — a free account at cloudinary.com to obtain your cloud name, API key, and API secret

Setup Steps

1

Clone the repository

Clone the VideoHub monorepo and navigate into the backend directory:
git clone https://github.com/barcode8/VideoHub.git
cd VideoHub/Backend
2

Install dependencies

Install all production and development dependencies with npm:
npm install
This installs Express 5, Mongoose, Cloudinary SDK, Multer, bcrypt, jsonwebtoken, cookie-parser, and the rest of the packages listed in package.json.
3

Configure your environment

Copy the sample environment file and fill in your credentials:
cp .env.sample .env
Open .env and set every variable:
PORT=5000
HOST=0.0.0.0

# URL shown to browsers in CORS headers — point this at your frontend origin
CORS_ORIGIN=http://localhost:5173

# MongoDB connection string (Atlas or local)
MONGODB_URL=mongodb+srv://<username>:<db_password>@cluster0.ikrv56o.mongodb.net

# JWT secrets — use a long random string for each (e.g. openssl rand -hex 64)
ACCESS_TOKEN_SECRET=
ACCESS_TOKEN_EXPIRY=1d
REFRESH_TOKEN_SECRET=
REFRESH_TOKEN_EXPIRY=10d

# Optional: Cloudinary URLs for default avatar/cover if user doesn't upload one
DEFAULT_AVATAR=
DEFAULT_COVER_IMAGE=

# Cloudinary credentials — find these in your Cloudinary dashboard
CLOUDINARY_API_KEY=
CLOUDINARY_SECRET_KEY=
CLOUDINARY_CLOUD_NAME=
Generate strong secrets with openssl rand -hex 64. Never reuse the same value for ACCESS_TOKEN_SECRET and REFRESH_TOKEN_SECRET.
4

Start the development server

Launch the server with nodemon so it restarts automatically on file changes:
npm run dev
You should see output similar to:
App is listening on PORT:5000
The server binds to the PORT defined in your .env file (default 5000) and connects to MongoDB before accepting traffic. If the database connection fails, the process exits with a non-zero code.
5

Verify with the healthcheck endpoint

Confirm the API is reachable:
curl http://localhost:5000/api/v1/healthcheck
A successful response looks like:
{
  "statusCode": 200,
  "data": {},
  "message": "Server is healthy and running smoothly"
}

Register Your First User

The registration endpoint accepts multipart/form-data (the route uses Multer middleware), but avatar and cover-image file uploads are not currently processed server-side. Only the text fields are required: username, email, and password. fullName is optional — the server falls back to the username value if it is omitted.
curl -X POST http://localhost:5000/api/v1/users/register \
  -F "username=johndoe" \
  -F "email=john@example.com" \
  -F "password=supersecret123" \
  -F "fullName=John Doe"
A successful registration returns the new user object (without the password or refresh token fields):
{
  "statusCode": 200,
  "data": {
    "_id": "6860a1b2c3d4e5f678901234",
    "username": "johndoe",
    "email": "john@example.com",
    "fullName": "John Doe",
    "avatar": "https://res.cloudinary.com/your-cloud/image/upload/default_avatar.jpg",
    "coverImage": "https://res.cloudinary.com/your-cloud/image/upload/default_cover.jpg",
    "watchHistory": [],
    "createdAt": "2025-06-28T12:00:00.000Z"
  },
  "message": "User registered sucessfully"
}

Log In and Receive Tokens

curl -X POST http://localhost:5000/api/v1/users/login \
  -H "Content-Type: application/json" \
  -d '{"email": "john@example.com", "password": "supersecret123"}'
The response carries accessToken and refreshToken in two places simultaneously:
  1. HTTP-only cookies (accessToken and refreshToken) — set with httpOnly: true, secure: false, sameSite: "Lax" and consumed automatically by browsers
  2. JSON body — available for non-browser clients (mobile apps, CLI tools)
{
  "statusCode": 200,
  "data": {
    "user": {
      "_id": "6860a1b2c3d4e5f678901234",
      "username": "johndoe",
      "email": "john@example.com",
      "fullName": "John Doe"
    },
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "message": "User logged in successfully"
}
The access token expires after ACCESS_TOKEN_EXPIRY (default 1d). Use the refresh token against /api/v1/users/refresh-token to obtain a new access token without requiring the user to log in again.

Make an Authenticated Request

Pass the access token in the Authorization header as a Bearer token. The example below fetches the current user’s channel profile:
curl http://localhost:5000/api/v1/users/current-user \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Almost every endpoint beyond /healthcheck and /users/login//users/register requires a valid JWT access token. Send it either as the Authorization: Bearer <token> header or let the browser send the accessToken cookie automatically. Missing or expired tokens return a 401 Unauthorized response.

Build docs developers (and LLMs) love