Nowadays, maintaining dynamic website content across multiple pages usually requires coordination between content editors and administrators. Rather than making constant requests via chat or email, I wanted to build a structured system that lets editors submit content change requests and lets admins manage and approve those changes.
So I built a Content Request Dashboard with the following features:
Let me walk you through the process.
Before writing any code, I settled on these technologies:
Rather than using Prisma or another ORM, I chose raw MySQL queries with mysql2/promise—cleaner and easier for a small schema.
This app only needs two tables:
CREATE TABLE users (
id VARCHAR(64) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
role ENUM('ADMIN', 'EDITOR') NOT NULL DEFAULT 'EDITOR',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);CREATE TABLE requests (
id VARCHAR(24) PRIMARY KEY,
form_key VARCHAR(64) NOT NULL,
section_key VARCHAR(64) NOT NULL,
title VARCHAR(255) NOT NULL,
fields JSON NOT NULL,
payload JSON NOT NULL,
status ENUM('REQUESTED', 'IN_PROGRESS', 'DONE') NOT NULL DEFAULT 'REQUESTED',
requester_email VARCHAR(100) NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);The Dashboard UI has two main areas:

Each page (e.g. "About") is broken into sections, and editors can submit updates per section. If they don't fill a section, no request is created for it.


One UX gem of this project is the unsaved change detector. If the user tries to switch sections without saving, a modal (or simple confirm) appears:
"You have unsaved changes. Are you sure you want to leave?"
This is implemented with a simple React Context:
const { isDirty, setDirty } = useUnsavedChanges();All form changes trigger setDirty(true).

Admins have access to a dedicated panel under /dashboard/admin, which allows them to:
These features make it easy for admins to prioritize updates, collaborate with editors, and track progress.
I'm building even more tools to help admins manage the system efficiently:
View and manage all registered users (add, delete, or update roles such as EDITOR or ADMIN).
Delete DONE requests within a selected date range (e.g., older than X days). Helps keep the system tidy.
This project has evolved into a practical and scalable content request tool, built with clarity and collaboration in mind. It empowers editors with a simple form-based UI to request website updates and gives admins a centralized dashboard to track and manage those requests.
From handling user authentication with role-based access, to translating dynamic form submissions into structured database entries, this project demonstrates a real-world full-stack workflow using Next.js, MySQL, and NextAuth.
While the core functionality is in place, there's still more to come:
Whether you're looking to build a project like this for a client or learning how to structure scalable dashboards with serverless APIs, I hope this walkthrough inspires your next build.
Categories: