118 lines
4 KiB
Markdown
118 lines
4 KiB
Markdown
---
|
|
title: "Nested Docs Plugin"
|
|
aliases: [nested-docs, plugin-nested-docs, parent-child-pages]
|
|
tags: [payloadcms, plugin, hierarchy, breadcrumbs, pages]
|
|
sources: [raw/plugins__nested-docs.md]
|
|
created: 2026-05-15
|
|
updated: 2026-05-15
|
|
---
|
|
|
|
## Overview
|
|
|
|
`@payloadcms/plugin-nested-docs` adds parent/child hierarchy to any collection. It injects two fields — `parent` (relationship) and `breadcrumbs` (array) — and recursively updates all descendants whenever a parent changes.
|
|
|
|
Common use case: hierarchical page tree (`/about/company/our-team`).
|
|
|
|
## Install
|
|
|
|
```bash
|
|
pnpm add @payloadcms/plugin-nested-docs
|
|
```
|
|
|
|
## Basic Setup
|
|
|
|
```ts
|
|
import { nestedDocsPlugin } from '@payloadcms/plugin-nested-docs'
|
|
|
|
buildConfig({
|
|
plugins: [
|
|
nestedDocsPlugin({
|
|
collections: ['pages'],
|
|
generateLabel: (_, doc) => String(doc.title),
|
|
generateURL: (docs) =>
|
|
docs.reduce((url, doc) => `${url}/${String(doc.slug)}`, ''),
|
|
}),
|
|
],
|
|
})
|
|
```
|
|
|
|
## Auto-Injected Fields
|
|
|
|
### `parent`
|
|
- Relationship field pointing to another doc in the same collection
|
|
- Editor picks the direct parent; plugin builds the full ancestry chain
|
|
|
|
### `breadcrumbs`
|
|
Array of ancestor objects, each with:
|
|
|
|
| Field | Default | Override via |
|
|
|-------|---------|-------------|
|
|
| `label` | `admin.useAsTitle` or doc ID | `generateLabel` option |
|
|
| `url` | `undefined` | `generateURL` option |
|
|
|
|
Breadcrumbs cascade automatically — if a grandparent slug changes, every descendant's breadcrumbs update.
|
|
|
|
## Plugin Options
|
|
|
|
| Option | Type | Description |
|
|
|--------|------|-------------|
|
|
| `collections` | `string[]` | Collection slugs to enable |
|
|
| `generateLabel` | `(docs, doc, collection, req) => string` | Dynamic breadcrumb label |
|
|
| `generateURL` | `(docs, doc, collection, req) => string` | Dynamic breadcrumb URL |
|
|
| `parentFieldSlug` | `string` | Use your own `parent` field (must be top-level) |
|
|
| `breadcrumbsFieldSlug` | `string` | Use your own `breadcrumbs` field (must be top-level) |
|
|
|
|
> **Gotcha:** custom `parent`/`breadcrumbs` fields **must** be at the top level — not inside a `group`, `array`, or `blocks`.
|
|
|
|
## Field Overrides
|
|
|
|
Use `createParentField` / `createBreadcrumbsField` to extend the built-in fields:
|
|
|
|
```ts
|
|
import { createParentField, createBreadcrumbsField } from '@payloadcms/plugin-nested-docs'
|
|
|
|
fields: [
|
|
createParentField('pages', {
|
|
admin: { position: 'sidebar' },
|
|
// keep self-reference guard: filterOptions: ({ id }) => ({ id: { not_equals: id } })
|
|
}),
|
|
createBreadcrumbsField('pages', { label: 'Page Breadcrumbs' }),
|
|
]
|
|
```
|
|
|
|
> If you override the `name` of either field, set `parentFieldSlug` / `breadcrumbsFieldSlug` in plugin options.
|
|
|
|
## Localization
|
|
|
|
When `localization` is enabled in Payload Config, the `breadcrumbs` field is automatically localized. See [[wiki/payloadcms/localization|Localization]].
|
|
|
|
## TypeScript
|
|
|
|
```ts
|
|
import type {
|
|
NestedDocsPluginConfig,
|
|
GenerateURL,
|
|
GenerateLabel,
|
|
} from '@payloadcms/plugin-nested-docs/types'
|
|
```
|
|
|
|
## Key Takeaways
|
|
|
|
- Plugin injects `parent` + `breadcrumbs` fields; updates cascade recursively down the tree
|
|
- `generateURL` builds full paths like `/about/company/our-team` from breadcrumb docs array
|
|
- Custom fields are supported — set `parentFieldSlug`/`breadcrumbsFieldSlug` and place them **at top-level only**
|
|
- Use `createParentField`/`createBreadcrumbsField` when you need sidebar placement or label overrides
|
|
- Localization is automatic when Payload's `localization` config is set
|
|
- Official Website Template in the Payload repo uses this plugin as a reference
|
|
|
|
## Related
|
|
|
|
- [[wiki/payloadcms/hierarchy|Hierarchy — Tree Structure]] — Payload's built-in hierarchy feature (virtual slug/title paths, different approach)
|
|
- [[wiki/payloadcms/plugins|Official Plugins]] — all 10 official plugins overview
|
|
- [[wiki/payloadcms/localization|Localization — Content Internationalization]] — locale config used by breadcrumbs
|
|
- [[wiki/payloadcms/fields-relationship|Relationship Field]] — underlying field type used for `parent`
|
|
|
|
## Sources
|
|
|
|
- `raw/plugins__nested-docs.md`
|
|
- https://payloadcms.com/docs/plugins/nested-docs
|