Paperbase Docs

Markdown to branded PDF report

End-to-end walkthrough — Markdown input, report template, full branding, warning handling.

This example walks through a complete integration: take a Markdown string, apply the report template with full branding, handle warnings, and download the PDF.

What you'll build

A function that:

  1. Sends Markdown to Paperbase with a branded theme
  2. Logs any warnings with their fix suggestions
  3. Returns a signed URL to the finished PDF

Prerequisites

npm install paperbase
.env
PAPERBASE_API_KEY=pb_live_…

Implementation

lib/generate-report.ts
import { Paperbase } from "paperbase";
 
const paperbase = new Paperbase({ apiKey: process.env.PAPERBASE_API_KEY! });
 
export type ReportInput = {
  markdown: string;
  title?: string;
  clientReference?: string;
};
 
export type ReportResult = {
  url: string;
  previewUrl: string | null;
  pageCount: number | null;
  warningCount: number;
};
 
export async function generateBrandedReport(
  input: ReportInput,
): Promise<ReportResult> {
  const result = await paperbase.pdf.generate({
    input: {
      type: "markdown",
      content: input.markdown,
    },
    template: "report",
    theme: {
      logo_url: "https://cdn.example.com/logo.svg",
      primary_color: "#1a1a2e",
      accent_color: "#6366f1",
      body_font: "Inter",
      heading_font: "Playfair Display",
      footer: "<p style='font-size:10px;color:#9ca3af'>Confidential</p>",
    },
    metadata: {
      title: input.title,
      client_reference: input.clientReference,
    },
  });
 
  // Surface warnings — agent-repairable ones include a suggested_fix
  for (const warning of result.warnings) {
    if (warning.severity === "warning") {
      console.warn(`[${warning.code}] ${warning.human_message}`);
      if (warning.agent_repairable) {
        console.warn(`  Fix: ${warning.suggested_fix}`);
      }
    }
  }
 
  return {
    url: result.url!,
    previewUrl: result.preview_url,
    pageCount: result.page_count,
    warningCount: result.warnings.length,
  };
}

Calling the function

scripts/run-report.ts
import { generateBrandedReport } from "./lib/generate-report";
 
const markdown = `
# Q3 2026 Performance Report
 
## Executive Summary
 
Revenue grew 34% quarter-over-quarter, driven by enterprise expansion.
 
## Revenue Breakdown
 
| Segment | Q2 | Q3 | Change |
|---|---|---|---|
| Enterprise | $1.2M | $1.6M | +33% |
| SMB | $0.4M | $0.5M | +25% |
| Self-serve | $0.1M | $0.1M | +0% |
 
## Appendix
 
Raw data available in the supplementary spreadsheet.
`;
 
const report = await generateBrandedReport({
  markdown,
  title: "Q3 2026 Performance Report",
  clientReference: "CLIENT-2026-Q3",
});
 
console.log("PDF ready:", report.url);
console.log("Pages:", report.pageCount);
console.log("Warnings:", report.warningCount);

What the report template renders

The report template automatically:

  • Generates a full-bleed branded cover page from the first # h1 heading
  • Inserts a clickable table of contents from ## h2 headings
  • Styles an Executive Summary section if that heading is present
  • Moves an Appendix section to the back matter
  • Applies your theme (logo, colors, fonts) to every page

See the Report template reference for the full list of recognized headings.

Self-healing with warning feedback

If you're building an agentic pipeline, use warnings to self-correct on the next run:

const result = await paperbase.pdf.generate({ ... });
 
const repairable = result.warnings.filter(w => w.agent_repairable);
 
if (repairable.length > 0) {
  // Ask an LLM to apply the suggested fixes to the original request
  const fixes = repairable.map(w => ({
    code: w.code,
    fix: w.suggested_fix,
  }));
 
  const patchedRequest = await applyFixes(originalRequest, fixes);
  const retryResult = await paperbase.pdf.generate(patchedRequest);
}

On this page