Welcome to the Anb Portfolio codebase. This repository contains the complete systems architecture for a dynamic developer portfolio website, featuring a Node.js API gateway, a client-facing landing page, and a secure content management system (CMS) dashboard.
The application is structured as a decoupled three-tier system:
graph TD
subgraph Clients ["Client Applications"]
FE["Frontend Portfolio Client<br>(React 19 / Redux Toolkit / Tailwind v4)"]
ADM["Admin CMS Portal<br>(React 19 / Redux MFA / Tailwind v4)"]
end
subgraph Server ["Backend Services"]
API["Express.js Server (Node.js)"]
SMTP["Nodemailer SMTP Transporter"]
CLD["Cloudinary Media API"]
end
subgraph Database ["Persistence Layer"]
DB[(MongoDB Database)]
end
FE -->|Public REST API Request| API
ADM -->|Authenticated REST API Request| API
API -->|Read / Write| DB
API -->|Send Authentication & Reset OTPs| SMTP
API -->|Upload Media Files| CLD
SMTP -.->|Mails| ADM
- Backend API Server: Serves REST endpoints for portfolio configuration, content updates, messaging pipelines, media library management, and two-step MFA admin login.
- Frontend Portfolio Client: A highly interactive, performant web application featuring animations (Framer Motion) and fallback databases (
src/DB) to support visual continuity when disconnected from the API. - Admin CMS Dashboard: A secure CMS enabling full CRUD operations for projects, skills, certificates, resumes, testimonials, and inbox logs.
The repository has the following directory structure:
Portfolio/
├── admin/ # Admin CMS dashboard portal client
├── assets/ # Design assets and mockups/screenshots
├── backend/ # Node.js + Express API server
└── frontend/ # Public-facing portfolio client website
For detailed documentation on each component, refer to the module-specific documentation:
- Backend Architecture & Database Setup Guide
- Frontend Architecture & Dynamic Rendering Guide
- Admin CMS Architecture & Security Guide
Make sure you have the following installed on your machine:
- Node.js: v18.x or above (Recommended v20+)
- MongoDB: Local installation or MongoDB Atlas cluster instance.
- Cloudinary Account: For managing image uploads.
- Gmail App Password: For sending authentication and password reset OTPs.
Configure .env files in each sub-directory before starting the services. Template references:
-
Backend Environment (
backend/.env):PORT=5000 MONGO_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/portfolio JWT_SECRET=your_jwt_access_secret_key JWT_REFRESH_SECRET=your_jwt_refresh_secret_key CLIENT_URL=http://localhost:5173 ADMIN_URL=http://localhost:5174 NODE_ENV=development # SMTP Nodemailer Settings SMTP_HOST=smtp.gmail.com SMTP_PORT=465 SMTP_SERVICE=gmail SMTP_MAIL=your_email@gmail.com SMTP_PASSWORD=your_gmail_app_password # SuperAdmin Auto-seed Credentials SUPERADMIN_EMAIL=your_email@gmail.com SUPERADMIN_PASSWORD=your_secure_password # Cloudinary Upload Credentials CLOUDINARY_CLOUD_NAME=your_cloudinary_cloud_name CLOUDINARY_API_KEY=your_cloudinary_api_key CLOUDINARY_API_SECRET=your_cloudinary_api_secret
-
Frontend Web App Environment (
frontend/.env):VITE_API_URL=http://localhost:5000/api
-
Admin CMS Environment (
admin/.env):VITE_API_URL=http://localhost:5000/api
To launch and test the portfolio system locally:
Navigate to the backend workspace and start the API:
cd backend
npm install
npm run devOn boot, the backend automatically connects to MongoDB, seeds the SuperAdmin user (if not already seeded), and listens on port 5000.
Navigate to the frontend workspace and start the React dev server:
cd frontend
npm install
npm run devThe client website starts running on port 5173.
Navigate to the admin workspace and start the CMS dev server:
cd admin
npm install
npm run devThe admin portal runs on port 5174.
Accessing the admin portal requires passing a secure MFA flow:
- Initial Authentication: Submit the SuperAdmin email and password.
- OTP Verification: The server generates a cryptographically random, 6-digit OTP code, saves it to the database with a 10-minute expiry window, and emails it using Nodemailer.
- Authentication Handshake: Submitting the correct OTP finishes the handshake, storing a HTTP-Only secure cookie (
refreshToken) and sending anaccessTokenin the JSON response body.