From napa-doc-suite
NAPA-branded Word document builder using python-docx with consistent brand standards. Use when the user asks to "create a document", "write a report", "draft a memo", "generate a Word file", "create a docx", "write a proposal", "create a design doc", "write a charter", or any Word document request. This skill replaces the generic Anthropic docx skill for all NAPA work.
npx claudepluginhub chadronbryant/napa-cowork-plugins --plugin napa-doc-suiteThis skill uses the workspace's default tool permissions.
Create professional Word documents with NAPA brand compliance using python-docx.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Create professional Word documents with NAPA brand compliance using python-docx.
brand-standards skill for colors, fonts, and tonereferences/template-catalog.md for document concept templates| Concept | Use When | Key Sections |
|---|---|---|
| Project Charter | Starting a new project/initiative | Purpose, Scope, Objectives, Stakeholders, Timeline, Risks |
| Design Document | Technical or process design decisions | Problem, Proposed Solution, Alternatives, Implementation Plan |
| Solution Proposal | Recommending a specific approach | Executive Summary, Current State, Proposed Solution, ROI |
| Technical Plan | Detailed technical implementation | Architecture, Dependencies, Milestones, Testing Strategy |
| Executive Summary | High-level overview for leadership | Situation, Analysis, Recommendation, Next Steps |
| Status Report | Periodic progress updates | Accomplishments, In Progress, Blockers, Next Period |
| Process Guide (VSOP) | Visual step-by-step instructions | Overview, Prerequisites, Steps (with screenshots), Troubleshooting |
| Analysis Report | Data-driven findings for stakeholders | Executive Summary, Data Inventory, Analysis, Recommendations, Appendix |
| Meeting Summary | Post-meeting documentation | Attendees, Key Decisions, Action Items, Next Meeting |
| Release Notes | Communicating changes | Version, New Features, Bug Fixes, Known Issues |
from docx import Document
from docx.shared import Pt, Inches, RGBColor, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
# ── Brand Constants ──
FONT = "Arial"
BODY_SIZE = Pt(12) # 12pt body (NEVER 11pt)
TABLE_SIZE = Pt(10) # 10pt in table cells
SMALL_SIZE = Pt(10) # 10pt for captions/metadata
H1_SIZE = Pt(18)
H2_SIZE = Pt(15)
H3_SIZE = Pt(13)
NAPA_BLUE = RGBColor(0x00, 0x51, 0x95)
DARK_BLUE = RGBColor(0x00, 0x33, 0x66)
ORANGE = RGBColor(0xFF, 0xA3, 0x00)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
GRAY = RGBColor(0x66, 0x66, 0x66)
BODY_COLOR = RGBColor(0x33, 0x33, 0x33)
RED = RGBColor(0xCC, 0x00, 0x00)
GREEN = RGBColor(0x2E, 0x8B, 0x57)
doc = Document()
# Default font: Arial 12pt
style = doc.styles['Normal']
style.font.name = 'Arial'
style.font.size = Pt(12)
style.font.color.rgb = RGBColor(0x33, 0x33, 0x33)
# Heading styles: NAPA Blue, bold
for level, size in [(1, 18), (2, 15), (3, 13)]:
h = doc.styles[f'Heading {level}']
h.font.name = 'Arial'
h.font.size = Pt(size)
h.font.color.rgb = RGBColor(0x00, 0x51, 0x95)
h.font.bold = True
# Narrow margins
for section in doc.sections:
section.top_margin = Inches(0.75)
section.bottom_margin = Inches(0.75)
section.left_margin = Inches(1.0)
section.right_margin = Inches(1.0)
def add_body(doc, text, bold=False, size=BODY_SIZE, color=BODY_COLOR):
"""Add a body paragraph."""
p = doc.add_paragraph()
run = p.add_run(text)
run.font.size = size
run.font.bold = bold
run.font.color.rgb = color
run.font.name = FONT
return p
def add_bullet(doc, text, size=BODY_SIZE):
"""Add a bulleted list item."""
p = doc.add_paragraph(style='List Bullet')
p.clear()
run = p.add_run(text)
run.font.size = size
run.font.name = FONT
run.font.color.rgb = BODY_COLOR
return p
def add_title_block(doc, title, subtitle=None, date=None):
"""Add NAPA-branded title block."""
p = doc.add_paragraph()
run = p.add_run(title)
run.font.size = Pt(28)
run.font.bold = True
run.font.color.rgb = NAPA_BLUE
run.font.name = FONT
if subtitle:
p2 = doc.add_paragraph()
run2 = p2.add_run(subtitle)
run2.font.size = Pt(13)
run2.font.color.rgb = GRAY
run2.font.name = FONT
if date:
p3 = doc.add_paragraph()
run3 = p3.add_run(date)
run3.font.size = SMALL_SIZE
run3.font.color.rgb = RGBColor(0x99, 0x99, 0x99)
run3.font.name = FONT
doc.add_paragraph() # spacer
NEVER use solid-color background callouts. Always use the left-border approach below.
def add_callout(doc, text, style='info'):
"""Add a left-border callout box.
Styles: 'info' (blue), 'warning' (orange), 'success' (green).
"""
p = doc.add_paragraph()
pPr = p._element.get_or_add_pPr()
# Thick left border
pBdr = OxmlElement('w:pBdr')
left = OxmlElement('w:left')
border_colors = {'info': '005195', 'warning': 'FFA300', 'success': '2E8B57'}
left.set(qn('w:val'), 'single')
left.set(qn('w:sz'), '24') # thick
left.set(qn('w:space'), '8')
left.set(qn('w:color'), border_colors.get(style, '005195'))
pBdr.append(left)
pPr.append(pBdr)
# Light background fill
bg_colors = {'info': 'E8F0FE', 'warning': 'FFF3E0', 'success': 'E8F5E9'}
shd = OxmlElement('w:shd')
shd.set(qn('w:fill'), bg_colors.get(style, 'E8F0FE'))
shd.set(qn('w:val'), 'clear')
pPr.append(shd)
# Left indent
ind = OxmlElement('w:ind')
ind.set(qn('w:left'), '360')
pPr.append(ind)
# Text
text_colors = {
'info': DARK_BLUE,
'warning': BODY_COLOR,
'success': BODY_COLOR
}
run = p.add_run(text)
run.font.size = BODY_SIZE
run.font.name = FONT
run.font.color.rgb = text_colors.get(style, BODY_COLOR)
return p
def shade_cell(cell, color_hex):
"""Apply background fill to a table cell."""
tc_pr = cell._element.get_or_add_tcPr()
shd = OxmlElement('w:shd')
shd.set(qn('w:fill'), color_hex)
shd.set(qn('w:val'), 'clear')
tc_pr.append(shd)
def set_cell_font(cell, size=TABLE_SIZE, bold=False, color=BODY_COLOR):
"""Set font properties on all runs in a cell."""
for p in cell.paragraphs:
for run in p.runs:
run.font.size = size
run.font.bold = bold
run.font.color.rgb = color
run.font.name = FONT
def add_napa_table(doc, headers, rows, col_widths=None):
"""Add NAPA-branded table: blue header, alternating gray rows."""
table = doc.add_table(rows=1 + len(rows), cols=len(headers))
table.alignment = WD_TABLE_ALIGNMENT.CENTER
table.style = 'Table Grid'
# Header row
for i, h in enumerate(headers):
cell = table.rows[0].cells[i]
cell.text = h
shade_cell(cell, '005195')
set_cell_font(cell, bold=True, color=WHITE)
# Data rows
for r, row_data in enumerate(rows):
for c, val in enumerate(row_data):
cell = table.rows[r + 1].cells[c]
cell.text = str(val)
set_cell_font(cell)
if r % 2 == 1:
shade_cell(cell, 'F5F5F5')
if col_widths:
for i, w in enumerate(col_widths):
for row in table.rows:
row.cells[i].width = Inches(w)
doc.add_paragraph() # spacer after table
return table
def add_hyperlink(paragraph, url, text, color=NAPA_BLUE, font_size=TABLE_SIZE):
"""Add a clickable hyperlink to an existing paragraph."""
part = paragraph.part
r_id = part.relate_to(
url,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
is_external=True
)
hyperlink = OxmlElement('w:hyperlink')
hyperlink.set(qn('r:id'), r_id)
new_run = OxmlElement('w:r')
rPr = OxmlElement('w:rPr')
# Color
c_elem = OxmlElement('w:color')
c_elem.set(qn('w:val'), f'{color.red:02X}{color.green:02X}{color.blue:02X}')
rPr.append(c_elem)
# Underline
u_elem = OxmlElement('w:u')
u_elem.set(qn('w:val'), 'single')
rPr.append(u_elem)
# Font size
sz_elem = OxmlElement('w:sz')
sz_elem.set(qn('w:val'), str(int(font_size.pt * 2)))
rPr.append(sz_elem)
# Font family
rFonts = OxmlElement('w:rFonts')
rFonts.set(qn('w:ascii'), FONT)
rFonts.set(qn('w:hAnsi'), FONT)
rPr.append(rFonts)
new_run.append(rPr)
new_run.text = text
hyperlink.append(new_run)
paragraph._element.append(hyperlink)
return hyperlink
def hr(doc):
"""Add a NAPA Blue horizontal rule."""
p = doc.add_paragraph()
pPr = p._element.get_or_add_pPr()
pBdr = OxmlElement('w:pBdr')
bottom = OxmlElement('w:bottom')
bottom.set(qn('w:val'), 'single')
bottom.set(qn('w:sz'), '6')
bottom.set(qn('w:space'), '1')
bottom.set(qn('w:color'), '005195')
pBdr.append(bottom)
pPr.append(pBdr)
To use a concept from the template library:
references/template-catalog.md for the document typeadd_hyperlink() for clickable references (NAPA Blue, underlined)v2.0.0 (2026-03-03)
add_hyperlink() helper for clickable links in documentshr() helper for horizontal rulesshade_cell() and set_cell_font() table helpersadd_body() and add_bullet() text helpersv1.0.0 (2026-02-16)