Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

96 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ URL Shortener Application β€” Node.js, Express, MongoDB & JWT (MVC Architecture)

A full-featured, secure URL Shortener RESTful Web Application built using Node.js, Express.js, MongoDB (Mongoose), and Server-Side Rendering (EJS). The project implements strict MVC Architecture, stateless JWT Authentication (via HTTP-Only Cookies), and Role-Based Access Control (RBAC).


πŸ”₯ Key Features & Implementation Highlights

  • πŸ—οΈ Clean MVC Architecture: Modular structure separating Models (Schemas), Views (EJS Templates), Controllers (Business Logic), and Middlewares/Services.
  • πŸ” JWT Authentication: Stateless session management using JSON Web Tokens set in secure browser cookies.
  • πŸ›‘οΈ Role-Based Access Control (RBAC) Middleware:
    • Normal Users: Can generate short URLs, view, manage, and track click analytics for only their own generated links.
    • Admin Users: Possess elevated privileges to view and manage all generated URLs across the entire platform.
  • πŸ“ˆ Real-Time Click Analytics: Dynamic redirection tracking total visits and timestamps for each generated short URL.
  • πŸ”’ Security & Best Practices: Middleware-level authorization checks, custom error handling, and environment-variable-ready (.env) configuration.

πŸ› οΈ Tech Stack & Tools

  • Runtime: Node.js (v18+)
  • Framework: Express.js
  • Template Engine: EJS (Embedded JavaScript)
  • Database: MongoDB (Local Community Server & Atlas Ready)
  • ODM Library: Mongoose
  • Utilities: nanoid, nodemon, cookie-parser, uuid, jsonwebtoken, dotenv
  • API Testing: Postman
  • Version Control: Git, GitHub

✨ Features

  • πŸ—οΈ MVC Architecture – Clean separation of concerns with Models, Views, Controllers, Routes, and Services.
  • πŸ” JWT Authentication & Cookies – Secure user signup/login system powered by JSON Web Tokens stored in HTTP-only cookies.
  • πŸ›‘οΈ Role-Based Access Control (RBAC) – Middleware-level authorization layer restricting routes based on user roles (Admin, Normal).
  • πŸ–ΌοΈ Server-Side Rendering (SSR) – Clean, dynamic user interfaces rendered using the EJS templating engine.
  • πŸ”— Dynamic URL Shortening – Generates short, unique IDs using nanoid for fast link management.
  • πŸ“Š Click Analytics & History – Tracks total clicks and logs visit timestamps inside MongoDB for every generated link.
  • βš™οΈ Centralized Environment Vault – Secure handling of sensitive keys (MONGO_URL, JWT_SECRET, PORT) via .env integration.
  • πŸ—„οΈ MongoDB & Mongoose Validation – Schema-level data validation and efficient database connectivity.
  • ⚑ Developer Workflow – Instant auto-reloads during development powered by nodemon.

πŸ› οΈ Tech Stack & Dependencies

Tool / Library Type Purpose
Node.js Runtime JavaScript execution engine on server-side
Express.js Framework Fast, unopinionated web framework for Node.js
MongoDB Database NoSQL Document-based database
Mongoose ODM Library Schema-based modeling for MongoDB & Express
nodemon Developer Tool Automatically restarts the node application when file changes in the directory are detected
nanoid Utility Small, secure, URL-friendly unique string ID generator
EJS Template Engine Server-side rendering (SSR) of dynamic HTML templates
uuid Utility Cryptographically strong Universally Unique Identifier (UUID) generator (e.g., v4 for unique session/user IDs)
jsonwebtoken Authentication Generates and verifies digital signatures/tokens (JWT) to securely pass information between client & server
cookie-parser Middleware Express middleware to parse incoming request Cookie headers and populate req.cookies
dotenv Utility Loads environment variables from a .env file into process.env
Postman API Client Testing REST API endpoints (GET, POST, PATCH, DELETE)

πŸ“‚ Project Directory Structure

Generated: 8/2/2026, 1:35:39 PM Root Path: workspace\Node

β”œβ”€β”€ πŸ“ Learning
β”‚   β”œβ”€β”€ πŸ“ Events
β”‚   β”‚   β”œβ”€β”€ πŸ“„ main.js
β”‚   β”‚   └── πŸ“„ test.txt
β”‚   β”œβ”€β”€ πŸ“ Express
β”‚   β”‚   β”œβ”€β”€ βš™οΈ .gitignore
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.js
β”‚   β”‚   β”œβ”€β”€ βš™οΈ package-lock.json
β”‚   β”‚   └── βš™οΈ package.json
β”‚   β”œβ”€β”€ πŸ“ First
β”‚   β”‚   β”œβ”€β”€ πŸ“„ contacts.txt
β”‚   β”‚   β”œβ”€β”€ πŸ“„ file.js
β”‚   β”‚   β”œβ”€β”€ πŸ“„ file.txt
β”‚   β”‚   β”œβ”€β”€ πŸ“„ math.js
β”‚   β”‚   β”œβ”€β”€ πŸ“„ modules.js
β”‚   β”‚   β”œβ”€β”€ βš™οΈ package.json
β”‚   β”‚   └── πŸ“„ test.txt
β”‚   β”œβ”€β”€ πŸ“ HTTP
β”‚   β”‚   └── πŸ“„ http-notes.js
β”‚   β”œβ”€β”€ πŸ“ RestAPI
β”‚   β”‚   β”œβ”€β”€ πŸ“ controllers
β”‚   β”‚   β”‚   └── πŸ“„ user.js
β”‚   β”‚   β”œβ”€β”€ πŸ“ logs
β”‚   β”‚   β”‚   └── πŸ“„ logs.txt
β”‚   β”‚   β”œβ”€β”€ πŸ“ middlewares
β”‚   β”‚   β”‚   └── πŸ“„ middleware.js
β”‚   β”‚   β”œβ”€β”€ πŸ“ models
β”‚   β”‚   β”‚   └── πŸ“„ user.js
β”‚   β”‚   β”œβ”€β”€ πŸ“ routes
β”‚   β”‚   β”‚   └── πŸ“„ user.js
β”‚   β”‚   β”œβ”€β”€ πŸ“ views
β”‚   β”‚   β”‚   └── βš™οΈ .gitkeep
β”‚   β”‚   β”œβ”€β”€ βš™οΈ .gitignore
β”‚   β”‚   β”œβ”€β”€ βš™οΈ MOCK_DATA.json
β”‚   β”‚   β”œβ”€β”€ πŸ“„ connection.js
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.js
β”‚   β”‚   β”œβ”€β”€ βš™οΈ package-lock.json
β”‚   β”‚   └── βš™οΈ package.json
β”‚   β”œβ”€β”€ πŸ“ Server
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.js
β”‚   β”‚   β”œβ”€β”€ πŸ“„ log.txt
β”‚   β”‚   β”œβ”€β”€ βš™οΈ package.json
β”‚   β”‚   └── πŸ“„ url_note.js
β”‚   └── πŸ“ Versions
β”‚       └── πŸ“„ version.js
β”œβ”€β”€ πŸ“ Shortener_URL
β”‚   β”œβ”€β”€ πŸ“ controllers
β”‚   β”‚   β”œβ”€β”€ πŸ“„ static.js
β”‚   β”‚   β”œβ”€β”€ πŸ“„ url.js
β”‚   β”‚   └── πŸ“„ user.js
β”‚   β”œβ”€β”€ πŸ“ middlewares
β”‚   β”‚   └── πŸ“„ auth.js
β”‚   β”œβ”€β”€ πŸ“ models
β”‚   β”‚   β”œβ”€β”€ πŸ“„ url.js
β”‚   β”‚   └── πŸ“„ user.js
β”‚   β”œβ”€β”€ πŸ“ routes
β”‚   β”‚   β”œβ”€β”€ πŸ“„ static.js
β”‚   β”‚   β”œβ”€β”€ πŸ“„ url.js
β”‚   β”‚   └── πŸ“„ user.js
β”‚   β”œβ”€β”€ πŸ“ services
β”‚   β”‚   └── πŸ“„ auth.js
β”‚   β”œβ”€β”€ πŸ“ views
β”‚   β”‚   β”œβ”€β”€ πŸ“„ home.ejs
β”‚   β”‚   β”œβ”€β”€ πŸ“„ login.ejs
β”‚   β”‚   └── πŸ“„ signup.ejs
β”‚   β”œβ”€β”€ βš™οΈ .gitignore
β”‚   β”œβ”€β”€ πŸ“„ app.js
β”‚   β”œβ”€β”€ πŸ“„ connect.js
β”‚   β”œβ”€β”€ βš™οΈ package-lock.json
β”‚   β”œβ”€β”€ βš™οΈ package.json
β”‚   └── βš™οΈ vercel.json
└── πŸ“ README.md

Prerequisites

  • Node.js (v16 or higher)
  • npm package manager
  • Basic knowledge of JavaScript

πŸ“œ Available Scripts

In the project directory, you can run the following commands configured in package.json:

πŸš€ Start Server

npm start

🌐 Deployment & Environment Setup

1. MongoDB Atlas Configuration

Before deploying, ensure your database access is open to Vercel:

  1. Go to MongoDB Atlas.
  2. Navigate to Network Access under Security.
  3. Click Add IP Address and select Allow Access from Anywhere (0.0.0.0/0).
  4. Save changes.

2. Environment Variables on Vercel

Set up your environment variables in Vercel before or after deployment:

  1. In your Vercel Project Dashboard, go to Settings βž” Environment Variables.
  2. Add your environment key-value pairs (e.g., MONGO_URL, JWT_SECRET, PORT).
  3. ⚠️ Important Requirement:
    • Ensure Production, Preview, and Development targets are ALL CHECKED.
    • DO NOT toggle on the "Sensitive" option for MONGO_URL to prevent variable save/sync issues.

3. Deploy to Vercel

  1. Push your latest code to GitHub.
  2. Go to vercel.com and log in.
  3. Click "New Project".
  4. Connect your GitHub repository.
  5. Select/Connect the exact project root folder containing package.json (to avoid nested directory deployment issues).
  6. Configure Build Settings:
    • Vercel automatically detects Vite/Node settings.
    • Toggle the "Build Command" switch and manually type npm run build to override it (if using a build step).
  7. Ensure all Environment Variables (MONGO_URL, etc.) are added under the project settings.
  8. Click "Deploy".

πŸ’‘ Note: If you edit or update any Environment Variable after deploying, always go to the Deployments tab, click the three dots (...) on the latest deployment, and select Redeploy to apply changes! & Make sure your project structure strictly follows the root layout:

Shortener_URL/
β”œβ”€β”€ models/
β”œβ”€β”€ routes/
β”œβ”€β”€ middlewares/
β”œβ”€β”€ views/
β”œβ”€β”€ .env
β”œβ”€β”€ app.js
β”œβ”€β”€ connect.js
└── package.json

βš™οΈ Environment Setup & Tool Installation Guide

1. Installing Node.js & NPM

Download and install the LTS version from Node.js Official Site. Verify installation in your terminal:

node -v
npm -v

2. Installing MongoDB Community Server & Mongosh

  1. Download MongoDB Community Server from MongoDB Download Center.
  2. Download MongoDB Shell (mongosh) to run CLI database operations.
  3. Start the local server daemon:
# Verify connection using mongosh CLI
mongosh

3. Setting Up package.json with ES Modules

Initialize your Node project inside any project directory:

npm init

During the prompt configuration, fill out the selections like this:

package name: (name)

version: (1.0.0)

description: may add ​ entry point: (index.js)​

test command: just enter​

git repository: (https://github.com/username/repo_name.git)

keywords: may add

author: may add

license: (ISC)

type: (commonjs) recommended module

Is this OK? (yes)


To enable modern ES6 import/export syntax instead of require(), open package.json and add "type": "module":

{
  "name": "node",
  "version": "1.0.0",
  "bugs": {
    "url": "https://github.com/username/repo/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/username/repo.git"
  },
  "license": "ISC",
  "author": "",
  "type": "commonjs",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node app.js" // add manually write "nodemon index.js" if installed
  }
}

4. Installing Core Dependencies

Run this command inside your project directory to install npm pakages in pakages.json file:

npm i express
npm i mongoose
npm i nanoid
npm i nodemon
npm i ejs
npm i cookie-parser
npm i uuid
npm i jsonwebtoken
npm i dotenv

It automatically Create package.json if not exists. Like

{
  "name": "pakage name",
  "version": "1.0.0",
  "description": "Something",
  "keywords": [
    "keywords"
  ],
  "homepage": "https://github.com/github.com/username#readme",
  "bugs": {
    "url": "https://github.com/github.com/username/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/github.com/username.git"
  },
  "license": "ISC",
  "author": "Auther",
  "type": "module",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app.js"
  },
  "dependencies": {
    "cookie-parser": "^1.4.7",
    "dotenv": "^17.4.2",
    "ejs": "^6.0.1",
    "express": "^5.2.1",
    "jsonwebtoken": "^9.0.3",
    "mongoose": "^9.8.0",
    "nanoid": "^6.0.0",
    "nodemon": "^3.1.14",
    "uuid": "^14.0.1"
  }
}

Note: Install pakages when needed


🎯 Architecture & Modules Overview

Component / Module Purpose
index.js Main entry point; configures dotenv, EJS view engine, global middlewares (cookie-parser, express.json), DB connection, and routes.
connect.js Handles async database connection setup using Mongoose to connect with MongoDB.
models/url.js Mongoose schema for short links; stores shortId, redirectURL, visitHistory, and reference to createdBy user.
models/user.js Mongoose schema for authentication; manages user details including name, email, password, and role (Normal, Admin).
controllers/url.js Core URL business logic; generates unique shortIds via nanoid and logs click timestamps upon redirection.
controllers/user.js Handles user authentication logic (HandleUserSignup, HandleUserLogin) and sets JWT cookies.
services/auth.js Pure JWT token manager; encodes user payload on login (setUser) and decodes/verifies incoming tokens (getUser).
middlewares/auth.js Security layer (AuthorizationHeaderVal, RestrictTo); extracts JWT cookies and enforces role-based access control.
routes/url.js Protected URL endpoints (POST /url); restricted to authenticated roles (Normal, Admin).
routes/static.js Handles SSR page rendering for home dashboard (/), signup (/signup), and login (/login) views.
routes/user.js Endpoints for authentication workflows (POST /user/signup, POST /user/login).
views/ Contains EJS template files (home.ejs, signup.ejs, login.ejs) for rendering the user interface.

πŸ§ͺ Postman & API Endpoint Testing

  • Install Postman from 🌐 postman.com to test API's

πŸ’‘ Note: Postman automatically manages the HTTP-only token cookie after login.

1. User Signup

  • Method & Route: POST /user/signup
  • Body (JSON):
{
  "name": "MehmoodCoder",
  "email": "mehmood@example.com",
  "password": "Password123"
}

2. User Login

  • Method & Route: POST /user/login
  • Body (JSON):
{
  "email": "mehmood@example.com",
  "password": "Password123"
}
  • Response: Sets HTTP-only token cookie.

3. Create Short URL (Protected)

  • Method & Route: POST /url
  • Body (JSON):
{
  "url": "[https://github.com/MehmoodCoder](https://github.com/MehmoodCoder)"
}
  • Response (201 Created):
{
  "id": "8xK9p2Lm"
}

4. Redirect Link

  • Method & Route: GET /url/:shortId
  • Example: http://localhost:4000/url/8xK9p2Lm
  • Response (302 Found): Redirects to target destination & updates analytics.

πŸ—‘οΈ Database Maintenance via mongosh

If you need to clear all test documents without dropping the collection structure:

# 1. Open mongosh CLI
mongosh

# 2. Show All DB's
show dbs

# 3. Switch to project DB
use project-db-name

# 4. Show Exist DB collections
show collections

# 5. Show All Documents
db.collection.find({})

# 6. Delete all documents inside 'project-db-name' collection if wants
db.project-db-name.deleteMany({})

# 5. Exit the interactive MongoDB Shell session and return to the system terminal
.exit

# 6. And many more

πŸ“š Learning Resources


πŸ’‘ Core Concepts Covered

  • βœ… MVC Architecture – Structuring backend apps using Models, Views, Controllers, Routes, and Services
  • βœ… Authentication & JWT – Issuing, signing, and verifying JSON Web Tokens (JWT) for user authentication
  • βœ… Cookie Management – Storing and parsing HTTP-only cookies safely with cookie-parser
  • βœ… Role-Based Access Control (RBAC) – Restricting route access dynamically based on user roles (Admin, Normal)
  • βœ… Server-Side Rendering (SSR) – Dynamic UI rendering with EJS and passing session data to views
  • βœ… MongoDB & Mongoose Schema Design – Managing schemas, data types, unique constraints, and population
  • βœ… Database Aggregation & Analytics – Array updates ($push) for recording link click history and timestamps
  • βœ… Express Middleware Pipeline – Request body parsing (json, urlencoded), auth state injection, and protected route guards
  • βœ… RESTful Endpoints & Redirection – Dynamic parameter handling (req.params) and 302 HTTP redirects
  • βœ… Environment Vault & Tooling – Managing configuration variables via .env and automated dev workflows with nodemon

πŸ‘€ Author

MehmoodCoder


πŸ“„ License

This project is open source and available under the MIT License.


πŸ“ Changelog

v2.0.0 (Latest Update)

  • πŸ” JWT Authentication System – Implemented user signup and login flows using JSON Web Tokens (JWT) for stateless authentication.
  • πŸͺ Cookie-Based Sessions – Integrated cookie-parser middleware to securely pass and verify HTTP-only auth tokens.
  • πŸ›‘οΈ Role-Based Access Control (RBAC) – Added authorization middlewares (RestrictTo) to restrict endpoints based on user roles (Admin, Normal).
  • πŸ–ΌοΈ SSR Dashboard (EJS Integration) – Built server-side rendered views for user login, registration, and URL management dashboard.
  • βš™οΈ Environment Management – Centralized sensitive configurations (PORT, MONGO_URL, JWT_SECRET) into .env file setup.

v1.0.0 (Initial Release)

  • πŸš€ Core Fundamentals – Built custom HTTP servers, learned EventEmitters, File System (fs) operations, and NPM module handling.
  • πŸ› οΈ RESTful API Architecture – Structured scalable Express servers following clean MVC (Model-View-Controller) patterns.
  • ⚑ URL Shortener Microservice – Implemented nanoid logic to generate unique short IDs for long URLs.
  • πŸ—„οΈ MongoDB Integration – Connected Mongoose schemas with real-time URL redirect logic and automated visit analytics tracking.
  • πŸ› οΈ Developer Experience – Configured nodemon for auto-reloading during development and created custom logging middlewares.

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Happy Coding without Chai ! β˜•

About

🟒 Node.js Core Fundamentals ⚑ β€” A lightweight & dependency-free HTTP server 🌐 built strictly using pure Node.js modules (`http` & `fs` πŸ“) without Express! πŸš€ Features asynchronous file system read/write operations πŸ’Ύ, native request routing πŸ”„, custom npm execution scripts πŸ“œ, and deep Event Loop architecture practice πŸ§ πŸ’»

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Contributors

Languages