lightweight-pdfv0.3.0

CASOON Open Source

Business PDFs from pure Rust.

lightweight-pdf builds invoices, quotes, reports and certificates from a fixed set of layout primitives – with its own PDF writer and TrueType subsetter, natively or as wasm32 inside a Cloudflare Worker.

cargo add lightweight-pdf
cargo install lightweight-pdf-cli
MITcrates.io 0.3.0wasm32-unknown-unknownPDF/A-3b · PDF/UA-1
Top of page 1 of the demo invoice: logo, address block, invoice details and the start of the position table.
examples/demo_invoice.rs, rendered during this site's build ·open the PDF (23.4 KiB)
required third-party dependency (skrifa, for font parsing)
1
demo invoice PDF from this build, fonts subset and embedded
23.4 KiB
gzipped WASM module with fonts, measured with wrangler
590 KiB
per invoice, quote or report, native release build
~4 ms

What it does

  1. Pagination handled for you

    Two-pass layout keeps “Page X of Y” stable, splits tables across pages with a repeating header, honours widow/orphan rules and keep-with-next, and fills a table of contents with real page numbers.

  2. Own writer, own subsetter

    PDF objects, xref and streams are written by this repository, and only the glyphs a document uses are embedded. Streams are Flate-compressed by default; output is deterministic.

  3. Built for the edge

    The wasm32 build is part of CI and its gzip size is gated against a baseline. A Cloudflare Worker starter and a browser playground live in examples/.

  4. JSON in, PDF out

    Documents serialise to a versioned JSON format. Templates resolve {{placeholders}} and $each rows against a data file, and the lwpdf CLI renders both without Rust code.

  5. Standards on request

    PDF/A-3b, ZUGFeRD/Factur-X invoice embedding and Tagged PDF/PDF-UA-1, each behind a Cargo feature and checked with veraPDF.

Generated at build time

All examples →
$ lwpdf validate examples/invoice-template.json --data examples/invoice-data.json
ok: examples/invoice-template.json is valid
$ lwpdf render examples/invoice-template.json --data examples/invoice-data.json -o invoice.pdf
wrote invoice.pdf (10435 bytes)

Captured while this site was built: the lwpdf CLI validating and rendering the template from examples/. The PDF it wrote is in the showcase.

scripts/render-site-showcase.sh

Quickstart

Three steps from install to a first PDF. The full walkthrough lives in the documentation.

  1. Add the crate: cargo add lightweight-pdf.
  2. Build a Document from text, tables, rows, lists and images.
  3. Call render() and write the bytes wherever you need them – or skip Rust and render JSON with lwpdf.
main.rsRust
use lightweight_pdf::*;

let mut doc = Document::new(PageFormat::A4)
    .margin(Margin::all(20.0))
    .footer(Footer::new(20.0, |ctx| {
        Text::new(format!("Page {} of {}", ctx.page, ctx.total_pages)).into()
    }));

doc.add(Text::new("Invoice").heading1());
doc.add(
    Table::new()
        .columns([TableColumn::flex(1.0), TableColumn::fixed(60.0).align(Align::End)])
        .header(["Item", "Amount"])
        .rows(vec![vec![Element::from("Consulting"), Element::from("1,200.00 USD")]]),
);

let bytes = doc.render().expect("render should succeed");
std::fs::write("invoice.pdf", bytes).unwrap();
terminalCLI
lwpdf render examples/invoice-template.json \
  --data examples/invoice-data.json -o invoice.pdf