From zero to print-ready: Pages & DOCX export
This guide walks through setting up a Tiptap editor from scratch with the Pages extension for paginated, print-like layout, plus DOCX export and import for a professional, print-ready workflow.
1. Install the Pages stack
Install the three Pro packages that always go together when you build with Pages:
npm install @tiptap-pro/extension-convert-kit \
@tiptap-pro/extension-pages-tablekit \
@tiptap-pro/extension-pagesWhy these three packages
@tiptap-pro/extension-convert-kit provides the editor's node and mark schema (paragraphs,
headings, lists, images, marks). @tiptap-pro/extension-pages-tablekit provides pagination-safe
tables — required, because ConvertKit's bundled tables are not designed to paginate.
@tiptap-pro/extension-pages provides the page layout itself. Make sure you've authenticated to
the Tiptap private npm registry first; see the Pro Extensions guide for
setup.
2. Set up your editor with Pages
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',
}),
],
})Best practice
Add Pages early in your setup so that document structure and layout are consistent from the start. You can change the page format, headers, and footers later via commands; it's harder to retrofit Pages onto a document that was already authored without pagination in mind.
3. Add DOCX export capability
Install the DOCX export extension:
npm install @tiptap-pro/extension-export-docxAdd it to your editor:
import { ExportDocx } from '@tiptap-pro/extension-export-docx'
const editor = new Editor({
extensions: [
ConvertKit.configure({ table: false }),
TableKit,
Pages.configure({
/* ... */
}),
ExportDocx,
],
})3a. Configure DOCX export
The DOCX export extension runs entirely in the browser — no JWT, no App ID, no server call. You configure it with an onCompleteExport callback that receives the result:
import { ExportDocx } from '@tiptap-pro/extension-export-docx'
ExportDocx.configure({
// Required. The exported file is delivered through this callback.
onCompleteExport: (result) => {
const blob = new Blob([result], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
})
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'document.docx'
a.click()
URL.revokeObjectURL(url)
},
// Optional: 'blob' (default), 'buffer', 'string', etc.
exportType: 'blob',
// Optional: override paragraph, heading, table styles, etc.
styleOverrides: {},
// Optional: define DOCX serialisation for any custom Tiptap nodes you've added.
customNodes: [],
})Required
onCompleteExport is required. The export does not return its result; it hands the result to your
callback for you to download, upload, or process.
4. Export your document
Trigger an export from the editor's command chain:
editor.commands.exportDocx()Round-trip is not byte-identical
DOCX export is faithful but not lossless. A few features (subscript/superscript marks, paragraph line-height, floating tables) round-trip imperfectly. See the feature support matrix for the full list.
5. Import DOCX files into your editor
Add the import extension so users can load Word documents into the paginated editor:
npm install @tiptap-pro/extension-import-docximport { ImportDocx } from '@tiptap-pro/extension-import-docx'
const editor = new Editor({
extensions: [
ConvertKit.configure({ table: false }),
TableKit,
Pages.configure({
/* ... */
}),
ExportDocx.configure({
/* ... */
}),
ImportDocx.configure({
appId: 'YOUR_APP_ID', // Your Convert App ID
token: 'YOUR_JWT', // A JWT generated by your server
// Optional: where the import service should upload images extracted from the document
// imageUploadConfig: { url: 'https://your-server.com/upload-image' },
}),
],
})To trigger an import, pass a File from an <input type="file" />:
editor
.chain()
.importDocx({
file,
onImport(context) {
if (context.error) {
// Handle the failure (toast, log, retry, etc.)
return
}
context.setEditorContent(context.content)
},
})
.run()When the imported document carries headers and footers, the Pages extension picks them up automatically — they appear at the top and bottom of each rendered page without further wiring.
Where to get your App ID and JWT
See the Conversion install guide for credential setup. JWTs must be generated server-side; never embed your secret key in the browser.
Next steps
- Pages options — every option Pages exposes
- Page header and footer — different first page, odd/even pages, programmatic editor open/close
- PagesTableKit — pagination-safe tables in detail, including the most important known limitation
- Limitations — non-splittable content, what Pages does not do, and how to work around each case
Need help?
Reach out to support if you hit something unexpected, or check the rest of the documentation for advanced workflows.