Pages extension API reference
This page is the canonical reference for the Pages extension's options, commands, and storage. For task-focused walkthroughs, see Page format, Page header and footer, Footnotes, Page gap, Page break node, and Zoom.
Options interface
import type { Extensions, JSONContent } from '@tiptap/core'
type PagesHeaderFooter = string | JSONContent
type BuiltInPageFormat = 'A4' | 'A3' | 'A5' | 'Letter' | 'Legal' | 'Tabloid'
interface CustomPageFormat {
id: string
width: number // pixels
height: number // pixels
margins: {
top: number
right: number
bottom: number
left: number
}
}
type PageFormat = BuiltInPageFormat | CustomPageFormat
interface PagesOptions {
/** Built-in format name or custom page format object. Default: 'A4'. */
pageFormat: PageFormat
/** Initial zoom level. Clamped to [0.25, 4]. Default: 1. */
zoom?: number
/** Default header content. Accepts a plain string, an HTML string, or Tiptap JSONContent.
* Supports `{page}` and `{total}` placeholders. Default: ''. */
header: string | JSONContent
/** Default footer content. Same shape as `header`. Default: ''. */
footer: string | JSONContent
/** Distance from the page top to where the header content starts (pixels).
* Defaults to 50% of the page top margin. */
headerTopMargin?: number
/** Distance from the footer content bottom to the page bottom (pixels).
* Defaults to 50% of the page bottom margin. */
footerBottomMargin?: number
/** Visual gap between pages (pixels). Default: 50. */
pageGap?: number
/** CSS color shown in the area between pages. Default: '#ffffff'. */
pageGapBackground?: string
/** Accent color applied to both header and footer editor overlays. Default: '#6366f1'. */
accentColor?: string
/** Accent color for the header overlay only. Defaults to the `accentColor` value. */
headerAccentColor?: string
/** Accent color for the footer overlay only. Defaults to the `accentColor` value. */
footerAccentColor?: string
/** Show the white fade gradient behind the edit-overlay toolbars (header, footer,
* footnotes, endnotes). Set to false for a flat, gradient-free toolbar. Default: true. */
toolbarGradient?: boolean
/** Enable a different header and footer for the first page (Word's "Different First Page").
* Default: false. */
differentFirstPage?: boolean
/** First-page header content. Default: ''. */
headerFirstPage?: PagesHeaderFooter
/** First-page footer content. Default: ''. */
footerFirstPage?: PagesHeaderFooter
/** Enable different headers and footers on odd vs. even pages (Word's "Different Odd & Even Pages").
* Default: false. */
differentOddEven?: boolean
/** Odd-pages header content. Default: ''. */
headerOdd?: PagesHeaderFooter
/** Even-pages header content. Default: ''. */
headerEven?: PagesHeaderFooter
/** Odd-pages footer content. Default: ''. */
footerOdd?: PagesHeaderFooter
/** Even-pages footer content. Default: ''. */
footerEven?: PagesHeaderFooter
/** Whether double-clicking the header opens the inline editor overlay.
* When false, the overlay cannot be opened by users or by `openHeaderEditor`.
* Default: true. */
editableHeader?: boolean
/** Whether double-clicking the footer opens the inline editor overlay.
* When false, the overlay cannot be opened by users or by `openFooterEditor`.
* Default: true. */
editableFooter?: boolean
/** Enable a different first-page footer independently of `differentFirstPage`.
* Set automatically when `setDifferentFirstPage(true)` is called. */
differentFirstPageFooter?: boolean
/** Enable different odd/even footers independently of `differentOddEven`.
* Set automatically when `setDifferentOddEven(true)` is called. */
differentOddEvenFooter?: boolean
/** Extensions registered on the inner header/footer editors.
*
* Accepts a static `Extensions` array, OR a callback that receives a
* `HeaderFooterExtensionsContext` per subtype (default / first / odd / even ×
* header / footer) and returns the extensions for that sub-editor. Use the
* callback form to attach `Collaboration` against the auto-computed Y field
* for each subtype. See Adding collaboration to Pages.
*
* Defaults to ConvertKit; mirror your main editor's stack to keep schemas aligned. */
headerFooterExtensions?: Extensions | ((ctx: HeaderFooterExtensionsContext) => Extensions)
/** Called when `setPageFormat()` succeeds, or when configure() applies a new format. */
onPageFormatChange?: (pageFormat: PageFormat) => void
/** Called when `setZoom()` changes the zoom level. */
onZoomChange?: (zoom: number) => void
/** Optional: return true to keep the active header or footer editor open when the user
* double-clicks outside it. Applies to both. */
onDblClickHeaderFooterPreventClose?: (event: MouseEvent) => boolean
/** Like `onDblClickHeaderFooterPreventClose`, but only for the header overlay.
* Takes priority over the fallback when both are set. */
onDblClickHeaderPreventClose?: (event: MouseEvent) => boolean
/** Like `onDblClickHeaderFooterPreventClose`, but only for the footer overlay.
* Takes priority over the fallback when both are set. */
onDblClickFooterPreventClose?: (event: MouseEvent) => boolean
/** Rename the built-in `{page}` / `{total}` placeholder tokens, or pass
* `false` to disable substitution entirely. Default: undefined (use built-ins as-is). */
placeholders?: false | { page?: string; total?: string }
/** Word-like footnotes. Disabled unless `enabled` is true. See Footnotes. */
footnotes?: {
/** Master switch. Default: false. */
enabled?: boolean
/** Extensions for the footnotes editor. Static array, or a callback that
* receives collaboration context (Y field + Y.Doc) for the footnotes
* editor. Defaults to ConvertKit. */
extensions?: Extensions | ((ctx: FootnotesExtensionsContext) => Extensions)
/** Seed footnote content keyed by note id (matches the DOCX import shape).
* Non-collaborative documents only. */
initialContent?: Record<string, JSONContent>
/** Render the Word-style separator rule above the footnotes area. Default: true. */
separator?: boolean
/** Maximum fraction of the page content height the footnotes area may
* occupy before clipping. Default: 0.5. */
maxHeightRatio?: number
/** Whether double-clicking the footnotes area opens the editor. Default: true. */
editable?: boolean
/** Accent color for footnote markers and the footnotes editor.
* Defaults to the `accentColor` value. */
accentColor?: string
}
/** Like `onDblClickHeaderFooterPreventClose`, but only for the footnotes editor.
* Takes priority over the fallback when both are set. */
onDblClickFootnotesPreventClose?: (event: MouseEvent) => boolean
/** Word-like endnotes, collected at the end of the document. Disabled unless
* `enabled` is true. See Endnotes. */
endnotes?: {
/** Master switch. Default: false. */
enabled?: boolean
/** Extensions for the endnotes editor. Static array, or a callback that
* receives collaboration context (Y field + Y.Doc) for the endnotes
* editor. Defaults to ConvertKit. */
extensions?: Extensions | ((ctx: EndnotesExtensionsContext) => Extensions)
/** Seed endnote content keyed by note id (matches the DOCX import shape).
* Non-collaborative documents only. */
initialContent?: Record<string, JSONContent>
/** Render the Word-style separator rule above the endnotes list. Default: true. */
separator?: boolean
/** Whether double-clicking the endnotes list opens the editor. Default: true. */
editable?: boolean
/** Accent color for endnote markers and the endnotes editor.
* Defaults to the `accentColor` value. */
accentColor?: string
}
/** Like `onDblClickHeaderFooterPreventClose`, but only for the endnotes editor.
* Takes priority over the fallback when both are set. */
onDblClickEndnotesPreventClose?: (event: MouseEvent) => boolean
}Options reference
Layout
| Option | Type | Default | Notes |
|---|---|---|---|
pageFormat | PageFormat | 'A4' | See Page format for built-ins. |
zoom | number | 1 | Clamped to [0.25, 4]. See Zoom. |
pageGap | number | 50 | Pixels. Visual only; does not affect export. |
pageGapBackground | string | '#ffffff' | Any CSS color value. |
Headers and footers
The full reference for header/footer options lives on Page header and footer. The table below summarises the surface; for first-page, odd/even, content types, and editor-overlay behaviour, follow the link.
| Option | Type | Default | Description |
|---|---|---|---|
header | PagesHeaderFooter | '' | Default header content |
footer | PagesHeaderFooter | '' | Default footer content |
headerTopMargin | number | 50% of top margin | Distance from page top to header content (px) |
footerBottomMargin | number | 50% of bottom margin | Distance from footer content to page bottom (px) |
differentFirstPage | boolean | false | First-page header and footer differ from the rest |
headerFirstPage | PagesHeaderFooter | '' | First-page header content |
footerFirstPage | PagesHeaderFooter | '' | First-page footer content |
differentOddEven | boolean | false | Odd/even pages have different headers and footers |
headerOdd | PagesHeaderFooter | '' | Odd-pages header content |
headerEven | PagesHeaderFooter | '' | Even-pages header content |
footerOdd | PagesHeaderFooter | '' | Odd-pages footer content |
footerEven | PagesHeaderFooter | '' | Even-pages footer content |
editableHeader | boolean | true | Allow opening the header overlay on double-click |
editableFooter | boolean | true | Allow opening the footer overlay on double-click |
headerFooterExtensions | Extensions | (ctx) => Extensions | ConvertKit | Extensions for the inner header/footer editors. Pass a callback to attach Collaboration per subtype (see Adding collaboration to Pages). |
onDblClickHeaderFooterPreventClose | (event: MouseEvent) => boolean | undefined | Prevent closing on double-click outside (header + footer) |
onDblClickHeaderPreventClose | (event: MouseEvent) => boolean | undefined | Prevent closing on double-click outside (header only) |
onDblClickFooterPreventClose | (event: MouseEvent) => boolean | undefined | Prevent closing on double-click outside (footer only) |
accentColor | string | '#6366f1' | Accent color for both overlays |
headerAccentColor | string | accentColor value | Accent color for the header overlay only |
footerAccentColor | string | accentColor value | Accent color for the footer overlay only |
toolbarGradient | boolean | true | Show the white fade gradient behind the edit-overlay toolbars (header, footer, footnotes, endnotes). Set false for flat toolbars. |
placeholders | false | { page?, total? } | undefined | Rename {page} / {total} tokens, or false to disable |
Footnotes
The full reference for footnote options lives on Footnotes. All options below sit under the footnotes key unless noted otherwise.
| Option | Type | Default | Description |
|---|---|---|---|
footnotes.enabled | boolean | false | Master switch for the footnotes feature |
footnotes.extensions | Extensions | (ctx) => Extensions | ConvertKit | Extensions for the footnotes editor; callback form enables collaboration |
footnotes.initialContent | Record<string, JSONContent> | undefined | Seed footnote content keyed by note id (non-collaborative only) |
footnotes.separator | boolean | true | Render the separator rule above the footnotes area |
footnotes.maxHeightRatio | number | 0.5 | Max fraction of page content height the area may occupy |
footnotes.editable | boolean | true | Allow opening the footnotes editor on double-click |
footnotes.accentColor | string | accentColor value | Accent color for markers and the footnotes editor |
onDblClickFootnotesPreventClose | (event: MouseEvent) => boolean (top-level option) | undefined | Prevent closing the footnotes editor on double-click outside |
Endnotes
The full reference for endnote options lives on Endnotes. All options below sit under the endnotes key unless noted otherwise.
| Option | Type | Default | Description |
|---|---|---|---|
endnotes.enabled | boolean | false | Master switch for the endnotes feature |
endnotes.extensions | Extensions | (ctx) => Extensions | ConvertKit | Extensions for the endnotes editor; callback form enables collaboration |
endnotes.initialContent | Record<string, JSONContent> | undefined | Seed endnote content keyed by note id (non-collaborative only) |
endnotes.separator | boolean | true | Render the separator rule above the endnotes list |
endnotes.editable | boolean | true | Allow opening the endnotes editor on double-click |
endnotes.accentColor | string | accentColor value | Accent color for markers and the endnotes editor |
onDblClickEndnotesPreventClose | (event: MouseEvent) => boolean (top-level option) | undefined | Prevent closing the endnotes editor on double-click outside |
Callbacks
| Option | Type | Description |
|---|---|---|
onPageFormatChange | (format: PageFormat) => void | Fired when the page format changes via configure or setPageFormat. |
onZoomChange | (zoom: number) => void | Fired when the zoom level changes via setZoom. |
Commands reference
For deep treatment of each command, see the linked core-concepts page.
Layout commands
| Command | Parameters | Description |
|---|---|---|
setPageFormat | pageFormat: PageFormat | Change the page format. Fires onPageFormatChange. |
setZoom | zoom: number | Set zoom (clamped to [0.25, 4]). Fires onZoomChange. |
setPageGap | pageGap: number | Set the gap between pages (px). Must be positive. |
setPageGapBackground | color: string | Set the page-gap background color (any CSS color value). |
Header / footer commands
The full reference also lives on Page header and footer.
| Command | Parameters | Description |
|---|---|---|
setHeader | header: PagesHeaderFooter | Set the default header content |
setFooter | footer: PagesHeaderFooter | Set the default footer content |
setHeaderTopMargin | margin: number | Set header top margin (px) |
setFooterBottomMargin | margin: number | Set footer bottom margin (px) |
setDifferentFirstPage | enabled: boolean | Toggle different first-page header and footer |
setDifferentFirstPageFooter | enabled: boolean | Toggle different first-page footer independently |
setHeaderFirstPage | header: PagesHeaderFooter | Set first-page header content |
setFooterFirstPage | footer: PagesHeaderFooter | Set first-page footer content |
setDifferentOddEven | enabled: boolean | Toggle different odd/even headers and footers |
setDifferentOddEvenFooter | enabled: boolean | Toggle different odd/even footers independently |
setHeaderOdd | header: PagesHeaderFooter | Set odd-pages header content |
setHeaderEven | header: PagesHeaderFooter | Set even-pages header content |
setFooterOdd | footer: PagesHeaderFooter | Set odd-pages footer content |
setFooterEven | footer: PagesHeaderFooter | Set even-pages footer content |
setHeaderEditable | enabled: boolean | Lock or unlock the header overlay (controls editableHeader). |
setFooterEditable | enabled: boolean | Lock or unlock the footer overlay (controls editableFooter). |
openHeaderEditor | { pageNumber: number } | Open header editor for a specific page (1-indexed). |
openFooterEditor | { pageNumber: number } | Open footer editor for a specific page (1-indexed). |
closeHeaderFooterEditors | none | Close whichever header/footer editor is open |
closeHeaderEditor | none | Close the header editor if open |
closeFooterEditor | none | Close the footer editor if open |
setAccentColor | color: string | Set accent color for both editor overlays |
setHeaderAccentColor | color: string | Set accent color for the header overlay only |
setFooterAccentColor | color: string | Set accent color for the footer overlay only |
Footnote commands
The full reference also lives on Footnotes.
| Command | Parameters | Description |
|---|---|---|
insertFootnote | none | Insert a footnote at the selection and open its editor |
setFootnotes | footnotes: Record<string, JSONContent> | Replace all footnote content from an id → document map |
openFootnoteEditor | { pageNumber: number, focusNoteId?: string } | Open the footnotes editor for a page (1-indexed) |
closeFootnoteEditor | none | Close the footnotes editor if open |
setFootnotesEditable | enabled: boolean | Lock or unlock footnotes editing (controls footnotes.editable) |
cleanupOrphanFootnotes | none | Permanently remove footnote content whose references are gone |
setFootnotesAccentColor | color: string | Set the footnotes accent color |
Endnote commands
The full reference also lives on Endnotes.
| Command | Parameters | Description |
|---|---|---|
insertEndnote | none | Insert an endnote at the selection and open its editor |
setEndnotes | endnotes: Record<string, JSONContent> | Replace all endnote content from an id → document map |
openEndnoteEditor | { focusNoteId?: string } (optional) | Open the endnotes editor, optionally focusing a specific note |
closeEndnoteEditor | none | Close the endnotes editor if open |
setEndnotesEditable | enabled: boolean | Lock or unlock endnotes editing (controls endnotes.editable) |
cleanupOrphanEndnotes | none | Permanently remove endnote content whose references are gone |
setEndnotesAccentColor | color: string | Set the endnotes accent color |
Storage reference
Read these from editor.storage.pages. Properties marked read-only should not be written directly; use the matching command.
Layout
| Property | Type | Description |
|---|---|---|
pageFormat | PageFormat | Current page format |
zoom | number | Current zoom level (read-only, use setZoom) |
getZoom | () => number | Convenience getter for the current zoom |
pageGap | number | Current gap between pages (px) |
pageGapBackground | string | Current page-gap background color |
getCurrentPage | () => number | null | The 1-indexed page number where the cursor sits |
getDistanceToNextPagebreak | (pos: number) => number | null | Pixel distance from pos to the next page break |
getDistanceToPrevPagebreak | (pos: number) => number | null | Pixel distance from pos to the previous page break |
Headers and footers (rendered HTML and JSON)
After a user edits a header or footer through its overlay, both the rendered HTML and the underlying Tiptap JSON are exposed on storage. Use the JSON forms when serialising for DOCX export. The HTML properties are always strings (defaulting to '' before any edit). The JSON properties are null until the user first edits the corresponding header or footer through its overlay.
| Property | Type | Description |
|---|---|---|
headerHTML | string | Default header rendered HTML |
headerJSON | Record<string, any> | null | Default header as Tiptap JSON |
headerFirstPageHTML | string | First-page header rendered HTML |
headerFirstPageJSON | Record<string, any> | null | First-page header as Tiptap JSON |
headerOddHTML | string | Odd-pages header rendered HTML |
headerOddJSON | Record<string, any> | null | Odd-pages header as Tiptap JSON |
headerEvenHTML | string | Even-pages header rendered HTML |
headerEvenJSON | Record<string, any> | null | Even-pages header as Tiptap JSON |
footerHTML | string | Default footer rendered HTML |
footerJSON | Record<string, any> | null | Default footer as Tiptap JSON |
footerFirstPageHTML | string | First-page footer rendered HTML |
footerFirstPageJSON | Record<string, any> | null | First-page footer as Tiptap JSON |
footerOddHTML | string | Odd-pages footer rendered HTML |
footerOddJSON | Record<string, any> | null | Odd-pages footer as Tiptap JSON |
footerEvenHTML | string | Even-pages footer rendered HTML |
footerEvenJSON | Record<string, any> | null | Even-pages footer as Tiptap JSON |
differentFirstPage | boolean | Whether the first page differs |
differentOddEven | boolean | Whether odd/even pages differ |
differentFirstPageFooter | boolean | First-page footer differs (independent flag) |
differentOddEvenFooter | boolean | Odd/even footers differ (independent flag) |
editableHeader | boolean | Whether the header overlay can be opened (read-only, use setHeaderEditable) |
editableFooter | boolean | Whether the footer overlay can be opened (read-only, use setFooterEditable) |
accentColor | string | Current accent color (both) |
headerAccentColor | string | Current header accent color |
footerAccentColor | string | Current footer accent color |
Footnotes
The full reference also lives on Footnotes.
| Property | Type | Description |
|---|---|---|
footnotesJSON | Record<string, JSONContent> | Footnote content per note id, use for persistence and DOCX export |
footnotesHTML | Record<string, string> | Rendered HTML per note id, matching the page previews |
footnoteNumbers | Record<string, number> | Current numbering (note id → 1-based number) |
footnotesEnabled | boolean | Whether footnotes are enabled |
editableFootnotes | boolean | Whether editing is unlocked (read-only, use setFootnotesEditable) |
Endnotes
The full reference also lives on Endnotes.
| Property | Type | Description |
|---|---|---|
endnotesJSON | Record<string, JSONContent> | Endnote content per note id, use for persistence and DOCX export |
endnotesHTML | Record<string, string> | Rendered HTML per note id, matching the document |
endnoteNumbers | Record<string, number> | Current numbering (note id → 1-based number) |
endnotesEnabled | boolean | Whether endnotes are enabled |
editableEndnotes | boolean | Whether editing is unlocked (read-only, use setEndnotesEditable) |
Active inner-editor state
When a header, footer, footnotes, or endnotes overlay is open, these properties reflect which one is active. Useful for building toolbars that follow the focused editor; see Page header and footer for a complete toolbar example.
| Property | Type | Description |
|---|---|---|
activeEditor | Editor | null | The active header/footer/footnotes/endnotes editor instance, or null |
activeEditorType | 'header' | 'footer' | 'footnotes' | 'endnotes' | null | Which kind of overlay is active |
activePageNumber | number | null | Page number being edited (header/footer/footnotes) |
headerEditorOn | Editor['on'] | null | Pre-bound subscriber for events on the header overlay's inner editor |
headerEditorOff | Editor['off'] | null | Pre-bound unsubscriber for the header overlay's inner editor |
footerEditorOn | Editor['on'] | null | Pre-bound subscriber for events on the footer overlay's inner editor |
footerEditorOff | Editor['off'] | null | Pre-bound unsubscriber for the footer overlay's inner editor |
footnotesEditorOn | Editor['on'] | null | Pre-bound subscriber for events on the footnotes editor |
footnotesEditorOff | Editor['off'] | null | Pre-bound unsubscriber for the footnotes editor |
endnotesEditorOn | Editor['on'] | null | Pre-bound subscriber for events on the endnotes editor |
endnotesEditorOff | Editor['off'] | null | Pre-bound unsubscriber for the endnotes editor |
Example usage
Built-in format
import { Editor } from '@tiptap/core'
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'
import { TableKit } from '@tiptap-pro/extension-pages-tablekit'
import { Pages } from '@tiptap-pro/extension-pages'
const editor = new Editor({
extensions: [
ConvertKit.configure({ table: false }),
TableKit,
Pages.configure({
pageFormat: 'A4',
pageGap: 40,
header: 'My Project',
footer: 'Page {page} of {total}',
pageGapBackground: '#f8f8f8',
}),
],
})Custom format and a runtime change
import { cmToPixels } from '@tiptap-pro/extension-pages'
Pages.configure({
pageFormat: {
id: 'custom-page-format',
width: cmToPixels(22.94),
height: cmToPixels(35.18),
margins: {
top: cmToPixels(2.54),
right: cmToPixels(2.54),
bottom: cmToPixels(2.54),
left: cmToPixels(2.54),
},
},
onPageFormatChange: (pageFormat) => {
console.log('Page format changed:', pageFormat.id)
},
})
// Switch later
editor.commands.setPageFormat('Letter')Header and footer template tokens
Both header and footer accept the tokens {page} (current 1-indexed page) and
{total} (total page count). They are substituted at render time and work in plain
strings, HTML strings, and JSONContent.