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).
- ποΈ 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:
NormalUsers: Can generate short URLs, view, manage, and track click analytics for only their own generated links.AdminUsers: 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.
- 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
- ποΈ 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
nanoidfor 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.envintegration. - ποΈ MongoDB & Mongoose Validation β Schema-level data validation and efficient database connectivity.
- β‘ Developer Workflow β Instant auto-reloads during development powered by
nodemon.
| 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) |
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
- Node.js (v16 or higher)
- npm package manager
- Basic knowledge of JavaScript
In the project directory, you can run the following commands configured in package.json:
npm startBefore deploying, ensure your database access is open to Vercel:
- Go to MongoDB Atlas.
- Navigate to Network Access under Security.
- Click Add IP Address and select Allow Access from Anywhere (
0.0.0.0/0). - Save changes.
Set up your environment variables in Vercel before or after deployment:
- In your Vercel Project Dashboard, go to Settings β Environment Variables.
- Add your environment key-value pairs (e.g.,
MONGO_URL,JWT_SECRET,PORT). β οΈ Important Requirement:- Ensure Production, Preview, and Development targets are ALL CHECKED.
- DO NOT toggle on the "Sensitive" option for
MONGO_URLto prevent variable save/sync issues.
- Push your latest code to GitHub.
- Go to vercel.com and log in.
- Click "New Project".
- Connect your GitHub repository.
- Select/Connect the exact project root folder containing
package.json(to avoid nested directory deployment issues). - Configure Build Settings:
- Vercel automatically detects Vite/Node settings.
- Toggle the "Build Command" switch and manually type
npm run buildto override it (if using a build step).
- Ensure all Environment Variables (
MONGO_URL, etc.) are added under the project settings. - 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.jsonDownload and install the LTS version from Node.js Official Site. Verify installation in your terminal:
node -v
npm -v- Download MongoDB Community Server from MongoDB Download Center.
- Download MongoDB Shell (
mongosh) to run CLI database operations. - Start the local server daemon:
# Verify connection using mongosh CLI
mongoshInitialize your Node project inside any project directory:
npm initpackage 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
}
}
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 dotenvIt 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
| 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. |
- Install Postman from π postman.com to test API's
π‘ Note: Postman automatically manages the HTTP-only
tokencookie after login.
- Method & Route:
POST /user/signup - Body (JSON):
{
"name": "MehmoodCoder",
"email": "mehmood@example.com",
"password": "Password123"
}- Method & Route:
POST /user/login - Body (JSON):
{
"email": "mehmood@example.com",
"password": "Password123"
}- Response: Sets HTTP-only
tokencookie.
- Method & Route:
POST /url - Body (JSON):
{
"url": "[https://github.com/MehmoodCoder](https://github.com/MehmoodCoder)"
}- Response (201 Created):
{
"id": "8xK9p2Lm"
}- Method & Route:
GET /url/:shortId - Example:
http://localhost:4000/url/8xK9p2Lm - Response (
302 Found): Redirects to target destination & updates analytics.
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
- π’ Node.js Official Documentation β Core Node.js concepts & runtime docs
- β‘ Express.js API Reference β Web framework, routing & middleware guides
- ποΈ MongoDB Manual β NoSQL database features & queries
- π Mongoose Docs β ODM schemas, models, and queries
- π¦ NPM Official Registry β Package manager & dependency discovery
- π JSON Web Tokens (JWT) β Token-based authentication mechanics
- π¨ EJS Templating Engine β Embedded JavaScript templates for SSR
- π² nanoid Documentation β Unique string generator for short URLs
- π§ͺ Postman Learning Center β API testing, environments & cookies
- β 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
.envand automated dev workflows withnodemon
MehmoodCoder
- π GitHub: github.com/MehmoodCoder
- π Portfolio: My Portfolio Link
This project is open source and available under the MIT License.
- π JWT Authentication System β Implemented user signup and login flows using JSON Web Tokens (JWT) for stateless authentication.
- πͺ Cookie-Based Sessions β Integrated
cookie-parsermiddleware 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.envfile setup.
- π 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
nanoidlogic 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
nodemonfor auto-reloading during development and created custom logging middlewares.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request