Early access One API · Rust, Java, JavaScript, Python and C#

PDFs that lay themselves out.

A document layout engine with the same API in Rust, Java, JavaScript, Python and C#. Compose pages from stacks, tables and charts — or design them in Construct — and PDFStreamline handles wrapping, page breaks, fonts and PDF/A, with the same pages in every language.

  • Rust 1.85+
  • Java 8+
  • Node 20.16+ & browsers
  • Python 3.11+
  • .NET 9
  • Works offline
PDF/A-3b · PDF/UA-1
Headers repeat on every page
RTL & complex scripts
20+ vector chart types
1import static com.pdfstreamline.Pdf.*;2import com.pdfstreamline.model.components.chart.Chart;3import com.pdfstreamline.model.components.text.list.ListText;4import com.pdfstreamline.render.Conformance;5 6document()7 .conformance(Conformance.PDF_A_3B)8 .add(page(yStack(9 xStack(image("logo.png"), spacer(),10 text("Invoice").fontSize(26)).itemsCenter(),11 text("Billed to " + customer.name()),12 table("Description", "Qty", "Amount") // header on every page13 .rows(lines, l -> new Object[]{l.name(), l.qty(), l.total()})14 .cellPadding(6),15 Chart.bar().data(revenue).x("month").y("amount"),16 ListText.instance()17 .addListItem("Payment due within 30 days")18 .addListItem("Pay by bank transfer or card"),19 text("Thank you for your business!"))20 .gap(12).padding(48).fillWidth()))21 .save("invoice.pdf");22
Invoice

Billed to Acme Robotics GmbH

DescriptionQtyAmount
Platform licence — annual1$4,800.00
Priority support12$1,440.00
Onboarding workshop2$900.00
JanFebMarAprMayJunJul
  • Payment due within 30 days
  • Pay by bank transfer or card
Thank you for your business!
Live preview Java · Ln 22
Three ways in · one document

Write it in code. Draw it in Construct.
Feed it a spreadsheet.

Every path produces the same document tree, so a design never gets stuck in one tool. The XML template is the bridge — copy it out of Construct, load it from Rust, Java, JavaScript, Python or C#, and back again. See how →

// Paste XML straight from Construct (Java 15+ text block)…
SLTemplate cert = SLTemplates.fromXml("""
    <page size="a4" orientation="LANDSCAPE">
      <yStack crossAxisAlignment="CENTER" gap="6">
        <text fontSize="9" bold="true">CERTIFICATE OF COMPLETION</text>
        <text fontSize="30" italic="true">{{name}}</text>
        <text fontColor="#6b7280">{{course}} · {{date}}</text>
      </yStack>
    </page>""");

// …or mix it with plain Java
Document doc = cert
    .bind("name", student.fullName())
    .bind("course", "Applied Data Science")
    .bind("date", LocalDate.now())
    .build();

doc.save("certificate.pdf");
CERTIFICATE OF COMPLETION

Aisha Rahman

Applied Data Science · 25 September 2026

InstructorDirector
Everything a document needs

A layout engine,
not a drawing API.

Low-level PDF libraries make you place every string at an x and y. PDFStreamline measures, wraps, splits and paginates for you — and ships the components real documents are made of, in every one of its five languages.

Layout

Stacks, grids and flow — like UI code

XStack, YStack and ZStack with FIT / FILL sizing, main and cross-axis alignment, margins, padding and borders. Content that runs long flows onto the next page on its own, with table headers repeated.

FIT
FILL
FIT
YStack · gap 8
ZStack

↳ table split across pages · header repeated · nothing clipped

Typography

Every script, shaped properly

Professional text shaping for every script, bundled font families with glyph fallback, embedding and subsetting, right-to-left layout, rich runs, drop caps and widow/orphan control.

Invoice Latin
فاتورة Arabic · RTL
चालान Devanagari
請求書 CJK
Charts

20+ chart types, vector-sharp

Bar, line, area, pie, scatter, radar, heatmap, treemap, waterfall, funnel, gauge, candlestick, box plot, histogram, Gantt and more — bound to your data and drawn as vectors, not pasted as images.

Compliance

Archive-ready, accessible, protected

Emit PDF/A and tagged PDF/UA with alt text in every language, check them with the built-in checkers, or lock a file with AES-256 passwords and permissions.

PDF/A-2bPDF/A-2uPDF/A-2aPDF/A-3bPDF/UA-1Alt textAES-256
Structure

Long documents, handled

Sections, table of contents, footnotes, cross-references, internal links, headers and footers with page numbers.

1 · Executive summary3
2 · Revenue by region7
3 · Appendix A14
Forms

Fillable PDFs

Text fields, checkboxes, radio groups, dropdowns, list boxes and signature fields.

Full name
Aisha Rahman
Sign here
Batch

From one record to a million

Turn any design into a Template<T> and render a batch to a folder, a ZIP or memory — in parallel in every language (threads in Java and .NET, worker processes in Python, worker_threads in Node) — with error policies, progress callbacks and a latency report. Single documents can render asynchronously with progress updates, and the streaming writer writes pages as they finish, so the output never sits in memory twice.

Template.of(this::invoice).batch(invoices).parallel()
  .output(Sink.zip(out, inv -> inv.number + ".pdf")).run();
rendering 0 / 10,000 · 8 threads
Extras

And the long tail

Diagrams (flowchart, Gantt, org chart, timeline), icons, SVG paths, gradients, pattern backgrounds, shadows, text, logo and icon watermarks, themes and element presets — plus SVG, PNG, JPEG and WebP pages.

Fast · measured

Big documents.
Done in milliseconds.

Long tables, batches of invoices and hundred-page reports render in a fraction of a second, with nothing else to install — no PDFBox, no headless browser.

4× faster than QuestPDF

A 3,000-row table, 79 pages, laid out and written to PDF.

ms per document · lower is better
0.7 s for 30,000 rows

790 pages. Even 100,000 rows take 2.4 s, with memory staying near 100 MB.

ms per document · lower is better

Warm renders of one table document on an Apple Silicon Mac. QuestPDF lays the same rows out on 77 and 770 pages where PDFStreamline uses 79 and 790, so it is a reference, not an identical document. All PDFStreamline figures include the evaluation watermark. Performance details →

Five languages · one API

Same API. Same pages.
Your language.

Pick the language your project already uses. The classes and methods are the same in each — only the naming follows the language — and a document gets the same line breaks, page breaks and positions everywhere.

Java

8+

One self-contained jar for Linux, macOS and Windows, fonts included — add it to the classpath and go.

java -cp pdfstreamline-1.0.0.jar:. Hello
import static com.pdfstreamline.Pdf.*;

document()
    .add(text("Hello").fontSize(28))
    .save("hello.pdf");

JavaScript

Node 20.16+ · browsers

ES modules for Node 20.16+ and modern browsers, with everything bundled.

npm install @pdfstreamline/core
import { Document, Text } from '@pdfstreamline/core';

Document.instance()
  .add(Text.of('Hello').fontSize(28))
  .save('hello.pdf');

Python

3.11+

A wheel for Linux, macOS and Windows: pip install it and start building documents.

pip install pdfstreamline
from pdfstreamline import Document, Text

(Document.instance()
    .add(Text.of("Hello").font_size(28))
    .save("hello.pdf"))

C#

.NET 9

A NuGet package for every platform; implicit usings keep files short.

dotnet add package PdfStreamline
Document.Instance()
    .Add(Text.Of("Hello").FontSize(28))
    .Save("hello.pdf");

Rust

1.85+

A crate with the full API: layout, text, tables, charts, barcodes and PDF output. Latin fonts are built in; the script-fonts feature adds Arabic, Devanagari, Thai and more.

cargo add pdfstreamline
use pdfstreamline::*;

Document::new()
    .add(Text::of("Hello").font_size(28))
    .save("hello.pdf")?;
  • Same namesfontSize in Java and JavaScript, font_size in Rust and Python, FontSize in C#.
  • Same pagesLine breaks, page breaks and positions are identical in every language.
  • Runs everywhereLinux, macOS and Windows on x64 and arm64, and in modern browsers.
Construct · the visual editor for PDFStreamline

Design visually.
Keep the XML — or the code.

Construct is a drag-and-drop editor, an XML editor and a live preview rendered by the real engine — side by side, always in sync. Every design is an XML template your code loads in Java, JavaScript, Python or C#, and anything your code builds can be pasted back in to edit visually. Three studios, one app: Design, Chart and Code.

invoice.slx — Construct
TreeDesignXMLPreviewData Merge
⌘K
Layout
Y Stack
X Stack
Z Stack
Grid
Content
Text
Table
Image
List
Chart
Your components
Invoice header
Totals
Icon + label
Invoice
Billed to{{customer.name}}
Due{{dueDate}}
DescriptionQtyAmount
{{description}}{{qty}}{{amount}}
{{description}}{{qty}}{{amount}}
Total{{total}}
<yStack gap="14"> <xStack mainAxisAlignment="SPACE_BETWEEN"> <text fontSize="12" bold="true">Northwind</text> <text fontSize="22">Invoice</text> </xStack> <table id="lineItems" repeat="lines" skipRows="1" headerRows="1"> <cell row="0" column="0"><text>Description</text></cell> <cell row="1" column="0"><text>{{description}}</text></cell> <cell row="1" column="2"><text>{{amount | money}}</text></cell> </table> <xStack mainAxisAlignment="END"> <text bold="true">Total {{total}}</text> </xStack> </yStack>
Table · lineItems
Repeat over lines
Columns 3
Header rows 1
Style Striped grid
Grid line 0.75
Box
Padding 6 · 4
Width FILL
Preview data
Source sample.json
Construct → code⌘C any element or save the .slx, then SLTemplates.loadXml(…), bind your data and build().
Code → ConstructSLTemplates.toXml(element) prints anything your code builds. Paste it in and keep designing.
Gen codeOne click turns the design into Java, JavaScript, Python or C# source — fields become parameters, repeats become loops.
Code StudioMark a function with @PdfPreview and watch its pages redraw every time you save in your IDE.
Saves as you goEvery change in the design or the XML is saved straight into the .slx — even a new design, into a temporary file until you name it.
Reusable componentsRight-click anything › Save as component: keep it in this document or for all of them, and drop it into the next design.
A realtime previewThe page redraws as you edit — about 19 ms per change, even on an 81-page report — and what you see is exactly the PDF your code gets.
Tables that look finishedOne-click table styles — striped rows, a dark or coloured header band, grid, ledger, boxed — plus totals, groups and calculated columns.

Charts, too. Chart Studio charts cells you paste, a linked CSV or Google Sheet, or your document's data, in 30 chart types — export a PNG, SVG or PDF, or drop it into a document as a live chart. And the For developers menu opens the XML editor, Gen code and Code Studio when you want full control. How Construct and code fit together →

No code required

One spreadsheet in.
A thousand PDFs out.

Design a template once, connect a CSV, an Excel file or a Google Sheet, and generate a finished, personalised PDF for every row. Built for operations, HR, schools, events and anyone who has ever mail-merged by hand.

attendees.xlsx · 1,243 rows
namecoursescore
Aisha RahmanApplied Data Science96
Lucas FerreiraApplied Data Science88
Mei TanakaApplied Data Science91
Omar HaddadApplied Data Science84
Sofia NovakApplied Data Science93
CERTIFICATE OF COMPLETION

Omar Haddad

Applied Data Science

CERTIFICATE OF COMPLETION

Mei Tanaka

Applied Data Science

CERTIFICATE OF COMPLETION

Aisha Rahman

Applied Data Science · score 96

InstructorDirector
01Start from a templateCertificates, invoices, badges, labels, letters and tickets — or design your own.
02Connect your dataCSV, Excel, a Google Sheet or pasted rows, with a photo per row if you like. Columns auto-match to fields; format dates and money in a click.
03Check every rowFlip through records, and get warned when a value is missing or looks too long for its field.
04GenerateOne PDF per row with your naming pattern, delivered as a ZIP, or one combined print-ready file.
🎓 Course certificates🏷️ Name badges & labels🧾 Invoices from exports✉️ Personalised letters🎟️ Event tickets with QR📋 Report cards💼 Payslips📦 Shipping labels
Choosing an approach

Why a layout engine?

There are three common ways to produce PDFs, whatever your stack. Each is good at something — here is where PDFStreamline sits.

Low-level drawing APIsHTML → PDFReport designersPDFStreamline
Automatic layout & page breaks✕ you position everything✓ via CSS◐ band-based✓ stacks, grids, flow
Author in code, type-checked✓ ✕ HTML strings✕ designer files✓ fluent API
One API in Rust, Java, JavaScript, Python & C#✕ usually one per library◐ per-language wrappers✕ ✓ identical layout
Visual editor✕ ◐ any HTML tool✓ ✓ Construct · web & desktop
Same template in code and editor✕ ◐ ◐ ✓ XML or generated code
No browser engine in production✓ ✕ often headless Chrome✓ ✓ native library per language
Charts & diagrams built in✕ ◐ JS libraries✓ ✓ native vector
Non-developers can generate PDFs✕ ✕ ◐ ✓ Construct Data Merge
Questions

Good to know

Do I need to write code to use PDFStreamline?

No. Construct, the visual editor, has a Data Merge mode that lets anyone design a template, connect a spreadsheet and generate PDFs without writing a line of code. Developers get the same template as XML that the library loads in Java, JavaScript, Python or C#.

Which languages and platforms are supported?

Rust 1.85+, Java 8 and newer, JavaScript on Node 20.16+ and in modern browsers, Python 3.11+, and C# on .NET 9 — on Linux, macOS and Windows, on x64 and arm64. Fonts and text shaping come with the library; nothing else has to be installed.

Do all five languages produce the same PDF layout?

Yes. The same document gets the same line breaks, page breaks and positions in every language, and the classes and methods are the same too — only the naming follows each language (fontSize, font_size, FontSize). A template you design in Construct comes out the same from any of them.

Does PDFStreamline need PDFBox or a browser?

No. PDFStreamline lays out and writes the PDF itself, so there is nothing else to install or run: no Apache PDFBox, no iText and no headless browser.

How does Construct talk to my code?

Through XML templates, in both directions. Save a design as an .slx file (or copy any element with ⌘C in Developer mode) and load it with SLTemplates.loadXml(…) or fromXml(…) — load_xml / from_xml in Python, LoadXml / FromXml in C# — then bind your data and build. Going the other way, SLTemplates.toXml(element) prints anything your code builds as XML that you paste or open in Construct. Gen code turns a design into Java, JavaScript, Python or C# source, and Code Studio previews the documents your own code builds, live as you save.

What is the difference between Construct on the web and on the desktop?

They are the same app, and the web edition is available today. The desktop edition, coming to macOS and Windows, adds native file access — open and save .slx templates on disk, watch them for changes, render entirely offline — and Code Studio, which compiles and runs your own project to preview its documents.

Is my data uploaded anywhere?

No. In the desktop app everything happens on your computer, and in the browser everything happens inside the tab: your spreadsheet and your pages are never uploaded.

Early access

Stop positioning text.
Start shipping documents.

Join the early-access list for the library and Construct, the visual editor for web and desktop.