Skip to content

Plugins ​

Plugins are the main extension mechanism in docx-kit. They let you add new node types without changing the core compiler, while keeping the same builder workflow and type-safe option objects.

Mental Model ​

Every built-in or custom plugin follows the same lifecycle:

  1. Import the plugin factory or plugin instance.
  2. Register it with .use(...).
  3. Invoke it with .plugin(name, options).
ts
import { calloutPlugin, createDocx } from 'docx-kit'

const doc = createDocx()
  .use(calloutPlugin())
  .plugin('callout', {
    type: 'success',
    title: 'Published',
    content: 'The release notes were exported successfully.',
  })

Built-in Coverage ​

docx-kit now includes 25 built-in plugins across the workspace:

  • References and terminology: crossReference, bibliography, glossary
  • Content blocks: badge, callout, checklist, codeBlock, divider, watermark
  • Report scaffolding: coverPage, letterhead, toc, pageNumber
  • Structured business data: dataTable, metricCard, propertyTable, timeline, invoice, meetingMinutes, changelog
  • Media and embeds: barcode, echarts, figure, qrcode
  • Approval workflows: signatureBlock

The full reference lives in the Plugins section.

Package Layout ​

Each built-in plugin is published as its own package under packages-plugins/:

text
packages-plugins/
  cross-reference/
  bibliography/
  glossary/
  badge/
  barcode/
  callout/
  changelog/
  checklist/
  code-block/
  cover-page/
  data-table/
  divider/
  echarts/
  figure/
  invoice/
  letterhead/
  meeting-minutes/
  metric-card/
  page-number/
  property-table/
  qrcode/
  signature-block/
  timeline/
  toc/
  watermark/

This keeps plugin releases, tests, peer dependencies, and documentation isolated.

Peer Dependencies ​

Some plugins intentionally keep their heavyweight runtime dependencies optional:

PluginWhy it is optional
@docxkit/plugin-barcodebwip-js is only needed when generating barcode images
@docxkit/plugin-code-blockhighlight.js is only needed for syntax coloring
@docxkit/plugin-echartsecharts is only needed when chart rendering is used
@docxkit/plugin-qrcodeqrcode is only needed when generating QR images

If a plugin relies on an optional peer dependency and it is missing, the plugin either falls back gracefully or throws an actionable runtime error.

Custom Plugins ​

Use definePlugin() when you need a new node type that is specific to your product or document workflow.

ts
import { definePlugin } from 'docx-kit'
import { Paragraph } from 'docx'

interface DisclaimerOptions {
  text: string
}

const disclaimerPlugin = definePlugin<'disclaimer', DisclaimerOptions>({
  name: 'disclaimer',
  render(options) {
    return new Paragraph(options.text)
  },
})

A good custom plugin should:

  • accept a small, explicit options object
  • return normal docx nodes or arrays of nodes
  • keep validation close to the render function
  • avoid hiding unrelated document mutations

Document plugins must return docx FileChild blocks such as Paragraph, Table, or TableOfContents, or a flat array of blocks (an empty array is valid). Convert DSL nodes with await context.compileNode(node). Strings, inline runs, null, and nested arrays fail with PLUGIN_RENDER_FAILED during compilation.

Tooling Around Plugins ​

  • @docxkit/create-plugin scaffolds new plugin packages
  • @docxkit/pdk provides helpers for plugin testing
  • @docxkit/loader loads plugins from inline, npm, URL, or local sources
  • @docxkit/registry discovers plugins published with docx-kit keywords
  • @docxkit/mcp exposes plugin-aware document generation tools to AI agents

See Monorepo Structure and Package Catalog for where each piece lives.

Released under the MIT License.