REST API backend for Rishabh Paudel's Portfolio — handles contact form submissions, stores them to MongoDB, and sends email notifications.
- Runtime — Node.js
- Framework — Express.js
- Database — MongoDB Atlas (Mongoose)
- Email — Resend
- Security — Helmet.js, express-rate-limit, express-validator
- Deployment — Render
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
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."
}Health check endpoint — used by Render to keep the service alive.
Response 200
{
"status": "ok"
}- 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
- Node.js v18+
- MongoDB Atlas account
- Resend account
- Gmail account with App Password
1. Clone the repo
git clone https://github.com/yourusername/portfolio-backend.git
cd portfolio-backend2. Install dependencies
npm install3. 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:55004. Run the server
node server.jsServer runs on http://localhost:5000
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"}'- Push repo to GitHub
- Go to render.com → New Web Service → connect repo
- Set:
- Runtime: Node
- Build Command:
npm install - Start Command:
node server.js - Root Directory:
backend(if repo has a subfolder)
- Add environment variables:
MONGO_URIEMAIL_USERRESEND_API_KEYFRONTEND_URL(your Netlify URL, no trailing slash)
- Deploy 🎉
| 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 |
MIT — feel free to use this as a reference for your own portfolio backend.
Part of rishabh-2d-portfolio.netlify.app