pdf-design
SKILL.md
PDF Design System
Create and edit professional PDF reports and funding proposals with live preview and iterative design.
Interactive editing mode
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 |
Upload to Google Drive |
done |
Finish session |
Workflow:
- You say "preview" → I show current state
- You describe changes → I implement them
- Repeat until done → Generate final PDF
Quick start
# 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 \
--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"
Document types
- Funding proposals — Grant requests with budgets
- Program reports — Initiative updates
- Impact reports — Metrics and outcomes
- Budget summaries — Financial breakdowns
Key principles
- Sentence case — Never Title Case
- Left-aligned — Never justified text
- Print-ready — 8.5" × 11" letter size
- Brand consistent — CCM red or program palettes
Brand guidelines
CCM standard colors
:root {
--ccm-red: #CA3553;
--ccm-black: #000000;
--ccm-gray: #666666;
--ccm-light: #e2e8f0;
}
Program-specific (Democracy Day)
:root {
--civic-navy: #1a2b4a;
--civic-blue: #2d4a7c;
--civic-gold: #c9a227;
--civic-red: #b31942;
}
Typography
<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;
}
HTML structure
Page setup
@page { size: letter; margin: 0; }
.page {
width: 8.5in;
height: 11in;
padding: 0.5in 0.65in;
position: relative;
page-break-after: always;
}
Cover page
<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>
Content page
<div class="page content-page">
<div class="page-header">
<div class="page-header-title">Document Title</div>
<div class="page-number">2</div>
</div>
<!-- Content -->
</div>
Budget table
<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 footer (institution note)
.institution-note {
position: absolute;
bottom: 0.5in;
left: 0.65in;
right: 0.65in;
border-top: 1px solid #e2e8f0;
font-size: 0.8rem;
}
PDF generation
Chromium (snap-confined)
# 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 \
--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 ./
Preview pages
# PDF to PNG
pdftoppm -png -f 1 -l 1 output.pdf preview
# Page count
pdfinfo output.pdf | grep Pages
Legion browser preview
~/.claude/scripts/legion-browser.py screenshot "file:///path/to/template.html" -o preview.png
Google Drive upload
cd ~/.claude/workstation/mcp-servers/gmail && source .venv/bin/activate
python3 << 'PYEOF'
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from google.oauth2.credentials import Credentials
import json
with open('/home/jamditis/.claude/google/drive-token.json') as f:
token_data = json.load(f)
creds = Credentials(
token=token_data['access_token'],
refresh_token=token_data.get('refresh_token'),
token_uri='https://oauth2.googleapis.com/token',
client_id=token_data.get('client_id'),
client_secret=token_data.get('client_secret')
)
service = build('drive', 'v3', credentials=creds)
# Upload new file
file_metadata = {
'name': 'Report.pdf',
'parents': ['1lKTdwq4_5uErj-tBN112WCdJGD2YtetO'] # Shared with Joe
}
media = MediaFileUpload('/path/to/output.pdf', mimetype='application/pdf')
file = service.files().create(body=file_metadata, media_body=media, fields='id,webViewLink').execute()
print(f"Uploaded: {file.get('webViewLink')}")
PYEOF
Drive folders
- Shared with Joe:
1lKTdwq4_5uErj-tBN112WCdJGD2YtetO - Claude Workspace:
1e5dtKOiuvk0PPrFq3UyNI2UAa6RFiom3
Known issues
- Base64 images — Don't read HTML with large base64 using Read tool (API error). Use sed/grep/Python.
- Snap confinement — Chromium can only write to
~/snap/chromium/common/ - Fonts — Google Fonts via CDN; for offline, embed as base64
Logo locations
- CCM logo:
~/.claude/plugins/pdf-design/templates/(embedded in template) - Brand assets:
/home/jamditis/projects/cjs2026/public/internal/brand_web_assets/
Template
Reference: ~/.claude/plugins/pdf-design/templates/democracy-day-proposal.html
Weekly Installs
72
Repository
jamditis/claude…urnalismGitHub Stars
70
First Seen
Feb 6, 2026
Security Audits
Installed on
cursor70
gemini-cli69
opencode69
codex68
github-copilot66
kimi-cli65