Create docx
Claude Code skills for developers
npx -y skills add MaskedControl/skills --skill create-docxAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when creating or generating a Word document (.docx) for a client, email, or report. Covers Windows setup, running docx-js scripts in a temp folder, cleanup, and formatting patterns (tables, bullets, callout boxes, screenshot placeholders). Triggers on requests like "create a Word doc", "generate a .docx", "make a report in Word", or "build a document for the client."
SKILL.md
8.5 KB, as published. Nobody here has run it
Create Word Documents (docx-js on Windows)
Overview
Word documents are generated by writing a JavaScript file that uses the docx npm package,
running it with Node, then cleaning up the temp files. The docx package must be installed
locally in the same folder as the script - global install does not work with require('docx').
The full docx-js API reference is in the example-skills:docx skill. Load it for syntax on
tables, images, headers/footers, tracked changes, and anything not covered here.
Process
1. Write the script
Write the JS file to a working location (e.g. Desktop). Output path should be absolute.
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
HeadingLevel, AlignmentType, LevelFormat, BorderStyle, WidthType,
ShadingType, VerticalAlign, PageBreak } = require('docx');
const fs = require('fs');
// ... build doc ...
Packer.toBuffer(doc).then(buf => {
fs.writeFileSync("C:/Users/rosem/Desktop/output.docx", buf);
console.log("Done");
}).catch(err => { console.error(err); process.exit(1); });
2. Install and run
cd C:/Users/rosem/Desktop
npm init -y
npm install docx
node build-doc.js
3. Clean up
Remove-Item -Recurse -Force build-doc.js, package.json, package-lock.json, node_modules
Windows Validation Caveat
The validate.py script from example-skills:docx throws a UnicodeEncodeError on Windows
consoles (cp1252 can't encode the arrow character it prints). This is a validator bug, not a
document problem. Skip validation - open the file in Word to verify instead.
Page Setup (Always Set Explicitly)
docx-js defaults to A4. Always override:
sections: [{
properties: {
page: {
size: { width: 12240, height: 15840 }, // US Letter
margin: { top: 1080, right: 1080, bottom: 1080, left: 1080 } // 0.75" margins
}
},
children: [...]
}]
// Content width = 12240 - (2 x 1080) = 10080 DXA
Numbering (Never Use Unicode Bullets Directly)
// Define once in Document
numbering: {
config: [
{ reference: "bullets", levels: [{ level: 0, format: LevelFormat.BULLET, text: "•",
alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
{ reference: "steps", levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.",
alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
]
}
// Use on paragraphs
new Paragraph({ numbering: { reference: "bullets", level: 0 }, children: [...] })
Use a separate reference for bullets inside table cells (avoids numbering continuation issues):
{ reference: "cell-bullets", levels: [{ level: 0, format: LevelFormat.BULLET, text: "•",
alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 360, hanging: 180 } } } }] }
Tables (Dual Widths Required)
Both columnWidths on the table AND width on each cell. They must match.
Always use WidthType.DXA - never WidthType.PERCENTAGE (breaks in Google Docs).
Always use ShadingType.CLEAR - never SOLID (causes black cell backgrounds).
const border = { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" };
const borders = { top: border, bottom: border, left: border, right: border };
const col1 = 5040, col2 = 5040; // must sum to content width (10080)
new Table({
width: { size: 10080, type: WidthType.DXA },
columnWidths: [col1, col2],
rows: [new TableRow({ children: [
new TableCell({
borders,
width: { size: col1, type: WidthType.DXA },
shading: { fill: "F0F0F0", type: ShadingType.CLEAR },
margins: { top: 80, bottom: 80, left: 120, right: 120 },
children: [new Paragraph({ children: [new TextRun("Cell content")] })]
}),
]})]
})
Screenshot Placeholder
For documents that will have screenshots inserted manually:
function screenshotBox(description) {
const br = { style: BorderStyle.SINGLE, size: 8, color: "999999" };
const borders = { top: br, bottom: br, left: br, right: br };
return new Table({
width: { size: 10080, type: WidthType.DXA },
columnWidths: [10080],
rows: [new TableRow({ children: [new TableCell({
borders,
width: { size: 10080, type: WidthType.DXA },
shading: { fill: "DEDEDE", type: ShadingType.CLEAR },
margins: { top: 280, bottom: 280, left: 280, right: 280 },
verticalAlign: VerticalAlign.CENTER,
children: [
new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 40, after: 60 },
children: [new TextRun({ text: "[ INSERT SCREENSHOT ]", font: "Arial",
size: 20, bold: true, color: "666666" })] }),
new Paragraph({ alignment: AlignmentType.CENTER,
children: [new TextRun({ text: description, font: "Arial",
size: 18, italics: true, color: "666666" })] })
]
})})]
});
}
Callout Box
Coloured border box with a bold title and bulleted lines:
function callout(title, lines, fill, borderColor) {
const br = { style: BorderStyle.SINGLE, size: 14, color: borderColor };
const borders = { top: br, bottom: br, left: br, right: br };
return new Table({
width: { size: 10080, type: WidthType.DXA },
columnWidths: [10080],
rows: [new TableRow({ children: [new TableCell({
borders,
width: { size: 10080, type: WidthType.DXA },
shading: { fill, type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 240, right: 240 },
children: [
new Paragraph({ spacing: { before: 40, after: 80 },
children: [new TextRun({ text: title, font: "Arial", size: 22, bold: true, color: "404040" })] }),
...lines.map(line => new Paragraph({
numbering: { reference: "cell-bullets", level: 0 },
spacing: { before: 40, after: 40 },
children: [new TextRun({ text: line, font: "Arial", size: 22, color: "404040" })]
}))
]
})})]
});
}
// Usage: callout("What to ask:", ["Question one", "Question two"], "FFF2CC", "FFC000")
Single-Cell Table Helper Pattern
Single-cell tables (code blocks, callout boxes, prompt boxes) follow this structure. The closing sequence is the most common source of syntax errors — get it wrong and Node throws Unexpected token '}'.
return new Table({
width: { size: CW, type: WidthType.DXA }, columnWidths: [CW],
rows: [new TableRow({ children: [new TableCell({ // opens: rows[, TableRow{, children[, TableCell{
borders, width: { size: CW, type: WidthType.DXA },
shading: { fill: "F4F4F4", type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [/* paragraphs */]
})]}) // closes: TableCell{, TableCell(, children[, TableRow{, TableRow(
] // closes: rows[
}); // closes: Table{, Table(
}
Closing sequence: } ) ] } ) then ] on next line, then });.
Never write })})] — it skips the ] that closes children:[ and crashes at parse time.
Common Mistakes
| Mistake | Fix |
|---|---|
require('docx') fails after npm install -g | Install locally: cd Desktop && npm init -y && npm install docx |
| Black table cell backgrounds | Use ShadingType.CLEAR not SOLID |
| Table renders incorrectly | Set columnWidths on table AND width on each cell, both in DXA |
WidthType.PERCENTAGE used | Switch to WidthType.DXA - percentage breaks in Google Docs |
| PageBreak causes invalid XML | Wrap it: new Paragraph({ children: [new PageBreak()] }) |
| Bullet shows as literal text | Never new TextRun("• item") - use numbering config |
| Em dashes (--) appear in Word | Do not use -- or — in content - rephrase the sentence instead |
| Validator crashes on Windows | Known encoding bug in validate.py - open in Word instead |
| node_modules left on Desktop | Always run cleanup step after generating |
SyntaxError: Unexpected token } in table helper | Missing ] to close children:[ of TableRow before closing } of TableRow args — use the single-cell table pattern above |