Extend your PDF export with Headers & Footers
The @tiptap-pro/extension-export-pdf extension includes built-in support for customizing the headers and footers of the exported document. You can configure different headers and footers for the first page, odd pages, and even pages.
Header and footer slot values
Each header and footer slot (default, first, even) accepts one of the shapes below. Mix and match freely across slots; pick whichever matches your data.
| Shape | Example | Notes |
|---|---|---|
| Plain text | 'Company name, 2026' | Rendered as an unstyled header/footer. |
| Stringified Tiptap JSONContent | JSON.stringify(myHeaderDoc) | Pre-serialized Tiptap node. Rich formatting (bold, italic, links, etc.) is preserved on render. |
| Tiptap JSONContent object | { type: 'doc', content: [/* … */] } | A Tiptap node passed directly. Same fidelity as stringified JSONContent, but no JSON.stringify step. |
docx Header / Footer | new Docx.Header({ children: [/* … */] }) | Full DOCX-level control over paragraphs and runs. Requires @tiptap-pro/extension-export-docx. |
Async factory returning Header / Footer | () => convertHeader({ node }) | Built on demand when the export runs. Typical use: convertHeader / convertFooter from the DOCX extension. |
Tiptap JSONContent objects must include a type field. The extension uses it at runtime to distinguish a Tiptap node from a docx instance. Objects without type that aren't Header / Footer instances are dropped with a console.warn naming the offending value; they're never forwarded to the DOCX serializer.
In TypeScript these collapse to two aliases (the type requirement is encoded in TiptapNodeContent):
import type { JSONContent } from '@tiptap/core'
import type { Footer, Header } from 'docx'
type TiptapNodeContent = JSONContent & { type: string }
type HeaderSlotValue = string | TiptapNodeContent | Header | (() => Promise<Header>)
type FooterSlotValue = string | TiptapNodeContent | Footer | (() => Promise<Footer>)The first three shapes work on their own with @tiptap-pro/extension-export-pdf. The Header / Footer instance and async-factory shapes require @tiptap-pro/extension-export-docx to be installed; they take the DOCX-first export path, which is loaded on demand so PDF-only consumers aren't affected.
Headers Configuration
The headers object configures the running header. Each slot accepts a header slot value.
| Property | Type | Description |
|---|---|---|
evenAndOddHeaders | boolean | Whether to use different headers for odd and even pages. |
differentFirstPage | boolean | Whether to use a different header on the first page. When true, the first value is used on page one instead of default. |
default | HeaderSlotValue | The standard default header on every page, or the header on odd pages when evenAndOddHeaders is active. |
first | HeaderSlotValue | The header on the first page. Only used when differentFirstPage is true. |
even | HeaderSlotValue | The header on even pages. Only used when evenAndOddHeaders is true. |
Footers Configuration
The footers object mirrors headers. Each slot accepts a footer slot value.
| Property | Type | Description |
|---|---|---|
evenAndOddFooters | boolean | Whether to use different footers for odd and even pages. |
differentFirstPage | boolean | Whether to use a different footer on the first page. When true, the first value is used on page one instead of default. |
default | FooterSlotValue | The standard default footer on every page, or the footer on odd pages when evenAndOddFooters is active. |
first | FooterSlotValue | The footer on the first page. Only used when differentFirstPage is true. |
even | FooterSlotValue | The footer on even pages. Only used when evenAndOddFooters is true. |
Complete example
import { ExportPdf } from '@tiptap-pro/extension-export-pdf'
const editor = new Editor({
extensions: [
// Other extensions...
ExportPdf.configure({
token: 'YOUR_TOKEN',
appId: 'YOUR_APP_ID',
headers: {
evenAndOddHeaders: true,
default: 'My Document - Confidential',
first: 'Welcome to My Document',
even: 'My Document - Even Page',
},
footers: {
evenAndOddFooters: true,
default: 'Company Name - All Rights Reserved',
first: 'Draft Version 1.0',
even: 'Company Name - Even Page Footer',
},
}),
// Other extensions...
],
})
// Export with headers and footers
editor
.chain()
.exportPdf({
onCompleteExport(result) {
const url = URL.createObjectURL(result)
const a = document.createElement('a')
a.href = url
a.download = 'document-with-headers.pdf'
a.click()
URL.revokeObjectURL(url)
},
})
.run()Simple headers and footers
If you don't need different headers for odd/even pages, you can provide just the default values:
ExportPdf.configure({
token: 'YOUR_TOKEN',
appId: 'YOUR_APP_ID',
headers: {
default: 'My Document Title',
},
footers: {
default: 'Page Footer - Company Name',
},
})Rich headers via Tiptap JSONContent
Pass a Tiptap JSONContent node directly on any slot. This is useful when you already have the node in memory and don't want to build a Docx.Header by hand:
ExportPdf.configure({
token: 'YOUR_TOKEN',
appId: 'YOUR_APP_ID',
headers: {
default: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{ type: 'text', marks: [{ type: 'bold' }], text: 'My Document' },
{ type: 'text', text: ' · Confidential' },
],
},
],
},
},
})Docx Header / Footer instances
For full control over paragraph properties, alignment, and run styles you can pass a docx Header / Footer instance (or an async factory that returns one). This requires @tiptap-pro/extension-export-docx to be installed alongside the PDF extension:
import { Docx, convertHeader } from '@tiptap-pro/extension-export-docx'
ExportPdf.configure({
token: 'YOUR_TOKEN',
appId: 'YOUR_APP_ID',
headers: {
// Direct Docx.Header instance
default: new Docx.Header({
children: [
new Docx.Paragraph({
children: [new Docx.TextRun({ text: 'My Document' })],
}),
],
}),
// Async factory: convert a Tiptap node to a Docx.Header on demand
first: () =>
convertHeader({
node: {
type: 'doc',
content: [
{ type: 'paragraph', content: [{ type: 'text', text: 'Welcome' }] },
],
},
}),
},
})