┌────────────────────────────────────────────────────────────────────────────┐
│ │
│ ███╗ ███╗ ██████╗ ██╗ ██╗██╗████████╗ ██████╗ ███████╗██╗ ██╗ │
│ ████╗ ████║██╔═══██╗██║ ██║██║╚══██╔══╝ ██╔══██╗██╔════╝██║ ██║ │
│ ██╔████╔██║██║ ██║███████║██║ ██║ ██║ ██║█████╗ ██║ ██║ │
│ ██║╚██╔╝██║██║ ██║██╔══██║██║ ██║ ██║ ██║██╔══╝ ╚██╗ ██╔╝ │
│ ██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ██║ ██████╔╝███████╗ ╚████╔╝ │
│ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═══╝ │
│ │
│ ◈ Personal Portfolio ◈ v2.0 ◈ Deployed on Render ◈ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
# Clone the repository
git clone https://github.com/MsParadox/Mohit_Portfolio.git
# Install dependencies
cd Mohit_Portfolio
npm install
cd backend && npm install
# Configure environment (create a `.env` in `backend/`)
# See the "Environment Variables" section below for required keys
# Run in development
cd ..
npm run dev ➜ http://localhost:5000
🏠 HERO — Interactive Particle Canvas
Mouse-reactive particle field · Animated headline · At-a-glance stats card
|
👤 ABOUT
Orbital animation · Stat badges · Tag cloud
|
🛠️ TECH STACK
Scroll-triggered animated bars · Rated tool pills
|
💼 PROJECTS
Featured card · Grid visual · Live demo links
|
🏆 ACHIEVEMENTS
ICPC · LeetCode Knight · CF Specialist · Contest ranks
|
📬 CONTACT
Live form → MongoDB + Email · Social links
|
Mohit_Portfolio/
│
│ ◈ FRONTEND (Vanilla HTML · CSS Modules · ES Modules)
│
├── index.html ← Semantic HTML, zero inline styles
│
├── css/
│ ├── animations.css ← Keyframes, reveal helpers, and motion tokens
│ ├── main.css ← Global layout, utilities and base styles
│ ├── mohit.css ← Page-specific tweaks / theme overrides
│ └── responsive.css ← Breakpoints and responsive helpers
│
├── js/
│ ├── main.js ← Entry point — imports & boots all modules
│ ├── loader.js ← Percentage-based intro loading screen
│ ├── contact.js ← Form → REST API + inline feedback
│ ├── form.js ← Form helpers & validation
│ ├── cursor.js ← Dot + lerp-ring cursor (pointer devices only)
│ ├── canvas.js ← Particle system class — mouse-reactive
│ ├── animations.js ← IntersectionObserver: reveal · bars · counters
│ ├── counters.js ← Count-up stat counters
│ ├── particles.js ← Particle utilities consumed by `canvas.js`
│ ├── reveal.js ← Section reveal helpers
│ └── mohit-app.js ← Page-specific glue logic
│
├── assets/ ← Resume PDF · favicon · OG image · screenshots
│
│ ◈ BACKEND (Node.js · Express · MongoDB via Mongoose)
│
├── backend/
│ ├── server.js ← Express app — middleware, routes, static files
│ ├── config/ ← configuration helpers
│ │ └── db.js ← MongoDB connection helper
│ ├── middleware/ ← security + error handler
│ │ └── errorHandler.js ← global error handler
│ ├── routes/
│ │ └── contactRoutes.js ← POST /api/contact · GET /api/contact (admin)
│ ├── controllers/ ← request validation, persistence, email jobs
│ │ └── contactController.js
│ ├── models/
│ │ └── Message.js ← Mongoose schema for messages
│ └── services/mailer.js ← Resend-based email notifications
│
│ ◈ DATABASE (MongoDB)
│
└── (MongoDB collections — `messages` collection managed via Mongoose)
|
⚡ Frontend Effects |
🔒 Backend & Security |
|
📱 Responsive Breakpoints |
🗄️ Database Schema |
▶ POST /api/contact — Submit the contact form
⚠️ Rate limited: 5 requests / IP / 15 minutes
▶ GET /api/contact — List all submissions (protected)
curl -H "x-admin-key: $JWT_SECRET" \
https://mohit-portfolio-bjd4.onrender.com/api/contactReturns newest-first, last 200 rows with preview (first 200 chars of message).
▶ PATCH (admin UI not included) — Update message metadata
This repository does not include a dedicated admin UI for mutating message state. Admins can update message documents directly in MongoDB (collection: messages) or implement a small authenticated PATCH endpoint that modifies read and notes fields.
▶ GET /api/health — Server + database status
// 200 — Healthy
{ "status": "ok", "db": "connected", "timestamp": "2025-05-24T10:00:00.000Z" }
// 503 — Database unreachable
{ "status": "error", "db": "unreachable", "timestamp": "..." }# ── Server ──────────────────────────────────────────────────────────
NODE_ENV=development
# Default port used by the backend
PORT=5000
# ── Database (MongoDB) ──────────────────────────────────────────────
# Example: mongodb+srv://user:pass@cluster0.mongodb.net/mydb
MONGO_URI=
# ── Resend (email) ──────────────────────────────────────────────────
# Get an API key at https://resend.com
RESEND_API_KEY=
# Optional from address: e.g. "Your Name <onboarding@resend.dev>"
RESEND_FROM=
# Recipient address for notifications
EMAIL_TO=your_name@gmail.com
# ── Admin API guard ──────────────────────────────────────────────────
# Used to protect the admin GET /api/contact endpoint
# Generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
JWT_SECRET=replace-this-with-a-cryptographically-random-string
# ── CORS / Client URL ───────────────────────────────────────────────
CLIENT_URL=http://localhost:3000
ALLOWED_ORIGIN=*🟢 Render — Current (Recommended)
-
Push this repo to GitHub.
-
Create a Web Service on render.com → connect the repo.
Setting Value
| Build Command | npm install --prefix backend && npm install |
| Start Command | npm run start:backend |
| Node Version | 18 |
- Set environment variables in the Render dashboard:
MONGO_URI,RESEND_API_KEY,RESEND_FROM,EMAIL_TO,JWT_SECRET,CLIENT_URL,NODE_ENV. - Deploy. The app serves the frontend statically and runs the Express API from
backend/server.js.
🟣 Railway
npm install -g @railway/cli
railway login && railway init
# Set the required environment variables on Railway (or via the UI):
railway variables set MONGO_URI=<url> RESEND_API_KEY=<key> EMAIL_TO=<email> JWT_SECRET=<secret> NODE_ENV=production
railway up⚫ VPS (Ubuntu + Nginx + PM2)
# Install Node 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Provision a MongoDB instance (Atlas, DigitalOcean Managed DB, or self-hosted) and copy the connection URI into `MONGO_URI` in your `.env`.
# Deploy
git clone https://github.com/MsParadox/Mohit_Portfolio.git /var/www/portfolio
cd /var/www/portfolio && npm install --omit=dev
cd backend && npm install --omit=dev
cp .env.example .env && nano .env
# Process manager
npm install -g pm2
pm2 start backend/server.js --name portfolio
pm2 save && pm2 startup
# Reverse proxy + SSL
sudo apt-get install -y nginx certbot python3-certbot-nginx
# Configure Nginx → proxy_pass http://localhost:5000
sudo certbot --nginx -d yourdomain.comnpm run dev # Run backend in development (nodemon)
cd backend && npm start # Start production backend╔══════════════════════════════════════════════════════╗
║ ⚡MOHIT SHARMA⚡ ║
║ B.Tech CSE · 2023–2027 ║
╚══════════════════════════════════════════════════════╝
MIT License — Copyright © 2026 Mohit Sharma
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software to use, copy, modify, merge, publish, and distribute it,
subject to the condition that the above copyright notice appears in all copies.





