Test it free for 30 days

Brevier The full-stack PDF library

Brevier generates PDF documents from the plainest web tools: HTML, CSS, JSON and Handlebars. Templates can be Markdown.

pip install brevier
Choose an example
rechnung

rechnung/rechnung.html

<!DOCTYPE html>
<html lang="de">
<head>
  <title>Rechnung</title>
</head>
<body>
  <p>{{ firma.name }}</p>
  <h1>Rechnung</h1>
  <table>
    <tr><th>Text</th><th>Betrag</th></tr>
    {{#each rechnung.positionen}}
    <tr>
      <td>{{ text }}</td>
      <td>{{ betrag | money }}</td>
    </tr>
    {{/each}}
  </table>
</body>
</html>

rechnung/rechnung.css

@page {
  size: A4;
  margin: 20mm;
}
body {
  font: 10pt sans-serif;
  color: #16181c;
}
.absender { font-size: 7pt; }
address { margin: 2mm 0 15mm; }
h1 { font-size: 14pt; }
table { width: 100%; }
th, td { padding: 1.5mm 0; }
td:last-child {
  text-align: right;
}

rechnung/rechnung.json

{
  "firma": {
    "name": "Muster AG",
    "ort": "Berlin"
  },
  "kunde": {
    "name": "Erika M.",
    "ort": "Köln"
  },
  "rechnung": {
    "nr": "R-2026-01",
    "positionen": [
      {
        "text": "Beratung",
        "betrag": 84.2
      }
    ]
  }
}

rechnung/rechnung.schema.json

{
  "type": "object",
  "properties": {
    "firma": {
      "type": "object"
    },
    "kunde": {
      "type": "object"
    },
    "rechnung": {
      "type": "object",
      "properties": {
        "nr": {
          "type": "string"
        },
        "positionen": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "betrag": {
                "type": "number"
              }
            }
          }
        }
      }
    }
  }
}

rechnung/rechnung.pdf

Page 1 of the invoice, as Brevier rendered it from these files.
rechnung

rechnung/rechnung.md

---
style: rechnung.css
---

{{ firma.name }}

An: {{ kunde.name }}

# Rechnung

| Text | Betrag |
| --- | ---: |
{{#each rechnung.positionen}}
| {{ text }} | {{ betrag | money }} |
{{/each}}

rechnung/rechnung.css

@page {
  size: A4;
  margin: 20mm;
}
body {
  font: 10pt sans-serif;
  color: #16181c;
}
.absender { font-size: 7pt; }
address { margin: 2mm 0 15mm; }
h1 { font-size: 14pt; }
table { width: 100%; }
th, td { padding: 1.5mm 0; }
td:last-child {
  text-align: right;
}

rechnung/rechnung.json

{
  "firma": {
    "name": "Muster AG",
    "ort": "Berlin"
  },
  "kunde": {
    "name": "Erika M.",
    "ort": "Köln"
  },
  "rechnung": {
    "nr": "R-2026-01",
    "positionen": [
      {
        "text": "Beratung",
        "betrag": 84.2
      }
    ]
  }
}
src/main/java

src/main/java/RechnungService.java

import dev.brevier.Brevier;

public class RechnungService {

    public byte[] pdf(
        Firma f,
        Rechnung r,
        Kunde k
    ) {
        return Brevier
            .template("rechnung")
            .render(f, r, k);
    }
}
app

app/rechnung.py

import brevier


def pdf(
    firma, rechnung, kunde
) -> bytes:
    return brevier.template("rechnung").render(
        firma, rechnung, kunde
    )

Everything a business document needs

Brevier handles the print rules, so you can focus on your data.

  • HTML and CSS templates

    Write the page in plain HTML and CSS.

  • Markdown for static content documents

    Turn a Markdown file into a PDF.

  • Data binding

    Fill the HTML with your JSON data.

  • Validate HTML templates against a JSON schema

    Find a misspelt field before anything prints.

  • Start from your classes

    Get a first template from your own classes.

  • Import JasperReports and BIRT

    Convert JasperReports and BIRT reports.

  • Import Word

    Convert .docx files with merge fields.

  • Replace your render call

    Swap your old render call for Brevier's.

  • The visible middle

    See the exact HTML and CSS the engine got.

  • German and English hyphenation

    Correct hyphenation in German and English.

  • Tables that span pages

    Tables that repeat their header on every page.

  • Übertrag - Running totals

    Running totals carried from page to page.

  • Headers, footers and page counters

    Headers, footers and page numbers on every page.

  • Contracts and fine print

    Numbered clauses and a table of contents.

  • Every feature, with its status

    Open the feature list

A breviary is a prayer book — the German word for it is Brevier. Brevier is built to be your go-to library for generating PDFs programmatically, but also to easily integrate the PDF rendering in your web apps. Having fought clunky PDF tools for years, I built it to make document generation intuitive, simple, and seamless within your existing code.

Liviu IonesiLiviu IonesiDeveloper of Brevier

Built on what you already know

HTML, CSS, JSON and your own code. Nothing new to learn.

  • HTML for the page

    The template is an HTML page. Handlebars binds it with your data: values, loops and conditions.

    developer.mozilla.org
  • CSS for the styling

    CSS sets the fonts and colours, and the page layout too: size, margins, headers, footers and page numbers.

    CSS @page
  • JSON for the data

    Your objects are serialized as JSON. A JSON Schema validates every field before rendering.

    json-schema.org
  • Your own code

    Pass the objects you already have in Java, Python, .NET and TypeScript. Brevier writes them to JSON the same way in every language. From Java and Python classes, it also writes a JSON Schema and a starting template.

    JavaPythonC#TypeScript

Install anywhere

Install Brevier with pip, a one-line script or Docker. It runs on Linux, macOS and Windows.

Call it from your language
  • pip
  • Linux and macOS
  • Windows
  • Docker