- Re-route Payload CMS: Reclaim /admin in Next.js Quick Guide
Re-route Payload CMS: Reclaim /admin in Next.js Quick Guide
Move Payload 3.0 to /payload-admin with payload.config.ts and Next.js App Router route groups for a clean custom admin…

Moving to Next.js and Payload CMS? I offer advisory support on an hourly basis.
Book Hourly AdvisoryMoving from the default Payload CMS setup to a custom multi-tenant application in Next.js isn't straightforward when you want to control the UX of your primary administration dashboard. I recently had to build a platform where the /admin route needed to be a tailored experience for business users, while the raw Payload database management interface needed to remain accessible for technical super-admins. This guide shows you exactly how to move the Payload engine to a dedicated sub-path so you can reclaim the default route for your own application logic.
The first step in decoupling the CMS from your application's primary route is telling the Payload engine exactly where it should expect to live. By default, Payload assumes it owns the /admin path. We override this behavior within the core configuration file by defining a custom route object. This change informs Payload's internal linking and redirection logic that it is no longer the primary occupant of the standard administration path.
// File: payload.config.ts
import { buildConfig } from "payload";
const config = buildConfig({
// ... other configuration
routes: {
admin: "/payload-admin",
},
// ... rest of config
});
export default config;
In this snippet, we explicitly set the admin key within the routes object to /payload-admin. This is a low-level change that updates how Payload generates its internal URLs. It ensures that when you click "View Site" or navigate between collections within the CMS interface, the engine correctly prepends your new path instead of the default. This is the foundation that allows the Next.js App Router to eventually pick up the request at the correct location.
With the configuration updated, we must now align our physical file structure with the new route. Payload 3.0 is built deeply into the Next.js App Router, which means the admin dashboard is simply a set of dynamic routes within your src/app directory. To keep the project organized and prevent our custom application routes from tangling with the CMS engine, we use a Next.js Route Group.
// File: src/app/(payload)/payload-admin/[[...segments]]/page.tsx
import type { Metadata } from "next";
import config from "@payload-config";
import { RootPage, generatePageMetadata } from "@payloadcms/next/views";
import { importMap } from "../importMap.js";
type Args = {
params: Promise<{
segments: string[];
}>;
searchParams: Promise<{
[key: string]: string | string[];
}>;
};
export const generateMetadata = ({
params,
searchParams,
}: Args): Promise<Metadata> =>
generatePageMetadata({ config, params, searchParams });
const Page = ({ params, searchParams }: Args) =>
RootPage({ config, params, searchParams, importMap });
export default Page;
This implementation uses the catch-all segment [[...segments]] to ensure that every sub-path under /payload-admin—such as /payload-admin/collections/users—is handled by the Payload RootPage component. By wrapping this folder in a (payload) route group, we essentially tell Next.js to ignore the parent folder name in the URL, allowing the nested payload-admin folder to map directly to the path we defined in our configuration. This separation is critical for maintaining a clean codebase as the project grows.
Now that the CMS has been safely tucked away behind /payload-admin, the standard /admin route is completely vacant. This is where we implement our custom, user-facing dashboard. Unlike the Payload interface, this dashboard is built using your own design system—in my case, a combination of shadcn/ui and custom React components—providing a streamlined experience for non-technical users who shouldn't be exposed to the complexities of a raw database interface.
// File: src/app/admin/page.tsx
import { DashboardHeader } from "@/components/layout/header";
import { StatsCards } from "@/components/dashboard/stats";
export default function AdminDashboard() {
return (
<div className="flex flex-col gap-6 p-8">
<DashboardHeader title="Business Overview" />
<StatsCards />
{/* Custom application logic goes here */}
</div>
);
}
Because we successfully re-routed the CMS engine earlier, this file can exist without any naming collisions or routing conflicts. The App Router sees a standard request for /admin and renders this custom page, while requests for /payload-admin are funneled into the Payload engine logic we set up in the previous step. This architecture allows you to maintain the rapid development benefits of Payload for data management while delivering a fully branded and simplified interface to your end users.
In this guide, we successfully solved the conflict between a CMS-driven administration interface and a custom application dashboard. By reconfiguring the Payload route engine and utilizing Next.js Route Groups, we moved the technical dashboard to a dedicated sub-path. This reclaimed the default administration route for our own custom logic, providing a clear separation between super-admin tools and user-facing features.
You can now build out complex workflows for your customers in the standard admin path while retaining a powerful, raw interface for your own development tasks. Let me know in the comments if you have questions, and subscribe for more practical development guides.
Thanks, Matija
Detailed Payload guides with field configuration examples, custom components, and workflow optimization tips to speed up your CMS development process.