GEO PDF Report Generator (pandoc pipeline)
Prerequisites
- pandoc —
brew install pandoc
- Google Chrome — must be installed at
/Applications/Google Chrome.app/
No Python dependencies. No ReportLab. No JSON data wrangling.
How It Works
- Read
GEO-AUDIT-REPORT.md in the current directory (created by /geo audit)
- Extract cover metadata from the report (brand name, domain, GEO score, date, locations)
- Run
pandoc with the bundled CSS + HTML template to produce a self-contained GEO-REPORT.html
- Run Chrome headless to print the HTML to
GEO-REPORT.pdf
The pandoc template (~/.claude/skills/geo/templates/geo-report-template.html) injects:
- A full-bleed dark navy cover section with the GEO score badge
- Per-section cover metadata (date, business type, locations, platform)
- JavaScript that runs inside Chrome before printing to color-code score cells and severity-tag finding sections
Workflow
Step 1: Check for audit report
Look for GEO-AUDIT-REPORT.md in the current directory. If absent, tell the user to run /geo audit <url> first.
Step 2: Extract cover metadata from the report
Read the top of GEO-AUDIT-REPORT.md and extract:
| Field |
Where to find it |
brand_name |
First H1 title (after "GEO Audit Report:") |
domain |
Second bold line (e.g. **Domain:** alexamediasolutions.com) |
geo_score |
Line matching ## Overall GEO Score: XX / 100 |
score_label |
Word after the score on that same line (e.g. "Poor", "Fair", "Good") |
date |
**Audit Date:** line |
business_type |
**Business Type:** line |
locations |
**Locations:** line |
platform |
**CMS:** line |
Step 3: Run pandoc
pandoc GEO-AUDIT-REPORT.md \
--to html5 \
--standalone \
--embed-resources \
--template ~/.claude/skills/geo/templates/geo-report-template.html \
--css ~/.claude/skills/geo/templates/geo-report-style.css \
--metadata title="GEO Audit Report — <brand_name>" \
--metadata brand_name="<brand_name>" \
--metadata domain="<domain>" \
--metadata geo_score="<geo_score>" \
--metadata score_label="<score_label>" \
--metadata date="<date>" \
--metadata business_type="<business_type>" \
--metadata locations="<locations>" \
--metadata platform="<platform>" \
-o GEO-REPORT.html
Replace <field> placeholders with values extracted in Step 2. If a field is not found in the report, omit that --metadata flag — the template has sensible defaults.
Step 4: Run Chrome headless
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--headless=new \
--disable-gpu \
--no-sandbox \
--print-to-pdf="$(pwd)/GEO-REPORT.pdf" \
--print-to-pdf-no-header \
--no-pdf-header-footer \
--virtual-time-budget=5000 \
"file://$(pwd)/GEO-REPORT.html"
Step 5: Report completion
Tell the user:
GEO-REPORT.pdf was generated in the current directory
- File size
- Optionally:
open GEO-REPORT.pdf to preview it
What the PDF Contains
- Cover page — Dark navy gradient, brand name, domain, GEO score badge (colored by score), audit date, business type, locations, CMS platform
- Score tables — Cells containing
XX/100 are color-coded: ≥80 green, ≥65 blue, ≥50 amber, ≥35 orange, <35 red
- Finding sections —
h3 headings containing "Critical / High / Medium / Low" get severity-colored left-border callout blocks (red / orange / yellow / green)
- Section page breaks — Major sections (High Priority, 90-Day Roadmap, Component Score Summary, Generated Schema) break to new pages automatically
- Code blocks — JSON schema templates render with dark theme monospace styling
- Page footer — Brand name · GEO Audit · date + page numbers (via CSS
@page)
Customizing the Report
- Colors / typography — Edit
~/.claude/skills/geo/templates/geo-report-style.css
- Cover layout — Edit
~/.claude/skills/geo/templates/geo-report-template.html
- Score thresholds for color-coding — Edit the
scoreColor() function in the template's <script> block
- Which sections get page breaks — Edit the
breakBefore array in the template's <script> block
Troubleshooting
| Problem |
Fix |
pandoc: command not found |
brew install pandoc |
| Chrome not found |
Check path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome |
| PDF is blank / empty |
Increase --virtual-time-budget to 8000 |
| Cover metadata missing |
Check GEO-AUDIT-REPORT.md has the standard header format |
| Fonts not loading |
PDF is rendered offline; system fonts are used as fallback — this is expected |
1---2name: geo-report-pdf3description: Generate a professional PDF report from a GEO audit using pandoc + Chrome headless. Converts GEO-AUDIT-REPORT.md into a styled, client-ready PDF with a cover page, color-coded score tables, severity-tagged findings, and a 90-day roadmap.4---5
6# GEO PDF Report Generator (pandoc pipeline)
7
8## Prerequisites
9
10- **pandoc** — `brew install pandoc`
11- **Google Chrome** — must be installed at `/Applications/Google Chrome.app/`
12
13No Python dependencies. No ReportLab. No JSON data wrangling.
14
15## How It Works
16
171. Read `GEO-AUDIT-REPORT.md` in the current directory (created by `/geo audit`)
182. Extract cover metadata from the report (brand name, domain, GEO score, date, locations)
193. Run `pandoc` with the bundled CSS + HTML template to produce a self-contained `GEO-REPORT.html`
204. Run Chrome headless to print the HTML to `GEO-REPORT.pdf`
21
22The pandoc template (`~/.claude/skills/geo/templates/geo-report-template.html`) injects:
23- A full-bleed dark navy cover section with the GEO score badge
24- Per-section cover metadata (date, business type, locations, platform)
25- JavaScript that runs inside Chrome before printing to color-code score cells and severity-tag finding sections
26
27## Workflow
28
29### Step 1: Check for audit report
30
31Look for `GEO-AUDIT-REPORT.md` in the current directory. If absent, tell the user to run `/geo audit <url>` first.
32
33### Step 2: Extract cover metadata from the report
34
35Read the top of `GEO-AUDIT-REPORT.md` and extract:
36
37| Field | Where to find it |
38|---|---|
39| `brand_name` | First H1 title (after "GEO Audit Report:") |
40| `domain` | Second bold line (e.g. `**Domain:** alexamediasolutions.com`) |
41| `geo_score` | Line matching `## Overall GEO Score: XX / 100` |
42| `score_label` | Word after the score on that same line (e.g. "Poor", "Fair", "Good") |
43| `date` | `**Audit Date:**` line |
44| `business_type` | `**Business Type:**` line |
45| `locations` | `**Locations:**` line |
46| `platform` | `**CMS:**` line |
47
48### Step 3: Run pandoc
49
50```bash
51pandoc GEO-AUDIT-REPORT.md \
52 --to html5 \
53 --standalone \
54 --embed-resources \
55 --template ~/.claude/skills/geo/templates/geo-report-template.html \
56 --css ~/.claude/skills/geo/templates/geo-report-style.css \
57 --metadata title="GEO Audit Report — <brand_name>" \
58 --metadata brand_name="<brand_name>" \
59 --metadata domain="<domain>" \
60 --metadata geo_score="<geo_score>" \
61 --metadata score_label="<score_label>" \
62 --metadata date="<date>" \
63 --metadata business_type="<business_type>" \
64 --metadata locations="<locations>" \
65 --metadata platform="<platform>" \
66 -o GEO-REPORT.html
67```
68
69Replace `<field>` placeholders with values extracted in Step 2. If a field is not found in the report, omit that `--metadata` flag — the template has sensible defaults.
70
71### Step 4: Run Chrome headless
72
73```bash
74"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
75 --headless=new \
76 --disable-gpu \
77 --no-sandbox \
78 --print-to-pdf="$(pwd)/GEO-REPORT.pdf" \
79 --print-to-pdf-no-header \
80 --no-pdf-header-footer \
81 --virtual-time-budget=5000 \
82 "file://$(pwd)/GEO-REPORT.html"
83```
84
85### Step 5: Report completion
86
87Tell the user:
88- `GEO-REPORT.pdf` was generated in the current directory
89- File size
90- Optionally: `open GEO-REPORT.pdf` to preview it
91
92## What the PDF Contains
93
94- **Cover page** — Dark navy gradient, brand name, domain, GEO score badge (colored by score), audit date, business type, locations, CMS platform
95- **Score tables** — Cells containing `XX/100` are color-coded: ≥80 green, ≥65 blue, ≥50 amber, ≥35 orange, <35 red
96- **Finding sections** — `h3` headings containing "Critical / High / Medium / Low" get severity-colored left-border callout blocks (red / orange / yellow / green)
97- **Section page breaks** — Major sections (High Priority, 90-Day Roadmap, Component Score Summary, Generated Schema) break to new pages automatically
98- **Code blocks** — JSON schema templates render with dark theme monospace styling
99- **Page footer** — Brand name · GEO Audit · date + page numbers (via CSS `@page`)
100
101## Customizing the Report
102
103- **Colors / typography** — Edit `~/.claude/skills/geo/templates/geo-report-style.css`
104- **Cover layout** — Edit `~/.claude/skills/geo/templates/geo-report-template.html`
105- **Score thresholds for color-coding** — Edit the `scoreColor()` function in the template's `<script>` block
106- **Which sections get page breaks** — Edit the `breakBefore` array in the template's `<script>` block
107
108## Troubleshooting
109
110| Problem | Fix |
111|---|---|
112| `pandoc: command not found` | `brew install pandoc` |
113| Chrome not found | Check path: `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome` |
114| PDF is blank / empty | Increase `--virtual-time-budget` to 8000 |
115| Cover metadata missing | Check GEO-AUDIT-REPORT.md has the standard header format |
116| Fonts not loading | PDF is rendered offline; system fonts are used as fallback — this is expected |