| name | DOCX Writer |
| description | Use this skill when the user asks to create, generate, export, or write Word documents such as .docx reports, proposals, contracts, SOPs, memos, letters, templates, formatted business documents, or documents with headings/tables/lists/headers/footers. Triggers on phrases like create Word doc, generate DOCX, export as Word, write proposal, make report, write contract, SOP document, memo, letter, create template, and formatted document. Use it to produce professional editable DOCX files with the docx npm package and safe formatting rules. |
| emoji | 📝 |
| version | 1.1.0 |
| triggers | create word doc, write proposal, generate docx, make report, write contract, SOP, memo, letter, create template, export word, word document, professional document, business document, formatted document, report with tables |
DOCX Writer
Create professional Word documents using the docx npm package. Pure Node — no Python, no LibreOffice.
DEPENDENCY CHECK — Run First Time Only
node -e "require('docx'); console.log('OK')"
Run from D:\Prometheus. If it fails: node workspace\doc-skills-setup.js
How It Works
Write a Node script to the workspace, run it, the script outputs a .docx file to the workspace. The pattern is always the same:
- Write
_tmp_docwrite.js to workspace/
- Run:
shell({ command: "node _tmp_docwrite.js", cwd: "D:\\Prometheus\\workspace" })
- Tell user the file is at
workspace/[filename].docx
- Clean up the temp script
Core Setup — Always Include These Imports
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
Header, Footer, AlignmentType, HeadingLevel, BorderStyle,
WidthType, ShadingType, VerticalAlign, PageNumber, PageBreak,
LevelFormat, TabStopType, TabStopPosition
} = require('../node_modules/docx');
const fs = require('fs');
Page Setup — Always Explicit
const pageProps = {
page: {
size: { width: 12240, height: 15840 },
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }
}
};
Style Setup — Always Define These
const styles = {
default: {
document: { run: { font: 'Arial', size: 24 } }
},
paragraphStyles: [
{
id: 'Heading1', name: 'Heading 1', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 36, bold: true, font: 'Arial', color: '1a1a2e' },
paragraph: { spacing: { before: 360, after: 120 }, outlineLevel: 0 }
},
{
id: 'Heading2', name: 'Heading 2', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 28, bold: true, font: 'Arial', color: '16213e' },
paragraph: { : { : , : }, : }
},
{
: , : , : , : , : ,
: { : , : , : , : },
: { : { : , : }, : }
}
]
};
Paragraph Patterns
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun('Section Title')] })
new Paragraph({ heading: HeadingLevel.HEADING_2, children: [new TextRun('Subsection')] })
new Paragraph({
children: [new TextRun({ text: 'Body text here.', size: 24, font: 'Arial' })],
spacing: { after: 120 }
})
new Paragraph({
children: [
new TextRun({ text: 'Key term: ', bold: true, size: 24, font: 'Arial' }),
new TextRun({ text: 'explanation text.', size: 24, font: })
]
})
({
: { : { : ., : , : , : } },
: { : }
})
({ : [ ()] })
Lists — NEVER Use Unicode Bullets
const numbering = {
config: [
{
reference: 'bullets',
levels: [{
level: 0, format: LevelFormat.BULLET, text: '•', alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } }
}]
},
{
reference: 'numbers',
levels: [{
level: 0, format: LevelFormat.DECIMAL, text: '%1.', alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } }
}]
}
]
};
new Paragraph({
numbering: { reference: 'bullets', level: 0 },
children: [new ({ : , : , : })]
})
({
: { : , : },
: [ ({ : , : , : })]
})
Tables
const border = { style: BorderStyle.SINGLE, size: 4, color: 'cccccc' };
const cellBorders = { top: border, bottom: border, left: border, right: border };
new Table({
width: { size: 9360, type: WidthType.DXA },
columnWidths: [3120, 3120, 3120],
rows: [
new TableRow({
tableHeader: true,
children: ['Column A', 'Column B', 'Column C'].map(text =>
new TableCell({
borders: cellBorders,
width: { size: 3120, type: WidthType.DXA },
shading: { fill: 'dce6f1', : . },
: { : , : , : , : },
: [ ({ : [ ({ text, : , : , : })] })]
})
)
}),
({
: [, , ].(
({
: cellBorders,
: { : , : . },
: { : , : , : , : },
: [ ({ : [ ({ text, : , : })] })]
})
)
})
]
})
Header and Footer
const header = new Header({
children: [
new Paragraph({
children: [
new TextRun({ text: 'Document Title', bold: true, size: 20, font: 'Arial', color: '555555' })
],
border: { bottom: { style: BorderStyle.SINGLE, size: 4, color: 'cccccc', space: 1 } }
})
]
});
const footer = new Footer({
children: [
new Paragraph({
children: [
new TextRun({ text: 'Page ', size: 18, font: 'Arial', color: '888888' }),
new TextRun({ children: [PageNumber.CURRENT], size: 18, font: , : }),
({ : , : , : , : }),
({ : [.], : , : , : })
],
: .
})
]
});
Full Document Template
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
Header, Footer, AlignmentType, HeadingLevel, BorderStyle,
WidthType, ShadingType, PageNumber, PageBreak, LevelFormat
} = require('../node_modules/docx');
const fs = require('fs');
const doc = new Document({
numbering: {
config: [
{ reference: 'bullets', levels: [{ level: 0, format: LevelFormat.BULLET, text: '•', alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
{ reference: 'numbers', levels: [{ level: , : ., : , : ., : { : { : { : , : } } } }] }
]
},
: {
: { : { : { : , : } } },
: [
{ : , : , : , : , : , : { : , : , : }, : { : { : , : }, : } },
{ : , : , : , : , : , : { : , : , : }, : { : { : , : }, : } }
]
},
: [{
: {
: { : { : , : }, : { : , : , : , : } }
},
: { : ({ : [ ({ : [ ({ : , : , : , : , : })] })] }) },
: { : ({ : [ ({ : ., : [ ({ : , : , : }), ({ : [.], : , : })] })] }) },
: [
({ : ., : [ ()] }),
({ : [ ({ : , : , : })], : { : } }),
({ : ., : [ ()] }),
({ : { : , : }, : [ ({ : , : , : })] }),
({ : { : , : }, : [ ({ : , : , : })] }),
]
}]
});
.(doc).( {
outPath = ;
fs.(outPath, buffer);
.(, outPath);
}).( { .(, e.); process.(); });
Critical Rules
- Never use
\n in TextRun — use separate Paragraph elements
- Never use unicode bullets (
•, \u2022) — use LevelFormat.BULLET with numbering config
- Always set table width with DXA — never use WidthType.PERCENTAGE (breaks in Google Docs)
- Tables need dual widths —
columnWidths array on the table AND width on every cell
- columnWidths must sum exactly to the table width
- Always set
ShadingType.CLEAR — never SOLID for cell shading (causes black background)
- Never use a table as a horizontal rule/divider — use paragraph border instead
- PageBreak must be inside a Paragraph — standalone PageBreak creates invalid XML
Output Location
Save files to D:\Prometheus\workspace\ so the user can access them. Tell the user the exact path.