GEO PDF Report Generator (pandoc pipeline)

Generate a professional PDF report from a GEO audit using pandoc + Chrome headless.

How to use it

  1. Hit Copy SKILL.md — or use the Claude Code line below to get every file.
  2. Claude: ⋯ → Download .md, then Customize → Skills → Add → Upload skill.
    ChatGPT: make a Project and paste it into Instructions.
    Neither? Paste it at the top of a new chat — it works for that chat.
  3. Describe your job in plain words. The AI follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit zubair-trabzada/geo-seo-claude/skills/geo-report-pdf#main ~/.claude/skills/geo-report-pdf

For one project only, change the path to .claude/skills/geo-report-pdf. This skill also uses GEO-AUDIT-REPORT.md — copying SKILL.md alone won't be enough. See the folder on GitHub.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text121 lines
geo-report-pdf/SKILL.md121 lines5.0 KBpushed 142d agoRawView on GitHub

GEO PDF Report Generator (pandoc pipeline)

Prerequisites

  • pandocbrew install pandoc
  • Google Chrome — must be installed at /Applications/Google Chrome.app/

No Python dependencies. No ReportLab. No JSON data wrangling.

How It Works

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

Discussion

Alternatives

Also in AI search (AEO)