Design and edit professional PDF reports and proposals with local HTML/PDF generation, iterative previews, print layouts, brand systems, and opt-in uploads. Use when creating, revising, previewing, exporting, or securely uploading a report, proposal, budget summary, or other designed PDF.
npx skills add https://github.com/jamditis/claude-skills-journalism --skill pdf-design
Create and edit professional PDF reports and funding proposals with live preview and iterative design.
During a design session, use these commands:
| Command | Action |
|---------|--------|
| preview | Screenshot current state |
| preview page N | Screenshot specific page |
| show cover | Preview cover page |
| show budget | Preview budget section |
| regenerate | Create new PDF |
| upload | Confirm and upload to a user-chosen destination |
| done | Finish session |
Workflow:
# Copy template to start new report
cp ~/.claude/plugins/pdf-design/templates/democracy-day-proposal.html ./new-report.html
# Generate PDF (must use snap-accessible path)
mkdir -p ~/snap/chromium/common/pdf-work
cp new-report.html ~/snap/chromium/common/pdf-work/
chromium-browser --headless --disable-gpu \
--blink-settings=scriptEnabled=false \
--print-to-pdf="$HOME/snap/chromium/common/pdf-work/output.pdf" \
--no-pdf-header-footer \
"file://$HOME/snap/chromium/common/pdf-work/new-report.html"
:root {
--ccm-red: #CA3553;
--ccm-black: #000000;
--ccm-gray: #666666;
--ccm-light: #e2e8f0;
}
:root {
--civic-navy: #1a2b4a;
--civic-blue: #2d4a7c;
--civic-gold: #c9a227;
--civic-red: #b31942;
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&family=Source+Sans+Pro:wght@300;400;600&display=swap" rel="stylesheet">
body {
font-family: 'Source Sans Pro', sans-serif;
font-size: 0.875rem;
line-height: 1.6;
}
h1, h2, h3 {
font-family: 'Montserrat', sans-serif;
}
@page { size: letter; margin: 0; }
.page {
width: 8.5in;
height: 11in;
display: grid;
grid-template-rows: auto 1fr auto;
overflow: hidden;
page-break-after: always;
}
<div class="page cover">
<div class="cover-header">
<div class="cover-org">Center for Cooperative Media</div>
<h1 class="cover-title">Report title</h1>
<p class="cover-intro">Brief description.</p>
</div>
<div class="cover-footer">
<div class="cover-stats"><!-- Stats --></div>
<div class="cover-footer-right">
<div class="cover-date">February 2026</div>
<div class="cover-logo"><img src="..." alt="Logo"></div>
</div>
</div>
</div>
<div class="page content-page">
<div class="page-header">
<div class="page-header-title">Document title</div>
<div class="page-number">2</div>
</div>
<div class="page-body">
<!-- Content goes here -->
</div>
<footer class="page-footer">
<!-- Footer -->
</footer>
</div>
<table class="budget-table">
<thead>
<tr><th>Expense</th><th>Per year</th><th>Total</th></tr>
</thead>
<tbody>
<tr>
<td>Item<span class="item-desc">Details</span></td>
<td>$10,000</td>
<td>$20,000</td>
</tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>$50,000</td><td>$100,000</td></tr>
</tfoot>
</table>
.page-body {
padding: 0.2in 0.65in 0.3in;
overflow: hidden;
}
.page-footer {
padding: 0 0.65in 0.5in;
border-top: 1px solid #e2e8f0;
font-size: 0.8rem;
}
Content must not touch or overlap the page footer. These rules apply to content pages — cover pages and special layouts may use different structures.
display: grid; grid-template-rows: auto 1fr auto on .page.page-body), footeroverflow: hidden to prevent text bleedingposition: absolute for footers — keep them in normal document flow as the third grid row.page-footer:empty { display: none; } so pages without footer content don't render a blank border# Must use ~/snap/chromium/common/ path
mkdir -p ~/snap/chromium/common/pdf-work
cp template.html ~/snap/chromium/common/pdf-work/
chromium-browser --headless --disable-gpu \
--blink-settings=scriptEnabled=false \
--print-to-pdf="$HOME/snap/chromium/common/pdf-work/output.pdf" \
--no-pdf-header-footer \
"file://$HOME/snap/chromium/common/pdf-work/template.html"
cp ~/snap/chromium/common/pdf-work/output.pdf ./
# PDF to PNG
pdftoppm -png -f 1 -l 1 output.pdf preview
# Page count
pdfinfo output.pdf | grep Pages
mkdir -p "$HOME/snap/chromium/common/pdf-work"
cp template.html "$HOME/snap/chromium/common/pdf-work/template.html"
chromium-browser --headless --disable-gpu \
--blink-settings=scriptEnabled=false \
--screenshot="$HOME/snap/chromium/common/pdf-work/preview.png" \
--window-size=1275,1650 \
"file://$HOME/snap/chromium/common/pdf-work/template.html"
cp "$HOME/snap/chromium/common/pdf-work/preview.png" ./preview.png
Upload only when the user explicitly requests it after reviewing the local PDF.
Do not read or parse raw OAuth token files. Do not search for credentials, silently choose a remote folder, or upload to a hard-coded destination. If no connected integration is available, stop after local generation and explain how the user can upload the PDF themselves.
These patterns were proven out in the NJ Public TV walkthrough deck (pdf-playground 1.3.0) and work just as well inside report and proposal pages. Drop them into any .page-body or .cover-footer.
A tight 0.95in × 0.08in red bar under the headline reads cleaner than a full-width border. Use for section headers inside content pages.
.section-header h2 {
font-family: 'Montserrat', sans-serif;
font-size: 22pt;
font-weight: 800;
color: var(--ccm-black);
line-height: 1.08;
}
.section-header h2::after {
content: '';
display: block;
width: 0.95in;
height: 0.08in;
background: var(--ccm-red);
margin-top: 0.14in;
}
Row of 3–4 big numbers with a short caption and a red left rule. Great for executive-summary numbers on a cover or intro page.
<div class="stats-strip">
<div class="stat"><div class="big">23,000+</div><div class="label">Students enrolled</div></div>
<div class="stat"><div class="big">$660M</div><div class="label">Annual operating budget</div></div>
<div class="stat"><div class="big">$2.3B</div><div class="label">Economic impact</div></div>
<div class="stat"><div class="big">252</div><div class="label">Acre main campus</div></div>
</div>
.stats-strip {
display: grid;
grid-template-columns: repeat(var(--stat-cols, 4), 1fr);
gap: 0.3in;
}
.stats-strip .stat {
padding: 0.05in 0 0.1in 0.24in;
border-left: 4px solid var(--ccm-red);
}
.stats-strip .big {
font-family: 'Montserrat', sans-serif;
font-size: 28pt;
font-weight: 800;
line-height: 1;
color: var(--ccm-black);
letter-spacing: -0.015em;
}
.stats-strip .label {
font-size: 9pt;
font-weight: 600;
margin-top: 0.1in;
color: var(--ccm-gray);
text-transform: uppercase;
letter-spacing: 0.05em;
}
For breaking one topic into three parallel facets with a dashed divider between columns.
.three-col {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 0.3in;
}
.three-col > div + div {
padding-left: 0.3in;
border-left: 2px dashed #d9d9d9;
}
.three-col h3 {
font-size: 10pt;
font-weight: 800;
color: var(--ccm-red);
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 0.12in;
}
Numbered cards with a red top rule — for parallel capabilities, themes, or commitments. Common on proposal executive summary pages.
<div class="four-col-tiles">
<div class="tile">
<div class="tile-num">Pillar 01</div>
<h3>Proven facilities and expertise</h3>
<p>Short 2–3 line description.</p>
</div>
<!-- 3 more tiles -->
</div>
.four-col-tiles {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.15in;
}
.four-col-tiles .tile {
border-top: 4px solid var(--ccm-red);
padding: 0.18in 0.15in 0.15in;
background: #f7f6f5;
}
.four-col-tiles .tile-num {
font-size: 8pt;
font-weight: 800;
color: var(--ccm-red);
letter-spacing: 0.15em;
text-transform: uppercase;
margin-bottom: 0.08in;
}
.four-col-tiles .tile h3 {
font-size: 12pt;
font-weight: 800;
color: var(--ccm-black);
margin-bottom: 0.08in;
}
.four-col-tiles .tile p {
font-size: 9pt;
line-height: 1.38;
color: var(--ccm-gray);
margin: 0;
}
4-column grid of labeled tiles with a red left accent bar. Use for sponsor lists, letters of support, or advisory board rosters.
.partner-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.12in 0.18in;
}
.partner-grid .partner {
position: relative;
padding: 0.14in 0.15in 0.14in 0.22in;
background: #f7f6f5;
font-size: 9pt;
font-weight: 600;
line-height: 1.25;
color: var(--ccm-black);
}
.partner-grid .partner::before {
content: '';
position: absolute;
left: 0; top: 0; bottom: 0;
width: 0.06in;
background: var(--ccm-red);
}
Every block above was tightened based on real presentation feedback. Key principles:
If a page feels too crowded, *reduce content*, don't expand spacing.
~/snap/chromium/common/Reference: ~/.claude/plugins/pdf-design/templates/democracy-day-proposal.html
Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks
Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.
Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation.
Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions \"deck,\" \"slides,\" \"presentation,\" or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill.
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
Take jamditis/pdf-design from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.