Skip to content

Typst Report¤

The TypstReport class lets you build PDF reports from your matplotlib figures using Typst. You compose a report by adding paragraphs and figure grids, then compile everything to a PDF with a single call.

Prerequisites¤

You need the typst CLI installed to compile reports to PDF. See the Typst installation guide.

# macOS
brew install typst

# or via cargo
cargo install typst-cli

Basic usage¤

Create a report, add some content, and save it:

from bessaplots import TypstReport

report = TypstReport(
    title="My Experiment Results",
    author="J. Doe",
    paper_size="a4",
)

report.add_paragraph("This report summarises the results of our experiment.")
report.add_figures(["figures/fig1.pdf", "figures/fig2.pdf"], columns=2)

# Writes report.typ and compiles report.pdf
report.save("report")

The date parameter defaults to today's date. You can set it explicitly or pass an empty string to omit it:

# Explicit date
report = TypstReport(title="Report", date="2026-01-15")

# No date line
report = TypstReport(title="Report", date="")

Adding figures¤

The add_figures() method places images in a grid layout. It supports several options for controlling the layout.

Columns¤

Pass an integer for equal-width columns, or a list of Typst width strings for custom widths:

# Two equal-width columns
report.add_figures(["fig1.pdf", "fig2.pdf"], columns=2)

# Custom column widths (1:2 ratio)
report.add_figures(["fig1.pdf", "fig2.pdf"], columns=["1fr", "2fr"])

Captions and subcaptions¤

Add a caption to wrap the grid in a Typst #figure block with automatic numbering. Use subcaptions for per-image labels:

# Overall caption
report.add_figures(
    ["fig1.pdf", "fig2.pdf"],
    columns=2,
    caption="Comparison of methods A and B.",
)

# Per-image subcaptions
report.add_figures(
    ["fig1.pdf", "fig2.pdf"],
    columns=2,
    caption="Comparison of methods A and B.",
    subcaptions=["Method A", "Method B"],
)

Splitting across pages¤

When you have many figures, use rows_per_page to automatically insert page breaks:

# 3 columns, max 2 rows per page
report.add_figures(
    [f"fig{i}.pdf" for i in range(12)],
    columns=3,
    rows_per_page=2,
    caption="All results.",
)

The caption is placed on the last page only.

Write and compile separately¤

If you want to inspect or edit the .typ source before compiling, use write() and compile() separately:

# Step 1: generate the .typ source file
typ_path = report.write("report")
print(typ_path)  # /absolute/path/to/report.typ

# Step 2: compile to PDF
pdf_path = report.compile(typ_path)
print(pdf_path)  # /absolute/path/to/report.pdf

Paper sizes¤

Three paper sizes are supported:

Value Paper size
"a4" A4 (default)
"letter" US Letter
"b5" ISO B5
report = TypstReport(title="US Letter Report", paper_size="letter")

Full example¤

Combining bessaplots figure creation with a Typst report:

import matplotlib.pyplot as plt
import numpy as np

from bessaplots import TypstReport, set_size

plt.style.use("bessaplots")

# Create two figures
figures = []
for _i, func in enumerate([np.sin, np.cos]):
    fig, ax = plt.subplots(figsize=set_size(paper_size="a4"))
    x = np.linspace(0, 2 * np.pi, 100)
    ax.plot(x, func(x))
    ax.set_xlabel("$x$")
    ax.set_ylabel(f"${func.__name__}(x)$")
    path = f"fig_{func.__name__}.pdf"
    fig.savefig(path, bbox_inches="tight")
    figures.append(path)
    plt.close(fig)

# Build the report
report = TypstReport(
    title="Trigonometric Functions",
    author="J. Doe",
    paper_size="a4",
)

report.add_paragraph(
    "This report shows the sine and cosine functions over one full period."
)

report.add_figures(
    figures,
    columns=2,
    caption="Sine and cosine.",
    subcaptions=["Sine", "Cosine"],
)

report.save("trig_report")