Fields And Blocks
Understand automatic field and block installation, manual schema control, and block rendering requirements.
Fields And Blocks
Payload Markdown supports both direct Markdown fields and reusable Payload blocks. Both store Markdown source; the difference is how the content is placed in your schema.
Automatic Install Behavior
1payloadMarkdown({2 collections: {3 pages: true,4 posts: true,5 },6})
For each enabled collection:
- if the collection has no
blocksfield, the plugin adds a Markdown text field - if the collection has a
blocksfield, the plugin installsMarkdownBlockinto that field - if both are disabled explicitly, the collection is recorded in plugin settings but no schema field is added
Explicit Install Options
Use installField and installIntoBlocks when inference is not what you want.
1payloadMarkdown({2 collections: {3 pages: {4 fieldName: 'body',5 installField: true,6 installIntoBlocks: true,7 },8 },9})
This is useful for page collections that have a layout builder but also need a primary Markdown body.
Manual Markdown Field
Use markdownField() when you want direct schema ownership.
1import { markdownField } from 'payload-markdown'2 3export const Posts = {4 slug: 'posts',5 fields: [6 markdownField({7 name: 'body',8 label: 'Body Markdown',9 localized: true,10 required: true,11 }),12 ],13}
markdownField() returns a Payload text field with the admin field component already wired to PayloadMarkdownField.
Manual Block Registration
Use MarkdownBlock when you want to place the block yourself.
1import { MarkdownBlock } from 'payload-markdown'2 3export const Pages = {4 slug: 'pages',5 fields: [6 {7 name: 'layout',8 type: 'blocks',9 blocks: [MarkdownBlock],10 },11 ],12}
The block slug is vlMdBlock. Generated Payload types use that value as the block type discriminator.
Render Block Entries
MarkdownBlockComponent accepts the block data fields directly. In a block renderer, pass the block object through as props and include collectionSlug when collection-scoped config should apply.
1import { MarkdownBlockComponent } from 'payload-markdown/server'2 3const blockComponents = {4 vlMdBlock: MarkdownBlockComponent,5}6 7export function RenderBlocks({8 blocks,9 collectionSlug,10}: {11 blocks?: Array<{ blockType?: string }>12 collectionSlug?: string13}) {14 if (!blocks?.length) return null15 16 return blocks.map((block, index) => {17 const Block = block.blockType ? blockComponents[block.blockType] : undefined18 if (!Block) return null19 20 return <Block {...block} collectionSlug={collectionSlug} key={index} />21 })22}
MarkdownBlockComponent accepts block data as direct props and renders the content field. Pass {...block}, not block={block}.
Field And Block Presentation
Use a split config object when fields and blocks need different typography or wrappers:
1payloadMarkdown({2 collections: {3 pages: {4 config: {5 blocks: {6 size: 'md',7 variant: 'docs',8 },9 field: {10 size: 'lg',11 variant: 'blog',12 },13 },14 },15 },16})
MarkdownBlockComponent resolves block scope internally. Direct field rendering should use scope="field" or omit scope, since field is the default.
Per-Block Params
Each markdown block has a Markdown Blocks Params group. While Enable Blocks Params is unchecked, the block renders with the global and collection block settings above.
Checking it fills the block's fields with exactly those effective values: the global config, then the collection's config.blocks and code, then the renderer's defaults. Enabling therefore changes nothing until you edit a field, and you only change the values you need. Unchecking clears the fields again.
For a block with params enabled, the block's values are the highest-precedence layer for that block:
| Layer | Precedence |
|---|---|
| Block params (enabled) | highest |
Collection config.blocks and collection code | |
Global config (blocks) and global code | |
| Renderer defaults | lowest |
A set block value replaces the inherited one (class names included). An empty or unset value inherits, so clearing a field never removes global or collection settings. The fields map to renderer options: showLineNumbers → code.lineNumbers, theme → code.shikiTheme, enhancedCodeBlocks → code.enhanced and fullBleedCode → code.fullBleed.
Pass every block field to MarkdownBlockComponent (<Block {...block} />, as shown above) so md-params reaches it. The "Enable Blocks Params" checkbox is an admin component: run payload generate:importmap after upgrading so it appears in your import map.