How-to guides/PDF Generation

Create a new PDF document from scratch in Rust

Build a PDF programmatically. Add pages, text, images, and set document metadata without any source file.

rust
use pdfluent::{PdfDocument, Page, PageSize, TextOptions, Color, Font};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::new();

    doc.set_title("Quarterly Report Q1 2024");
    doc.set_author("Finance Team");

    let mut page = Page::new(PageSize::A4);

    page.add_text(
        "Quarterly Report",
        TextOptions {
            x: 50.0,
            y: 780.0,
            font_size: 28.0,
            color: Color::rgb(10, 10, 10),
            ..TextOptions::default()
        },
    )?;

    page.add_text(
        "Q1 2024 — Revenue: EUR 1,240,000",
        TextOptions {
            x: 50.0,
            y: 740.0,
            font_size: 14.0,
            color: Color::rgb(80, 80, 80),
            ..TextOptions::default()
        },
    )?;

    doc.add_page(page);
    doc.save("quarterly-report.pdf")?;
    Ok(())
}
Install:cargo add pdfluentDownload SDK →

Step by step

1

Add PDFluent to Cargo.toml

Creating PDFs from scratch requires only the base crate.

rust
# Cargo.toml
[dependencies]
pdfluent = "0.9"
2

Create a new document and set metadata

PdfDocument::new() creates an empty PDF 1.7 document. Set XMP and DocInfo metadata before adding content.

rust
use pdfluent::PdfDocument;

let mut doc = PdfDocument::new();

doc.set_title("Quarterly Report Q1 2024");
doc.set_author("Finance Team");
doc.set_subject("Financial summary");
doc.set_creator("pdfluent 0.9");
3

Create a page and set its size

Page::new() accepts a PageSize enum or custom dimensions in points. Common sizes: A4 is 595x842 pt, US Letter is 612x792 pt.

rust
use pdfluent::{Page, PageSize};

// Standard A4
let mut page = Page::new(PageSize::A4);

// Custom size: 200 x 100 mm
let mut page = Page::new(PageSize::custom_mm(200.0, 100.0));

println!("Page: {}x{} pt", page.width(), page.height());
4

Add text with position and style

PDF coordinates start at the bottom-left corner. Use font_size, color, and an optional embedded font to control appearance.

rust
use pdfluent::{TextOptions, Color};

page.add_text(
    "Invoice #INV-2024-042",
    TextOptions {
        x: 50.0,
        y: 780.0,
        font_size: 22.0,
        color: Color::black(),
        ..TextOptions::default()
    },
)?;

page.add_text(
    "Due: 2024-05-01",
    TextOptions {
        x: 50.0,
        y: 750.0,
        font_size: 11.0,
        color: Color::rgb(100, 100, 100),
        ..TextOptions::default()
    },
)?;
5

Draw lines, rectangles, and add images

Use the page drawing API for visual structure. Add a horizontal rule under a header or a bounding box around a table.

rust
use pdfluent::{Image, ImagePosition, Rect, StrokeOptions};

// Horizontal line
page.draw_line(50.0, 720.0, 545.0, 720.0, StrokeOptions {
    width: 1.0,
    color: Color::rgb(200, 200, 200),
})?;

// Filled rectangle
page.draw_rect(Rect {
    x: 50.0, y: 100.0, width: 495.0, height: 40.0,
}, Color::rgb(240, 245, 255), None)?;

// Image
let logo = Image::from_file("logo.png")?;
page.add_image(&logo, ImagePosition {
    x: 400.0, y: 780.0, width: 100.0, height: 40.0,
})?;

// Add page to document and save
doc.add_page(page);
doc.save("invoice.pdf")?;

Notes and tips

  • The 14 standard PDF fonts (Helvetica, Times-Roman, Courier) do not need embedding. For any other typeface, load a TTF/OTF and call doc.embed_font() before use.
  • Pages are added in the order you call doc.add_page(). Insert a page at a specific position with doc.insert_page(index, page).
  • For multi-page documents with repeated headers and footers, build a shared layout function that accepts a &mut Page and call it for each page.
  • doc.save() writes to a file. Use doc.to_bytes() to get a Vec<u8> for in-memory handling, S3 uploads, or HTTP responses.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions