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.875 rem ; line-height : 1.6 ; } h1 , h2 , h3 { font-family : 'Montserrat' , sans-serif ; } HTML structure Page setup @page { size : letter ; margin : 0 ; } .page { width : 8.5 in ; height : 11 in ; padding : 0.5 in 0.65 in ; 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 "
</ 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
</ 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.5 in ; left : 0.65 in ; right : 0.65 in ; border-top : 1 px solid
e2e8f0
; font-size : 0.8 rem ; } 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