| title | Custom Admin Panel Location |
|---|---|
| label | Custom Admin Panel Location |
| order | 35 |
| desc | Learn how to move and customize the location of your Payload Admin Panel, including nested routes and custom folder structures. |
| keywords | admin, customization, routes, folder structure, import map, configuration |
Payload is flexible about where your Admin Panel lives within your Next.js application. You can customize routes, move folders, and organize your project structure to match your application's needs.
- Custom admin routes - Change
/adminto/dashboard,/cms, etc. - Nested admin panels - Place Payload at
/admin/contentalongside custom admin routes - Multiple admin interfaces - Organize Payload and custom dashboards together
- Organizational preferences - Match your team's folder structure conventions
By default, Payload creates this structure in your Next.js app:
app/ (or src/app/)
├── (payload)/
│ ├── admin/
│ │ ├── [[...segments]]/
│ │ │ ├── not-found.tsx
│ │ │ └── page.tsx
│ │ └── importMap.js
│ ├── api/
│ │ └── [...slug]/
│ │ └── route.ts
│ ├── custom.scss
│ └── layout.tsx
(payload)/- Parent folder containing all Payload-related routesadmin/- Admin Panel UI routesapi/- REST API routeslayout.tsx- Root layout that imports the import mapimportMap.js- Auto-generated file mapping component paths (regenerated on startup)
To change the admin route from /admin to /dashboard:
1. Update your Payload Config:
import { buildConfig } from 'payload'
export default buildConfig({
// ...
routes: {
admin: '/dashboard', // Changed from '/admin'
},
})2. Move the folder:
# Move the admin folder
mv app/(payload)/admin app/(payload)/dashboard3. Update the import path in layout.tsx:
Edit app/(payload)/layout.tsx and update the import map reference to match the new folder name:
// Before
import { importMap } from './admin/importMap.js'
// After
import { importMap } from './dashboard/importMap.js'4. Restart your dev server
Payload will now be available at /dashboard.
To move both the Payload Admin Panel and API under a custom path, you move the entire (payload) folder. This example places everything under /admin/content.
1. Update your Payload Config with all routes and import map settings:
import { buildConfig } from 'payload'
import path from 'path'
import { fileURLToPath } from 'url'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
export default buildConfig({
// ...
routes: {
admin: '/admin/content/admin',
api: '/admin/content/api',
graphQL: '/admin/content/api/graphql',
graphQLPlayground: '/admin/content/api/graphql-playground',
},
admin: {
importMap: {
baseDir: path.resolve(dirname, './src/app/admin/content/(payload)'),
importMapFile: path.resolve(
dirname,
'./src/app/admin/content/(payload)/admin/importMap.js',
),
},
},
})2. Move the (payload) folder:
# Create the new directory structure
mkdir -p app/admin/content
# Move the entire (payload) folder
mv app/(payload) app/admin/content/(payload)3. Update the import path in layout.tsx:
Edit app/admin/content/(payload)/layout.tsx:
// Change this import path to match your new structure
import { importMap } from './admin/importMap.js'The import path should be relative from layout.tsx to importMap.js. In this case, it remains './admin/importMap.js'.
4. Regenerate the import map:
pnpm payload generate:importmapYour Payload admin is now at /admin/content/admin and the API at /admin/content/api.
If you want both Payload and custom admin routes under /admin:
Folder Structure:
app/
├── admin/
│ ├── content/ # Payload admin
│ │ └── (payload)/
│ │ ├── admin/
│ │ ├── api/
│ │ └── layout.tsx
│ ├── platform/ # Your custom admin
│ │ ├── dashboard/
│ │ │ └── page.tsx
│ │ └── layout.tsx
│ └── page.tsx # Choose between admins
Configuration:
export default buildConfig({
routes: {
admin: '/admin/content',
api: '/admin/content/api',
graphQL: '/admin/content/api/graphql',
graphQLPlayground: '/admin/content/api/graphql-playground',
},
admin: {
importMap: {
baseDir: path.resolve(dirname, './src/app/admin/content/(payload)'),
importMapFile: path.resolve(
dirname,
'./src/app/admin/content/(payload)/admin/importMap.js',
),
},
},
})Not all files in the (payload) folder are auto-generated. Here's what you need to know:
| File | Auto-Generated? | Safe to Edit? | When Regenerated? | Notes |
|---|---|---|---|---|
layout.tsx |
No | Yes | Never | Created once during setup. Safe to modify import paths. |
admin/importMap.js |
Yes | No | Startup, HMR, manual command | Always regenerated. Configure via admin.importMap instead. |
admin/[[...segments]]/page.tsx |
No | Rarely needed | Never | Part of template. Usually no need to edit. |
admin/[[...segments]]/not-found.tsx |
No | Rarely needed | Never | Part of template. Usually no need to edit. |
api/[...slug]/route.ts |
No | Rarely needed | Never | Part of template. Usually no need to edit. |
custom.scss |
No | Yes | Never | Intended for your custom styles. |
You may see this warning in layout.tsx:
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */This warning is misleading. The file was generated during initial project setup by create-payload-app, but it is never regenerated by Payload. It is completely safe to modify this file, especially when customizing your folder structure.
When you move the Payload folder, you'll need to update the import path in layout.tsx:
// app/admin/content/(payload)/layout.tsx
import { importMap } from './admin/importMap.js' // Update this path as neededWhat you can safely edit:
- Import map path (required when moving folders)
- Custom imports for additional functionality
- Custom SCSS imports
- Server function logic (advanced use cases)
What you should NOT edit:
- The core
RootLayoutusage (required for Payload) - The
serverFunctionpattern (required for Payload to work) - The import map prop to
RootLayout
The importMap.js file is automatically regenerated in these scenarios:
- Application startup - Every time you start your dev server or production build
- Hot Module Replacement (HMR) - When you save changes to component files in development
- Manual generation - When you run
pnpm payload generate:importmap
The import map is never regenerated during:
- Normal runtime (only at startup)
- After the production build completes
If you see an error about the import map not being found:
- Verify
admin.importMap.importMapFilepoints to the correct location - Run
pnpm payload generate:importmapmanually - Check that the path is absolute, not relative
If you see an import error in layout.tsx:
- Verify the import path is relative from
layout.tsxtoimportMap.js - Use
./admin/importMap.jsif importMap is in a siblingadminfolder - Use
./importMap.jsif you moved importMap to the same folder as layout
If the admin panel returns 404:
- Verify
routes.adminmatches your actual folder structure - Ensure you moved the entire
(payload)folder, not justadmin - Check that Next.js is recognizing your new routes
If custom components aren't loading:
- Verify
admin.importMap.baseDiris correct - Regenerate the import map:
pnpm payload generate:importmap - Check component paths in your config are relative to
baseDir