10 KiB
| title | label | order | desc | keywords | source |
|---|---|---|---|---|---|
| Custom Admin Panel Location | Custom Admin Panel Location | 35 | Learn how to move and customize the location of your Payload Admin Panel, including nested routes and custom folder structures. | admin, customization, routes, folder structure, import map, configuration | https://payloadcms.com/docs/admin/admin-panel-location |
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.
Common Use Cases
- 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
Understanding the Payload Folder Structure
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)
Scenario 1: Simple Route Change
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)/dashboard
3. 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'
Your IDE may auto-update this import when you move the folder, but it may not.
To catch any stale references to the old path, run a build or type-check
(`pnpm build` or `pnpm tsc --noEmit`) and fix any import errors until it
passes.
4. Restart your dev server
Payload will now be available at /dashboard.
Scenario 2: Moving the Entire Payload Folder (Admin Panel and API)
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:importmap
Your Payload admin is now at /admin/content/admin and the API at /admin/content/api.
Scenario 3: Multiple Admin Dashboards
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',
),
},
},
})
Understanding Auto-Generated Files
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. |
About the "DO NOT MODIFY" Warning
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.
Editing layout.tsx Safely
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 needed
What 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
Import Map Regeneration
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
Troubleshooting
Import map not found error
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
Layout.tsx import error
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
Admin panel 404 error
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
Components not loading
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