Builder API
The DocxBuilder class, createDocx() factory, renderDocx() JSON entry point, and export methods.
createDocx(config?)
The primary entry point. Returns a fluent DocxBuilder for chaining content.
import { createDocx } from 'docx-kit'
const doc = createDocx({
page: { size: 'A4', margin: '2cm 2.5cm' },
styles: { /* defineStyles(...) */ },
theme: { /* theme tokens */ },
defaults: {
text: { fontFamily: 'Arial', fontSize: 11 },
},
metadata: {
title: 'Annual Report',
creator: 'Alice',
customProperties: {
Department: 'Finance',
},
},
})Binary font data can be embedded once and referenced by its family name in document styles:
import { readFile } from 'node:fs/promises'
import { createDocx } from 'docx-kit/node'
const doc = createDocx({
fonts: [
{
name: 'Inter',
data: await readFile('./Inter-Regular.ttf'),
},
],
defaults: {
text: { fontFamily: 'Inter' },
},
})DocxBuilder<TStyles, TPlugins>
The fluent builder class returned by createDocx().
class DocxBuilder<
TStyles extends StyleSheet = StyleSheet,
TPlugins extends PluginRegistry = PluginRegistry,
> {
// ── Content ──
h1(text: string, opts?: StyleOptions): this
h2(text: string, opts?: StyleOptions): this
h3(text: string, opts?: StyleOptions): this
h4(text: string, opts?: StyleOptions): this
h5(text: string, opts?: StyleOptions): this
h6(text: string, opts?: StyleOptions): this
p(text: string | InlineNode[], opts?: StyleOptions): this
bookmark(name: string, children: (string | TextNode)[], opts?: StyleOptions): this
bulletList(items: BulletItem[], opts?: StyleOptions): this
checkbox(options?: CheckboxOptions): this
comment(options: CommentOptions): this
footnote(content: (string | ParagraphNode)[], opts?: StyleOptions): this
math(children: MathExpression[]): this
numberedList(items: BulletItem[], opts?: StyleOptions): this
hyperlink(url: string, text: string, opts?: StyleOptions): this
internalLink(anchor: string, text: string, opts?: StyleOptions): this
insertedText(options: RevisionOptions): this
deletedText(options: RevisionOptions): this
image(options: ImageNode): this
table<T>(options: TableOptions<T>): this
textBox(options: TextBoxOptions): this
thematicBreak(opts?: StyleOptions): this
columnBreak(): this
pageBreak(): this
section(config?: SectionConfig): this
add(node: BlockNode): this
// ── Plugins ──
use(plugin: DocxPlugin): DocxBuilder<TStyles, TPlugins & Record<TName, TOptions>>
plugin(name: TName, options: TOptions, opts?: StyleOptions): this
// ── Rich Content ──
span(text: string, style?: DocxStyleRule): TextNode
inlineImg(options: InlineImageOptions): ImageNode
// ── Debug ──
toJSON(): object
// ── Export ──
save(filename: string): Promise<void> // Node.js only
toBlob(): Promise<Blob>
toUint8Array(): Promise<Uint8Array>
toBuffer(): Promise<Uint8Array> // alias for toUint8Array
toBase64(): Promise<string>
toDocument(): Promise<Document> // raw docx Document
}Content Methods
| Method | Description |
|---|---|
.h1(text, opts?) | Level-1 heading |
.h2(text, opts?) | Level-2 heading |
.h3(text, opts?) | Level-3 heading |
.h4(text, opts?) | Level-4 heading |
.h5(text, opts?) | Level-5 heading |
.h6(text, opts?) | Level-6 heading |
.p(text, opts?) | Paragraph with optional inline children |
.bookmark(name, children, opts?) | Named bookmark target |
.bulletList(items, opts?) | Unordered list |
.checkbox(options?) | Word checkbox content control |
.comment(options) | Annotated range with a Word comment |
.footnote(content, opts?) | Footnote reference and body |
.math(children) | Structured Office Math expression |
.numberedList(items, opts?) | Ordered list |
.hyperlink(url, text, opts?) | Clickable hyperlink |
.internalLink(anchor, text, opts?) | Link to a bookmark in the document |
.insertedText(options) | Tracked insertion |
.deletedText(options) | Tracked deletion |
.table({ columns, data, ... }) | Data table |
.image({ data, width?, height?, ... }) | Embedded image |
.textBox(options) | Positioned Word text box |
.thematicBreak(opts?) | Horizontal thematic break |
.columnBreak() | Forced break to the next section column |
.pageBreak() | Forced page break |
.section(config?) | Start a new section |
.plugin(name, options, opts?) | Invoke registered plugin |
.use(plugin) | Register a plugin |
.add(node) | Add raw DSL node |
span() and inlineImg() Helpers
These create inline content nodes for use inside .p():
import { span, inlineImg } from 'docx-kit'
// span: creates a TextNode
doc.p([
span('Hello '),
span('world', { bold: true, color: '#e11d48' }),
span('!'),
])
// inlineImg: creates an inline ImageNode
doc.p([
span('Icon: '),
inlineImg({ data: iconDataUrl, width: 16, height: 16 }),
span(' done!'),
])Table Options
interface TableOptions<TData> {
columns: {
key: string
title: string
align?: 'left' | 'center' | 'right'
width?: UnitValue
cellStyle?: DocxStyleRule | TableCellStyleResolver<TData>
headerCellStyle?: DocxStyleRule
render?: (value: unknown, row: TData, index: number) => string | InlineNode[]
}[]
data: TData[]
alignment?: 'left' | 'center' | 'right'
bordered?: boolean
borders?: TableBordersConfig
floating?: TableFloatingOptions
striped?: boolean
header?: boolean
layout?: 'autofit' | 'fixed'
styleName?: string
tableLook?: TableLookOptions
visuallyRightToLeft?: boolean
width?: UnitValue
headerCellStyle?: DocxStyleRule
cellStyle?: DocxStyleRule | TableCellStyleResolver<TData>
}Floating positioning supports side-by-side tables by anchoring two fixed-width tables at different horizontal offsets:
doc
.table({
columns,
data: leftData,
layout: 'fixed',
width: '45%',
floating: { horizontalAnchor: 'page', x: '0.5in', y: '2in' },
})
.table({
columns,
data: rightData,
layout: 'fixed',
width: '45%',
floating: { horizontalAnchor: 'page', x: '4.25in', y: '2in' },
})Export Methods
import { createDocx } from 'docx-kit/node'
const doc = createDocx()
await doc.toBlob() // → Blob (browser & Node.js)
await doc.toUint8Array() // → Uint8Array
await doc.toBuffer() // → Uint8Array (alias)
await doc.toBase64() // → base64 string
await doc.toStream() // → Node.js stream (Node.js only)
await doc.save('f.docx') // → writes to disk (Node.js only)
await doc.toDocument() // → raw docx Document
doc.toJSON() // → shallow config/content view (inspection)toJSON() returns a shallow view of the config and content, not a lossless persistence format. It does not include plugins registered with .use(). Callbacks (including table renderers), binary inputs, and runtime adapters do not survive JSON stringify/parse unchanged. Store serializable schemas separately and register trusted plugins and adapters again before export.
renderDocx(schema, options?)
AI/LLM-friendly JSON entry point for document generation.
import { renderDocx } from 'docx-kit'
const doc = await renderDocx({
content: [
{ type: 'heading', level: 1, text: 'AI-Generated Report' },
{ type: 'paragraph', text: 'Generated from structured JSON.' },
{
type: 'table',
columns: [
{ key: 'name', title: 'Name' },
{ key: 'value', title: 'Value' },
],
data: [{ name: 'Foo', value: 'Bar' }],
},
],
styles: { accent: { color: '#2563eb', fontWeight: 'bold' } },
})
const blob = await doc.toBlob()The optional second argument is RenderDocxOptions, supported by core, browser, and Node entries. pluginLoader: false rejects external npm, local, and url sources before I/O; trusted in-process inline plugins remain supported. resolveImage: false disables image-path resolution. A custom loader or image resolver replaces the platform default. Existing one-argument calls keep their behavior.
DocxSchema<TStyles>
interface DocxSchema<TStyles extends StyleSheet = StyleSheet> {
content: BlockNode<TStyles>[]
page?: DocxKitConfig<TStyles>['page']
styles?: TStyles
plugins?: PluginSource[]
}