| name | markdown-to-report |
| description | Convert a Markdown document into a polished, Bridge-branded enterprise PDF report (cover page, orange section headings, navy data tables, inline SVG charts, clickable source footnotes, and editorial design components). Use this skill whenever the user wants to turn a `.md` file into a PDF / report / deck, (re)generate the Bridge reports, add charts / footnotes / source citations to a report, restyle a document to the report theme, or mentions `build-report.mjs`, `report-theme.css`, `render-report.sh`, or `tools/pdf`. Also use when adding an inline chart, a clickable source list, a stat band, or the spec-sheet / verdict-bar / option-card / numbered-findings layouts to a doc — even if they don't say the word "report". Pipeline is Markdown → marked → headless Chrome → PDF; fully offline, deterministic, no LaTeX/Pandoc. |
Markdown → enterprise PDF report
Turn any Markdown doc into a branded, presentation-grade A4 PDF. The pipeline is
Markdown → marked (GFM) → post-processed HTML → system Google Chrome (puppeteer-core) → PDF.
No Pandoc, no LaTeX, no Chromium download. Output is visually deterministic.
The three files (canonical location: tools/pdf/)
| File | Role |
|---|
tools/pdf/build-report.mjs | The builder. One .md → one .pdf. Handles cover, title-block stripping, tables, callouts, charts, footnotes, stat band. |
tools/pdf/report-theme.css | The theme: palette, fonts, section headings, tables, charts, footnotes, and all design components. Extend it here when a layout is missing. |
tools/pdf/render-report.sh | Batch driver — rebuilds every project doc with its per-doc cover metadata. Edit this to add a doc. |
To reuse in another repo: copy those three files into tools/pdf/, then run the setup below.
Setup (once per machine / fresh clone)
node_modules is gitignored, so a fresh checkout needs deps:
npm install --prefix tools/pdf puppeteer-core marked
Requirements: Google Chrome at /usr/bin/google-chrome (override with CHROME_PATH), and the fonts Montserrat, Noto Sans, Liberation Mono installed (fc-list | grep -iE "montserrat|noto sans|liberation mono"). These are the local stand-ins for the design system's Schibsted Grotesk / IBM Plex Mono — keep using them so the whole report stays one consistent type system.
Build one doc
node tools/pdf/build-report.mjs <input.md> --out <output.pdf> [options]
| Option | Effect |
|---|
--title "..." | Cover title (default: first # heading, parens stripped) |
--kicker "..." | Small uppercase label above the title |
--subtitle "..." | Date / descriptor line under the title (falls back to a leading ## subtitle) |
--stats "Label=Value;Label=Value" | Up to 4 hero stat cards under the cover (Value shown big) |
--foot-left / --foot-right | Cover footer strips (default: "Bridge Pilot…" / "Confidential") |
Build every doc at once: bash tools/pdf/render-report.sh.
What the builder does automatically
- Cover page (full-bleed gradient, Bridge arch logo, kicker/title/subtitle, footer) — page 1, unnumbered.
- Title-block stripping — the leading
# title (+ optional ## subtitle + a metadata line) is removed from the body so it isn't stranded on page 2; the ## subtitle becomes the cover subtitle if --subtitle isn't given.
- Section headings — every
## is orange and starts a new page (page-per-context); the first section flows after the intro so page 2 isn't half-empty.
- Tables — navy header, zebra rows, numbers right-aligned & bold, and any row containing
TOTAL / MINIMUM FLOOR auto-highlighted.
- Callouts — a paragraph starting with
⚠️ becomes an amber warning panel, ✅ a green one; blockquotes become soft panels.
- Running header —
Bridge <page#> top-right via CSS @page margin boxes (relies on this Chrome supporting them).
Markdown directives
These are the value-add features. Drop them straight into the .md.
Charts — inline SVG (crisp vector, offline, no deps)
<!-- bridge:chart type=bar title="Budget by bucket (IDR M)" unit="M" data="Hotel:54, Production:36, Venue:30" -->
<!-- bridge:chart type=donut title="Revenue mix" unit="M" data="International:230, Local:150" -->
bar = horizontal bars (orange/teal, value labels). donut = ring + legend with value · %. Labels must not contain commas (the parser splits on , then takes the value after the last :).
Footnotes + clickable source citations
Inline marker → fine-print Sources block at section end. Any domain/URL in a source line is auto-linkified into a clickable link in the PDF.
Some claim with a citation.[^1]
<!-- bridge:sources -->
- Source one — jetbrains.com, survey.stackoverflow.co.
- Source two: Bank Indonesia (bi.go.id), 2026.
<!-- /bridge:sources -->
[^1] renders as an orange superscript; the block renders as a numbered "SOURCES" panel. Every external citation should carry a domain so it resolves to a clickable link — add the canonical site (homepage is fine when there's no deep link). Internal/analytical figures can stay link-free but label them honestly ("Bridge estimate").
Editorial design components
For richer layouts (comparison tables, KPI bands, option cards), write raw HTML in the markdown using the classes below — marked passes block HTML through, and report-theme.css styles them. Keep each block free of internal blank lines (marked ends an HTML block at a blank line). Ready-to-paste snippets and the full class list are in references/components.md — read it before hand-writing these.
Components available: .qc-sub (orange-bar subheading), .spec (two-tier spec-sheet), .qc-band (captioned KPI band), .options/.opt/.recpill (option cards), .verdict (navy verdict bar), .findings (numbered 01–N grid).
Verify the output (don't trust blind)
pdftoppm -png -r 120 -f 1 -l 3 out.pdf /tmp/chk
grep -a -o "/URI" out.pdf | wc -l
pdfinfo out.pdf | grep Pages
Render and look at any page you changed — especially charts (labels not overflowing), source blocks (links present & not stranded on a near-empty page), and any hand-written component (cells not clipped).
Palette & type (in report-theme.css :root)
Navy ink #16243B (= design navy #2A3D5C for component headers), warm orange #E0701A, teal #1C8C7D, cream/peach panels. Montserrat (display), Noto Sans (body), Georgia (cover/serif), Liberation Mono (labels). Don't reintroduce the old Bridge navy/amber build.mjs theme or any PwC branding — orange + navy is the house style.
Reproducibility note
Re-running the build produces visually identical pages, but the PDF bytes differ each run because Chrome embeds a creation timestamp + document ID. So git will flag regenerated PDFs as "modified" even when nothing visual changed — that's expected, not a real diff.
Reference files
references/components.md — paste-ready HTML for every design component + the complete CSS class reference and which --var tokens they use.