Executive Summary Formatter
Transform any executive summary content into a professionally formatted .docx document matching the brand template exactly.
Quick Start
- •Read the content from the user's input (text, markdown, or uploaded document)
- •Create a new document using docx-js with the specifications below
- •Apply all formatting rules precisely
- •Output to
/mnt/user-data/outputs/
Brand Specifications
Fonts
- •Primary Font: Work Sans (body text, tables, lists)
- •Light Variant: Work Sans Light (document title only - 48pt)
- •Fallback: Arial (if Work Sans unavailable)
Color Palette
| Element | Color Code | Usage |
|---|---|---|
| Section Headers | #DA291C (red) | Major section titles |
| Table Header BG | #032340 (navy) | Table header row background |
| Table Header Text | #FFFFFF (white) | Text in table headers |
| Body Text | #000000 (black) | Normal paragraph text |
| Subtitle/Caption | #808080 (gray) | Subtitle, secondary info |
| Table Borders (Data) | #CCCCCC (light gray) | Data row borders |
| Table Borders (Header) | #AAAAAA (medium gray) | Header row borders |
| Alternating Row BG | #F2F2F2 (very light gray) | Every other data row |
| Highlight Cell BG | #FFE3E3 (light pink) | Special emphasis cells |
| Hyperlink | #0563C1 (blue) | Links |
Typography Scale (half-points)
| Element | Size | Weight | Additional |
|---|---|---|---|
| Document Title | 48 (24pt) | Light | Work Sans Light, centered, NOT bold |
| Subtitle | 22 (11pt) | Regular | Italic, gray #808080, centered |
| Section Header (Large) | 48 (24pt) | Regular | Red #DA291C, NOT bold |
| Section Header (Small) | 28 (14pt) | Regular | Red #DA291C, NOT bold |
| Body Text | 22 (11pt) | Regular | Work Sans (inherited from defaults) |
| Table Header | 18 (9pt) | Bold | White on navy #032340 |
| Table Data | 18 (9pt) | Regular | Work Sans |
| Table Data (Small) | 16 (8pt) | Regular | Used in compact tables |
| Bullet Items | 22 (11pt) | Regular | Work Sans |
Spacing (in twips, 1440 = 1 inch)
| Element | Before | After |
|---|---|---|
| Document Title | 0 | 120 |
| Subtitle | 0 | 400 |
| Section Header (large) | 360 | 160 |
| Section Header (small) | 360 | 160 |
| Body Paragraph | 0 | 160 |
| Bullet Item | 0 | 120 |
| Table | 240 | 240 |
Page Layout
- •Page Size: A4 (11906 × 16838 twips)
- •Margins: 1440 twips (1 inch) all sides
- •Header Distance: 708 twips
- •Footer Distance: 708 twips
Document Structure
1. Title Block
[Document Title - Work Sans Light 24pt, centered] [Subtitle - Work Sans 11pt italic gray, centered] [Blank line]
2. Section Pattern
[Section Header - Work Sans 24pt or 14pt red] [Body paragraphs - Work Sans 11pt, 160 twips after] [Tables as needed] [Bullet lists as needed]
docx-js Implementation Patterns
The skill uses the docx npm package. Here are working patterns:
Required Imports
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
Header, Footer, AlignmentType, WidthType, BorderStyle,
ShadingType, VerticalAlign, PageNumber, ImageRun,
convertInchesToTwip
} = require('docx');
Table Creation - CRITICAL RULES
- •Always use percentage width for tables with explicit columnWidths:
const table = new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
borders: tableBorders,
columnWidths: [1800, 850, 850, 850, 850], // REQUIRED - specify explicit widths
rows: [...]
});
- •
Always specify
columnWidthsarray - Without this, columns will collapse or be uneven. This is the #1 cause of table rendering issues. - •
Define borders once and reuse:
const tableBorders = {
top: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
left: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
right: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
insideHorizontal: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
insideVertical: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" }
};
Column Width Calculation Guidelines
Total usable width for A4 with 1" margins: ~9300 DXA
| Content Type | Recommended Width (DXA) | Examples |
|---|---|---|
| Single character / dash | 700-850 | "—", "3", "4" |
| Percentage values | 800-900 | "40%", "65%" |
| Short text (1-3 words) | 1000-1400 | "Production", "Live 2024" |
| Medium text (4-8 words) | 1600-2200 | "Shape standard & preserve IP" |
| Long text (sentences) | 2800-4500 | Full descriptions |
| Row labels (first column) | 1600-2000 | Category names |
| Highlight columns | 1000-1200 | "CDM Relevance" values |
For multi-column tables (6+ columns):
- •Use abbreviated headers (e.g., "MS" not "Morgan Stanley", "BofA" not "Bank of America")
- •Keep data columns uniform width (800-900 DXA each)
- •Give first column extra width for row labels (1600-1800 DXA)
- •Verify total width sums to ~9300 DXA
Cell Shading for Alternating Rows
CRITICAL: Must include all three shading properties:
shading: {
fill: "F2F2F2", // The background color
type: ShadingType.CLEAR, // Required
color: "auto" // Required
}
Highlight Column Rules
CRITICAL: When a column uses highlight formatting (e.g., pink background for "CDM Relevance"), ALL cells in that column must use the highlight cell function, including empty cells:
// WRONG - leaves cell without highlight, breaks column consistency
createHighlightCell("", 1100)
// CORRECT - maintains column consistency with placeholder
createHighlightCell("—", 1100)
Multi-Paragraph Table Cells
For cells with multiple lines of content, pass an array:
createDataCell(["Line 1.", "Line 2."], width, isFirstCol, isAltRow)
// Implementation adds spacing between paragraphs:
const children = paragraphs.map((para, idx) => new Paragraph({
spacing: idx > 0 ? { before: 80 } : {},
children: [new TextRun({ text: para, ... })]
}));
Working Helper Functions
// Brand colors constant
const COLORS = {
RED_ACCENT: "DA291C",
NAVY_HEADER: "032340",
WHITE: "FFFFFF",
BLACK: "000000",
GRAY_SUBTITLE: "808080",
BORDER_LIGHT: "CCCCCC",
BORDER_HEADER: "AAAAAA",
ALT_ROW_GRAY: "F2F2F2",
HIGHLIGHT_PINK: "FFE3E3"
};
// Table header cell (navy background, white bold text)
function createHeaderCell(text, width) {
return new TableCell({
width: { size: width, type: WidthType.DXA },
shading: { fill: COLORS.NAVY_HEADER, type: ShadingType.CLEAR, color: "auto" },
verticalAlign: VerticalAlign.CENTER,
margins: {
top: convertInchesToTwip(0.03),
bottom: convertInchesToTwip(0.03),
left: convertInchesToTwip(0.06),
right: convertInchesToTwip(0.06)
},
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({
text,
bold: true,
color: COLORS.WHITE,
size: 18,
font: "Work Sans"
})]
})]
});
}
// Data cell with alternating row support
function createDataCell(content, width, isFirstCol = false, isAlternateRow = false, centered = false) {
const paragraphs = Array.isArray(content) ? content : [content];
const children = paragraphs.map((para, idx) => new Paragraph({
alignment: centered ? AlignmentType.CENTER : AlignmentType.LEFT,
spacing: idx > 0 ? { before: 80 } : {},
children: [new TextRun({
text: para,
bold: isFirstCol,
size: 18,
font: "Work Sans"
})]
}));
const cell = new TableCell({
width: { size: width, type: WidthType.DXA },
verticalAlign: VerticalAlign.CENTER,
margins: {
top: convertInchesToTwip(0.04),
bottom: convertInchesToTwip(0.04),
left: convertInchesToTwip(0.06),
right: convertInchesToTwip(0.06)
},
shading: isAlternateRow ? { fill: COLORS.ALT_ROW_GRAY, type: ShadingType.CLEAR, color: "auto" } : undefined,
children: children
});
return cell;
}
// Highlight cell (pink background) - use for special emphasis columns
function createHighlightCell(text, width) {
return new TableCell({
width: { size: width, type: WidthType.DXA },
shading: { fill: COLORS.HIGHLIGHT_PINK, type: ShadingType.CLEAR, color: "auto" },
verticalAlign: VerticalAlign.CENTER,
margins: {
top: convertInchesToTwip(0.03),
bottom: convertInchesToTwip(0.03),
left: convertInchesToTwip(0.02),
right: convertInchesToTwip(0.02)
},
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({
text: text || "—", // Always use placeholder for empty cells
bold: true,
color: COLORS.BLACK,
size: 16,
font: "Work Sans"
})]
})]
});
}
Table Formatting
Table Structure
// Table width: 100% with explicit columnWidths // Cell margins (header): top 0.03", left 0.06", bottom 0.03", right 0.06" // Cell margins (data): top 0.04", left 0.06", bottom 0.04", right 0.06" // Cell margins (highlight): top 0.03", left 0.02", bottom 0.03", right 0.02"
Header Row
- •Background: #032340 (navy)
- •Text: White (#FFFFFF), Bold, 9pt (18 half-pts), centered
- •Borders: 4pt #CCCCCC
- •Vertical align: center
Data Rows - Alternating Colors
- •Odd rows (1, 3, 5...): No fill (white background)
- •Even rows (2, 4, 6...): Fill #F2F2F2 (light gray) with type: CLEAR, color: auto
- •Text: Black, Regular, 9pt (18 half-pts)
- •Borders: 4pt #CCCCCC
- •First column: Bold (archetype/category names)
- •Vertical align: center
Special Highlight Cells
- •Background: #FFE3E3 (light pink) with type: CLEAR, color: auto
- •Used for emphasis columns like "CDM Relevance"
- •Text: Bold, centered, 8pt (16 half-pts)
- •Apply to ALL cells in highlight column, use "—" for empty
Bullet List Formatting
- •Style: Symbol bullet (â—)
- •Indent: 360 twips left
- •Spacing: 120 twips after each item
- •Font: Work Sans 11pt
Header/Footer
Header
- •Graphic bar spanning full page width at top
- •Uses
assets/media/image2.svgorimage1.png(decorative header bar) - •Position: anchored to page, offset from top
Footer
- •Centered page numbering: "Page X of Y"
- •Logo in right margin (
assets/media/image3.png) - •Font: Default (Arial 11pt)
Pre-Delivery Checklist
Before outputting the document, verify:
- • All tables have
columnWidthsarray specified - • Column widths sum to approximately 9300 DXA for A4
- • Highlight columns have styling on ALL cells (no empty unstyled cells)
- • Empty highlight cells use "—" placeholder
- • Alternating row shading includes
type: ShadingType.CLEAR, color: "auto" - • Long text content has adequate column width (2500+ DXA)
- • Multi-column tables (6+) use abbreviated headers
- • First column has adequate width for row labels (1600+ DXA)
Workflow
- •Parse Input: Extract text content, identify structure (titles, sections, tables, bullets)
- •Analyze Tables: Count columns, estimate content length, calculate widths
- •Map to Template: Match content to template elements
- •Build Document: Use docx-js with exact specifications above
- •Add Header/Footer: Include branded graphics from
assets/media/ - •Validate: Run through pre-delivery checklist
- •Export: Save as .docx to outputs directory
Assets
The skill includes these brand assets in assets/media/:
- •
image1.png- Header bar / Footer logo (fallback) - •
image2.svg- Header decorative bar - •
image3.png- Footer logo
Critical Rules
- •ALWAYS use Work Sans font family (Light variant for title only - NOT BOLD)
- •ALWAYS use exact color codes - no approximations
- •ALWAYS apply precise spacing - before/after values in twips
- •Table headers MUST be navy #032340 with white bold text
- •Section headers MUST be red #DA291C - NOT bold
- •Alternating table rows: white, then #F2F2F2 (light gray)
- •Never use default Word styles - apply custom formatting explicitly
- •Preserve content hierarchy - don't flatten structure
- •ALWAYS specify columnWidths for tables - this is required for proper rendering
- •Highlight columns: style ALL cells including empty ones (use "—")
- •Multi-paragraph table cells use spacing before: 80 twips for 2nd+ paragraphs
- •Body text inherits 11pt from document defaults - don't set explicitly unless overriding
Common Issues and Solutions
| Issue | Cause | Solution |
|---|---|---|
| Tables collapse/render incorrectly | Missing columnWidths | Always specify columnWidths array |
| Uneven column spacing | Widths don't match content | Use width guidelines by content type |
| Missing highlight on cells | Empty cell = no styling applied | Use "—" placeholder with highlight styling |
| Alternating rows not showing | Incomplete shading object | Include fill, type: CLEAR, and color: auto |
| Text overflow in cells | Column too narrow | Increase width, abbreviate headers if needed |