Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 

Repository files navigation

📬 Portfolio Backend

REST API backend for Rishabh Paudel's Portfolio — handles contact form submissions, stores them to MongoDB, and sends email notifications.


🚀 Tech Stack

  • Runtime — Node.js
  • Framework — Express.js
  • Database — MongoDB Atlas (Mongoose)
  • Email — Resend
  • Security — Helmet.js, express-rate-limit, express-validator
  • Deployment — Render

📁 Project Structure

portfolio-backend/
├── src/
│   ├── routes/
│   │   └── contact.js        # POST /api/contact
│   ├── models/
│   │   └── Contact.js        # Mongoose schema
│   └── middleware/
│       ├── validate.js        # Input validation rules
│       └── rateLimiter.js     # IP + email rate limiting
├── .env                       # Environment variables (not committed)
├── .gitignore
├── server.js                  # Entry point
└── package.json

⚙️ API Endpoints

POST /api/contact

Accepts a contact form submission, saves to MongoDB, and sends an email notification.

Request Body

{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john@example.com",
  "organization": "Acme Inc",
  "message": "Hey, I'd love to connect!"
}

Success Response 201

{
  "success": true,
  "message": "Message received! I will get back to you soon."
}

Validation Error Response 400

{
  "success": false,
  "errors": [
    { "field": "email", "message": "Invalid email address" }
  ]
}

Rate Limited Response 429

{
  "success": false,
  "message": "Too many messages sent from your IP. Please try again after an hour."
}

GET /health

Health check endpoint — used by Render to keep the service alive.

Response 200

{
  "status": "ok"
}

🔒 Security

  • Helmet.js — sets 14 secure HTTP response headers
  • IP Rate Limiting — max 5 submissions per IP per hour
  • Email Rate Limiting — max 3 submissions per email per 24 hours
  • Input Validation — all fields validated and sanitized before touching the database
  • CORS — restricted to the portfolio frontend URL only

🛠️ Local Development

Prerequisites

  • Node.js v18+
  • MongoDB Atlas account
  • Resend account
  • Gmail account with App Password

Setup

1. Clone the repo

git clone https://github.com/yourusername/portfolio-backend.git
cd portfolio-backend

2. Install dependencies

npm install

3. Create .env file

PORT=5000
MONGO_URI=mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/portfolio?retryWrites=true&w=majority&appName=Cluster0
EMAIL_USER=yourgmail@gmail.com
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxx
FRONTEND_URL=http://localhost:5500

4. Run the server

node server.js

Server runs on http://localhost:5000

Test the endpoint

Invoke-RestMethod -Uri http://localhost:5000/api/contact -Method POST -ContentType "application/json" -Body '{"firstName":"Test","lastName":"User","email":"test@example.com","organization":"Test","message":"This is a test message"}'

☁️ Deployment (Render)

  1. Push repo to GitHub
  2. Go to render.comNew Web Service → connect repo
  3. Set:
    • Runtime: Node
    • Build Command: npm install
    • Start Command: node server.js
    • Root Directory: backend (if repo has a subfolder)
  4. Add environment variables:
    • MONGO_URI
    • EMAIL_USER
    • RESEND_API_KEY
    • FRONTEND_URL (your Netlify URL, no trailing slash)
  5. Deploy 🎉

📦 Dependencies

Package Purpose
express Web framework
mongoose MongoDB ODM
resend Email delivery
cors Cross-origin requests
helmet Security headers
express-rate-limit Rate limiting
express-validator Input validation
dotenv Environment variables

📄 License

MIT — feel free to use this as a reference for your own portfolio backend.


Part of rishabh-2d-portfolio.netlify.app

About

Backend of my 2-d portfolio lives here

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages