Generating PDF Reports in TypeScript: PDF-Lib Library

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Generating PDF Reports in TypeScript with the PDF-Lib Library



In modern web development, there is often a need to create complex PDF documents: reports, invoices, certificates, or analytical dashboards. TypeScript, thanks to its strict typing, makes this process reliable and predictable. Among the many libraries for working with PDF on the Node.js platform and in the browser, PDF-Lib stands out — a lightweight, powerful tool written entirely in TypeScript.



PDF-Lib does not require installing additional native dependencies (unlike heavyweight solutions like Puppeteer or wkhtmltopdf), works both in Node.js and the browser, and supports all modern PDF features: embedding fonts, images, creating forms, annotations, and much more.



Installation and First Document



To get started, simply install the package via npm:



npm install pdf-lib


Let's create a simple PDF document with text:



import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';

async function createSimplePdf() { // Create a new PDF document const pdfDoc = await PDFDocument.create();

// Add a page (A4 format) const page = pdfDoc.addPage([595.28, 841.89]); // A4 in points

// Embed a standard font const font = await pdfDoc.embedFont(StandardFonts.Helvetica);

// Draw text page.drawText('Hello, World!', { x: 50, y: 700, size: 30, font: font, color: rgb(0.2, 0.4, 0.8), });

// Save the document to bytes const pdfBytes = await pdfDoc.save(); return pdfBytes;}

// Usage examplecreateSimplePdf().then((bytes) => { // In Node.js, you can write to a file // require('fs').writeFileSync('hello.pdf', bytes); console.log('PDF created! Size:', bytes.length, 'bytes');});


Working with Russian Text and Custom Fonts



One of the key tasks when generating reports in Russian is the correct display of Cyrillic characters. Standard PDF fonts (Helvetica, Times, Courier) do not contain Cyrillic glyphs. The solution is to embed a TrueType font with Unicode support.



import { PDFDocument, rgb } from 'pdf-lib';import fontkit from '@pdf-lib/fontkit';import fs from 'fs';

async function createRussianPdf() { const pdfDoc = await PDFDocument.create();

// Register fontkit for working with custom fonts pdfDoc.registerFontkit(fontkit);

// Load a font with Cyrillic support (e.g., Roboto) const fontBytes = fs.readFileSync('Roboto-Regular.ttf'); const customFont = await pdfDoc.embedFont(fontBytes);

const page = pdfDoc.addPage([595.28, 841.89]);

page.drawText('Generating a Report in TypeScript', { x: 50, y: 750, size: 24, font: customFont, color: rgb(0, 0, 0), });

page.drawText('Date: 2024-01-15', { x: 50, y: 700, size: 14, font: customFont, color: rgb(0.3, 0.3, 0.3), });

return await pdfDoc.save();}


Creating Tables and Structured Reports



PDF-Lib does not have a built-in module for tables, but they are easy to implement manually by drawing lines and positioning text. For convenience, you can create a helper function:



interface TableCell {  text: string;  width: number;  height?: number;  align?: 'left' | 'center' | 'right';}

async function drawTable( page: PDFPage, headers: TableCell[], rows: TableCell[][], startX: number, startY: number, font: PDFFont, fontSize: number = 12) { const cellPadding = 5; const rowHeight = fontSize + 2 * cellPadding; let currentY = startY;

// Draw headers let currentX = startX; for (const header of headers) { page.drawRectangle({ x: currentX, y: currentY - rowHeight, width: header.width, height: rowHeight, color: rgb(0.9, 0.9, 0.9),

Recommendations