# How to Create New DOCX Documents Using docx-js: A Complete Guide

> Easily generate new DOCX documents server-side with docx-js. This guide covers setup, construction, and export for creating Word files efficiently.

- Repository: [Composio/awesome-claude-skills](https://github.com/composiohq/awesome-claude-skills)
- Tags: how-to-guide
- Published: 2026-07-24

---

**The docx-js skill in the ComposioHQ/awesome-claude-skills repository provides a production-ready wrapper around the docx JavaScript library, enabling server-side generation of Word-compatible .docx files through a three-layer architecture of setup, document construction, and export.**

Creating new DOCX documents using docx-js within the ComposioHQ/awesome-claude-skills ecosystem requires understanding its structured API patterns. This skill leverages the open-source docx library to generate complex Word documents entirely in Node.js or the browser, supporting professional formatting, tables, images, and Table of Contents generation according to the specifications in [`document-skills/docx/docx-js.md`](https://github.com/ComposioHQ/awesome-claude-skills/blob/main/document-skills/docx/docx-js.md).

## Three-Layer Architecture

The docx-js skill implements a structured approach to document generation consisting of three distinct layers.

### Setup Layer

Install the dependency globally to ensure availability across the project. The skill expects the `docx` package to be installed via npm and all required classes to be imported in a single destructured `require` statement.

```bash
npm install -g docx

```

```javascript
const {
    Document, Packer, Paragraph, TextRun,
    HeadingLevel, AlignmentType, PageBreak,
    Table, TableRow, TableCell, WidthType, BorderStyle,
    Numbering, LevelFormat, ImageRun, Header, Footer,
    PageNumber, PageOrientation, TableOfContents,
    ExternalHyperlink, InternalHyperlink
} = require('docx');

```

### Document Construction Layer

Documents are built from a **Document** object containing one or more sections. Each section houses an array of children—Paragraphs, Tables, Images, and other elements—that form the document content.

```javascript
const doc = new Document({
    sections: [{
        properties: {
            page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } }
        },
        children: [
            // Content elements go here
        ]
    }]
});

```

### Export Layer

The **Packer** class serializes the in-memory `Document` into a Buffer (Node.js) or Blob (browser). This binary data is then written to disk or offered for download.

```javascript
Packer.toBuffer(doc).then(buffer => {
    fs.writeFileSync("MyDocument.docx", buffer);
});

```

## Document Structure and Content

Creating rich DOCX documents requires precise construction of content elements. The docx-js skill enforces specific patterns for text, headings, and structural elements.

### Paragraphs and TextRuns

**TextRun** objects contain the actual text content, while **Paragraph** elements wrap them and control alignment, spacing, and list properties. According to the source code in [`document-skills/docx/docx-js.md`](https://github.com/ComposioHQ/awesome-claude-skills/blob/main/document-skills/docx/docx-js.md), you must never embed newline characters (`\n`) inside a `TextRun`. Each line break requires a separate `Paragraph` instance.

```javascript
// Correct: Multiple paragraphs for line breaks
new Paragraph({ children: [new TextRun("First line")] }),
new Paragraph({ children: [new TextRun("Second line")] })

// Incorrect: Newline inside TextRun (creates malformed XML)
new TextRun({ text: "Line 1\nLine 2" })

```

### Headings and Styles

To ensure Table of Contents functionality works correctly, override built-in heading styles using exact IDs (`Heading1`, `Heading2`, etc.) and set the `outlineLevel` property. The document-level styles configuration defines default fonts and custom paragraph styles.

```javascript
const doc = new Document({
    styles: {
        default: { document: { run: { font: "Arial", size: 24 } } },
        paragraphStyles: [
            { 
                id: "Heading1", 
                name: "Heading 1", 
                basedOn: "Normal",
                run: { size: 32, bold: true },
                paragraph: { outlineLevel: 0, spacing: { before: 240, after: 240 } }
            }
        ]
    },
    sections: [{
        children: [
            new Paragraph({
                heading: HeadingLevel.HEADING_1,
                children: [new TextRun("Introduction")]
            })
        ]
    }]
});

```

## Lists, Tables, and Images

Complex document elements require specific configuration objects to render correctly in Microsoft Word.

### Configuring Lists

Numbered and bulleted lists must be defined via the `numbering` configuration in the Document constructor. Unicode bullet characters are ignored by Word; instead, reference a defined numbering style.

```javascript
const doc = new Document({
    numbering: {
        config: [
            {
                reference: "bullet-list",
                levels: [{
                    level: 0,
                    format: LevelFormat.BULLET,
                    text: "•",
                    style: { paragraph: { indent: { left: 720, hanging: 360 } } }
                }]
            }
        ]
    },
    sections: [{
        children: [
            new Paragraph({
                numbering: { reference: "bullet-list", level: 0 },
                children: [new TextRun("First bullet")]
            })
        ]
    }]
});

```

### Building Tables

Tables require both a `columnWidths` array at the table level and a `width` object on each **TableCell**. Cell borders are applied per-cell, not per-table, requiring explicit border definitions for each side.

```javascript
new Table({
    columnWidths: [4680, 4680],
    rows: [
        new TableRow({
            children: [
                new TableCell({
                    width: { size: 4680, type: WidthType.DXA },
                    borders: {
                        top: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                        bottom: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                        left: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                        right: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }
                    },
                    shading: { fill: "D5E8F0", type: "clear" },
                    children: [new Paragraph({ children: [new TextRun({ text: "Header", bold: true })] })]
                }),
                // Additional cells...
            ]
        })
    ]
})

```

### Inserting Images

Images must include a mandatory `type` field specifying the format (`png`, `jpg`, etc.) and a fully populated `altText` object containing `title`, `description`, and `name` properties.

```javascript
new Paragraph({
    alignment: AlignmentType.CENTER,
    children: [
        new ImageRun({
            type: "png",
            data: fs.readFileSync("logo.png"),
            transformation: { width: 150, height: 100 },
            altText: { 
                title: "Company Logo", 
                description: "Logo of the company", 
                name: "logo" 
            }
        })
    ]
})

```

## Page Breaks and Table of Contents

**Page breaks** must be wrapped in a `Paragraph` element. A bare `PageBreak()` produces malformed XML that Word cannot open. Similarly, a **TableOfContents** relies on properly configured heading styles with `outlineLevel` settings to generate correctly.

```javascript
// Correct page break implementation
new Paragraph({ children: [new PageBreak()] }),

// Table of Contents (requires HeadingLevel usage in document)
new TableOfContents("Table of Contents", {
    hyperlink: true,
    headingStyleRange: "1-3"
})

```

## Complete Implementation Example

The following example from [`document-skills/docx/docx-js.md`](https://github.com/ComposioHQ/awesome-claude-skills/blob/main/document-skills/docx/docx-js.md) demonstrates the complete workflow combining styles, headings, formatted text, lists, tables, images, and a Table of Contents:

```javascript
const fs = require('fs');
const {
    Document, Packer, Paragraph, TextRun,
    HeadingLevel, AlignmentType, PageBreak,
    Table, TableRow, TableCell, WidthType, BorderStyle,
    LevelFormat, ImageRun, TableOfContents
} = require('docx');

const doc = new Document({
    styles: {
        default: { document: { run: { font: "Arial", size: 24 } } },
        paragraphStyles: [
            { id: "Title", name: "Title", basedOn: "Normal",
              run: { size: 56, bold: true },
              paragraph: { spacing: { before: 240, after: 120 }, alignment: AlignmentType.CENTER } },
            { id: "Heading1", name: "Heading 1", basedOn: "Normal",
              run: { size: 32, bold: true },
              paragraph: { outlineLevel: 0, spacing: { before: 240, after: 240 } } }
        ]
    },
    sections: [{
        properties: {
            page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } }
        },
        children: [
            new Paragraph({
                heading: HeadingLevel.TITLE,
                children: [new TextRun("My First DOCX Document")]
            }),
            new Paragraph({
                heading: HeadingLevel.HEADING_1,
                children: [new TextRun("Introduction")]
            }),
            new Paragraph({
                alignment: AlignmentType.JUSTIFY,
                children: [
                    new TextRun({ text: "Bold text", bold: true }),
                    new TextRun({ text: " – normal text – " }),
                    new TextRun({ text: "Red underline", underline: { type: "single", color: "FF0000" }, color: "FF0000" })
                ]
            }),
            new Paragraph({ children: [new PageBreak()] }),
            new Paragraph({
                numbering: { reference: "bullet-list", level: 0 },
                children: [new TextRun("First bullet")]
            }),
            new Table({
                columnWidths: [4680, 4680],
                rows: [
                    new TableRow({
                        tableHeader: true,
                        children: [
                            new TableCell({
                                width: { size: 4680, type: WidthType.DXA },
                                borders: { top: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                                           bottom: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                                           left: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                                           right: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" } },
                                shading: { fill: "D5E8F0", type: "clear" },
                                children: [new Paragraph({ children: [new TextRun({ text: "Header", bold: true })] })]
                            }),
                            new TableCell({
                                width: { size: 4680, type: WidthType.DXA },
                                borders: { top: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                                           bottom: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                                           left: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" },
                                           right: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" } },
                                shading: { fill: "D5E8F0", type: "clear" },
                                children: [new Paragraph({ children: [new TextRun({ text: "Data" })] })]
                            })
                        ]
                    })
                ]
            }),
            new Paragraph({
                alignment: AlignmentType.CENTER,
                children: [
                    new ImageRun({
                        type: "png",
                        data: fs.readFileSync("logo.png"),
                        transformation: { width: 150, height: 100 },
                        altText: { title: "Company Logo", description: "Logo of the company", name: "logo" }
                    })
                ]
            }),
            new TableOfContents("Table of Contents", {
                hyperlink: true,
                headingStyleRange: "1-3"
            })
        ]
    }]
});

Packer.toBuffer(doc).then(buffer => {
    fs.writeFileSync("MyDocument.docx", buffer);
    console.log("Document created → MyDocument.docx");
});

```

## Key Source Files

The docx-js implementation references several critical files in the repository:

- **[`document-skills/docx/docx-js.md`](https://github.com/ComposioHQ/awesome-claude-skills/blob/main/document-skills/docx/docx-js.md)**: Complete API reference and best-practice checklist
- **[`document-skills/docx/SKILL.md`](https://github.com/ComposioHQ/awesome-claude-skills/blob/main/document-skills/docx/SKILL.md)**: High-level skill description and use case guidelines  
- **[`document-skills/docx/ooxml.md`](https://github.com/ComposioHQ/awesome-claude-skills/blob/main/document-skills/docx/ooxml.md)**: Documentation for unpacking and validating existing .docx files

## Summary

- The **docx-js** skill uses a three-layer architecture: setup (npm install), construction (Document/Section/Children), and export (Packer.toBuffer)
- **Never use `\n`** inside TextRun objects; create separate Paragraph instances for line breaks
- **Tables** require `columnWidths` at the table level and `width` objects with per-cell BorderStyle definitions
- **Images** must include `type` and complete `altText` objects to pass Word validation
- **Page breaks** must be wrapped in Paragraph elements, not used standalone
- **Tables of Contents** require `outlineLevel` configuration in paragraph styles to populate correctly

## Frequently Asked Questions

### How do I install docx-js for use with Claude skills?

Install the `docx` package globally using `npm install -g docx`, then import all required classes (Document, Packer, Paragraph, TextRun, etc.) via `require('docx')` at the top of your skill file. The awesome-claude-skills repository expects this global installation pattern for the document generation skills.

### Why are my Unicode bullets not rendering in the generated DOCX file?

Microsoft Word ignores Unicode bullet characters in favor of structured numbering definitions. You must define bulleted lists using the `numbering` configuration in the Document constructor, referencing a LevelFormat.BULLET style, then apply that reference to Paragraph elements via the `numbering` property.

### What causes malformed XML errors when adding page breaks?

Passing a bare `PageBreak()` object without wrapping it in a Paragraph produces invalid XML that Word cannot parse. Always wrap page breaks in a Paragraph constructor: `new Paragraph({ children: [new PageBreak()] })`.

### How do I ensure the Table of Contents populates correctly?

The TableOfContents element requires properly configured heading styles with explicit `outlineLevel` values (0 for Heading 1, 1 for Heading 2, etc.). Use the exact style IDs `Heading1`, `Heading2`, etc., and ensure your sections use `HeadingLevel.HEADING_1` and similar constants rather than plain text styling.