How I Built a Dynamic Admin Panel for My MERN Stack Portfolio

Published: (December 27, 2025 at 03:56 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

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 hard‑coded files.

Tech Stack Overview

LayerTechnology
FrontendReact (functional components & hooks)
BackendNode.js + Express (REST APIs)
DatabaseMongoDB + Mongoose
AuthJWT (JSON Web Tokens)
File StorageCloudinary (image & resume uploads)
StylingCSS Modules + UI libraries

Key Features of the Admin Panel

  • Profile Section: Update bio, profile picture, contact info.
  • Skills: Add, update, or remove programming skills dynamically.
  • Projects: CRUD operations for projects (title, description, images, links).
  • Resume: Upload and update resume files.
  • Authentication: Secure login with email & password, protected routes using JWT.

How It Works — Architecture Breakdown

1. 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. Authentication middleware protects sensitive endpoints.

2. 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.

3. 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.

Conditional rendering and loading states provide a 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 ${token}` },
        });
        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: Integrating Cloudinary’s signed URLs and managing upload states required extra care.
  • State Management: Keeping the admin UI in sync with backend data, especially after real‑time CRUD updates, demanded thoughtful use of React state and effects.
  • Authentication Flow: Securing routes and managing JWT tokens was critical to avoid unauthorized access.
  • UX Considerations: Simple, effective forms and clear feedback messages greatly 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 showcases your technical abilities but also saves you a ton of time and effort in the long run.

Check out my portfolio in action:
[http://your-portfolio-link.com] (replace with your actual URL)


https://adithyan-phi.vercel.app

Got questions or want to share your experience? Drop a comment below!


Happy coding!

Back to Blog

Related posts

Read more »