134 lines
5 KiB
Markdown
134 lines
5 KiB
Markdown
---
|
|
title: "Payload CMS — Custom Admin Panel Location"
|
|
aliases: [payload-admin-route, payload-custom-route, payload-admin-location]
|
|
tags: [payload-cms, nextjs, admin-panel, routing, configuration]
|
|
sources: [raw/admin__admin-panel-location.md]
|
|
created: 2026-05-15
|
|
updated: 2026-05-15
|
|
---
|
|
|
|
# Payload CMS — Custom Admin Panel Location
|
|
|
|
Payload is flexible about where the Admin Panel lives in a Next.js App Router project. You can rename the route, nest it deeper, or co-locate it with custom admin dashboards.
|
|
|
|
## Default Folder Structure
|
|
|
|
```
|
|
app/ (or src/app/)
|
|
└── (payload)/
|
|
├── admin/
|
|
│ ├── [[...segments]]/
|
|
│ │ ├── not-found.tsx
|
|
│ │ └── page.tsx
|
|
│ └── importMap.js ← auto-generated, never edit manually
|
|
├── api/
|
|
│ └── [...slug]/route.ts
|
|
├── custom.scss
|
|
└── layout.tsx ← safe to edit despite the "DO NOT MODIFY" warning
|
|
```
|
|
|
|
## Scenario 1 — Rename the Route (`/admin` → `/dashboard`)
|
|
|
|
1. **Config:**
|
|
```ts
|
|
buildConfig({ routes: { admin: '/dashboard' } })
|
|
```
|
|
2. **Move folder:** `mv app/(payload)/admin app/(payload)/dashboard`
|
|
3. **Update `layout.tsx` import:**
|
|
```ts
|
|
import { importMap } from './dashboard/importMap.js'
|
|
```
|
|
4. Restart dev server.
|
|
|
|
## Scenario 2 — Move the Entire `(payload)` Folder
|
|
|
|
Moves both Admin UI and REST API under a custom prefix (e.g. `/admin/content`).
|
|
|
|
> **Gotcha:** `(payload)/admin/` is a Next.js route segment, so placing `(payload)` at `app/admin/content/(payload)` gives you `/admin/content/admin`, not `/admin/content`.
|
|
|
|
**Config:**
|
|
```ts
|
|
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',
|
|
),
|
|
},
|
|
},
|
|
})
|
|
```
|
|
|
|
**Steps:**
|
|
1. `mkdir -p app/admin/content && mv app/(payload) app/admin/content/(payload)`
|
|
2. Verify `layout.tsx` import path (usually stays `'./admin/importMap.js'`)
|
|
3. `pnpm payload generate:importmap`
|
|
|
|
## Scenario 3 — Multiple Admin Dashboards
|
|
|
|
```
|
|
app/admin/
|
|
├── content/(payload)/ ← Payload CMS
|
|
├── platform/ ← custom admin
|
|
└── page.tsx ← landing page choosing between admins
|
|
```
|
|
|
|
Same config as Scenario 2; just add your custom routes alongside `(payload)`.
|
|
|
|
## Auto-Generated vs Safe-to-Edit Files
|
|
|
|
| File | Auto-Generated? | Safe to Edit? |
|
|
|------|----------------|--------------|
|
|
| `layout.tsx` | No (created once by create-payload-app) | **Yes** — update import paths here |
|
|
| `admin/importMap.js` | **Yes** (startup, HMR, manual cmd) | **No** — configure via `admin.importMap` |
|
|
| `admin/[[...segments]]/page.tsx` | No | Rarely needed |
|
|
| `api/[...slug]/route.ts` | No | Rarely needed |
|
|
| `custom.scss` | No | Yes |
|
|
|
|
> **Note:** The "DO NOT MODIFY" comment in `layout.tsx` is misleading — it was generated once during `create-payload-app` and Payload **never** overwrites it. Safe to edit import paths.
|
|
|
|
## `importMap.js` Regeneration Triggers
|
|
|
|
- App startup (dev or prod build)
|
|
- HMR (when component files change)
|
|
- `pnpm payload generate:importmap` (manual)
|
|
|
|
Never edit `importMap.js` directly — configure paths via `admin.importMap.baseDir` / `importMapFile`.
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Fix |
|
|
|---------|-----|
|
|
| Import map not found | Check `admin.importMap.importMapFile` is absolute; run `pnpm payload generate:importmap` |
|
|
| `layout.tsx` import error | Path must be relative from `layout.tsx` → `importMap.js`; verify after folder move |
|
|
| Admin panel 404 | Verify `routes.admin` matches actual folder structure; ensure entire `(payload)` was moved |
|
|
| Custom components not loading | Check `admin.importMap.baseDir`; regenerate import map |
|
|
|
|
## Key Takeaways
|
|
|
|
- `routes.admin` in Payload config **must match** the actual Next.js folder path.
|
|
- When you rename/move `admin/`, update the `import { importMap }` line in `layout.tsx`.
|
|
- Moving `(payload)` deeper adds its subfolder names to the URL — plan the nesting accordingly.
|
|
- `importMap.js` is always auto-generated; configure its location via `admin.importMap`, never edit the file.
|
|
- `layout.tsx` is **safe to edit** despite the generated-file warning.
|
|
- After any folder move, run `pnpm payload generate:importmap` to be safe.
|
|
|
|
## Related Articles
|
|
|
|
- [[wiki/tech-patterns/payload-cms-installation|Payload CMS — Installation & Setup]]
|
|
- [[wiki/tech-patterns/payload-cms-access-control-overview|Payload CMS — Access Control Overview]]
|
|
- [[wiki/tech-patterns/payload-cms-admin-accessibility|Payload CMS — Admin Panel Accessibility]]
|
|
- [[wiki/tech-patterns/nextjs-fastapi-fullstack|Next.js + FastAPI Fullstack Pattern]]
|
|
|
|
## Sources
|
|
|
|
- `raw/admin__admin-panel-location.md`
|
|
- https://payloadcms.com/docs/admin/admin-panel-location
|