As a developer, building a portfolio isn’t just about showcasing projects — it’s about demonstrating how you can create flexible, maintainable web applications. For my portfolio website, I wanted more than a static showcase. I needed a dynamic Admin Panel that would allow me to easily manage my projects, skills, profile details, and resume — all without touching the code every time.
In this post, I’ll walk you through how I built a dynamic admin dashboard using the MERN stack (MongoDB, Express, React, Node.js) that powers my portfolio backend and frontend. This admin panel makes managing my portfolio content a breeze, and I’ll share the key architecture decisions, tools, and lessons learned.
Why Build an Admin Panel for Your Portfolio?
...As a developer, building a portfolio isn’t just about showcasing projects — it’s about demonstrating how you can create flexible, maintainable web applications. For my portfolio website, I wanted more than a static showcase. I needed a dynamic Admin Panel that would allow me to easily manage my projects, skills, profile details, and resume — all without touching the code every time.
In this post, I’ll walk you through how I built a dynamic admin dashboard using the MERN stack (MongoDB, Express, React, Node.js) that powers my portfolio backend and frontend. This admin panel makes managing my portfolio content a breeze, and I’ll share the key architecture decisions, tools, and lessons learned.
Why Build an Admin Panel for Your Portfolio?
At first, I just had a simple React portfolio displaying static content. But soon, every update required code changes and redeployments, which was time-consuming and error-prone.
By building an admin dashboard, I achieved:
- Real-time content updates: Add, update, or delete projects, skills, and other profile data via a UI.
- Secure access: Only I can log in to manage content with JWT authentication.
- Scalability: Easily extend with new sections or data types without modifying the frontend.
- Better organization: Store portfolio content in a database instead of hardcoded files.
Tech Stack Overview
Here’s the stack I used to build the admin panel and the portfolio backend:
- Frontend: React with functional components and hooks for building the admin UI.
- Backend: Node.js + Express REST APIs for handling CRUD operations.
- Database: MongoDB with Mongoose for schema modeling and data storage.
- Authentication: JWT (JSON Web Tokens) to secure admin routes.
- File Storage: Cloudinary for managing image uploads (profile pics, project images).
- Styling: CSS modules and some UI libraries for clean layouts.
Key Features of the Admin Panel
The dashboard lets me manage:
- Profile Section: Update bio, profile picture, contact info.
- Skills: Add, update, or remove programming skills dynamically.
- Projects: CRUD operations for projects including title, description, images, links.
- Resume: Upload and update resume files.
- Authentication: Secure login with email and password, protected routes using JWT.
How It Works — Architecture Breakdown
- Backend API Design
I created RESTful APIs to handle CRUD actions for all portfolio data.
Example routes:
-
GET /api/projects— fetch all projects -
POST /api/projects— add a new project -
PUT /api/projects/:id— update project by ID -
DELETE /api/projects/:id— delete project by ID
The APIs validate requests and interact with MongoDB collections using Mongoose models. I also implemented authentication middleware to protect sensitive endpoints.
- Authentication with JWT
To secure the admin panel, I built a login system with:
- Password hashing using bcrypt.
- JWT token generation on login.
- Protected routes in both frontend and backend that require a valid token.
- React Admin Dashboard UI
Using React hooks and axios for API calls, I built components for:
- Login Page: Authenticate and store JWT in localStorage.
- Dashboard: Overview of portfolio content.
- Forms: Controlled forms for adding/editing skills and projects.
- File Uploads: Integrated Cloudinary API for image and resume uploads.
I also used conditional rendering and loading states for smooth UX.
Code Snippet — Example: Fetching Projects in Admin Panel
import React, { useEffect, useState } from "react";
import axios from "axios";
const AdminProjects = () => {
const [projects, setProjects] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchProjects = async () => {
try {
const token = localStorage.getItem(“authToken”);
const response = await axios.get(“/api/projects”, {
headers: { Authorization: Bearer </span><span class="p">${</span><span class="nx">token</span><span class="p">}</span><span class="s2"> },
});
setProjects(response.data);
} catch (error) {
console.error(“Error fetching projects:”, error);
} finally {
setLoading(false);
}
};
fetchProjects();
}, []);
if (loading) return <p>Loading projects…</p>;
return (
<div>
<h2>Manage Projects</h2>
{projects.length === 0 ? (
<p>No projects found.</p>
) : (
projects.map((project) => (
<div key={project._id}>
<h3>{project.title}</h3>
<p>{project.description}</p>
{/* Buttons for Edit/Delete can go here */}
</div>
))
)}
</div>
);
};
export default AdminProjects;
Challenges & Lessons Learned
Handling File Uploads: Uploading images and resumes required integrating Cloudinary's API with signed URLs and managing upload states.
State Management: Keeping the admin UI in sync with backend data, especially with real-time CRUD updates, needed careful use of React state and effects.
Authentication Flow: Securing routes and managing JWT tokens was critical to avoid unauthorized access.
UX Considerations: Designing simple but effective forms and feedback messages improved admin usability.
Final Thoughts
Building a dynamic admin panel transformed my portfolio from a static webpage into a powerful content management system I can control without redeploying. It gave me hands-on experience with full-stack development, API design, secure authentication, and file management — all essential skills for a modern web developer.
If you’re planning to build or improve your portfolio, I highly recommend adding an admin dashboard. It not only shows your technical skills but also saves you a ton of time and effort in the long run.
If you want to check out my portfolio in action, feel free to visit:
https://adithyan-phi.vercel.app
Got questions or want to share your experience? Drop a comment below!
Happy coding!