---
title: "Extend your PDF export with Headers & Footers"
description: "Learn how to extend your PDF exports with custom Headers & Footers using the Export PDF extension."
canonical_url: "https://tiptap.dev/docs/conversion/export/pdf/headers-footers"
---

# Extend your PDF export with Headers & Footers

Learn how to extend your PDF exports with custom Headers & Footers using the Export PDF extension.

- **1. Activate trial or subscribe**

  Start a [free trial](https://cloud.tiptap.dev/v2?trial=true) or [subscribe to the Start plan](https://cloud.tiptap.dev/v2/billing) in your account.
- **2. Install from private registry**

  To install this frontend extension, authenticate to Tiptap's private npm registry by following the [setup guide](https://tiptap.dev/docs/guides/pro-extensions.md).

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`):

```ts
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](#header-and-footer-slot-values).

| 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](#header-and-footer-slot-values).

| 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

```js
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:

```js
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:

```js
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:

```ts
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' }] },
          ],
        },
      }),
  },
})
```
