Install tinypdf via npm
mainInstall the tinypdf library using npm to start creating minimal PDFs with zero dependencies.
npm install tinypdfrepository·main·Indexed 23 days ago
https://github.com/lulzx/tinypdfA minimal, zero-dependency PDF creation library (v0.3.1) designed for high performance and small bundle size. It provides a PDFBuilder for placing text, JPEG images, and vector shapes (rectangles, lines) on pages. Features include a markdown-to-PDF converter supporting headers, lists, and horizontal rules, as well as a buildStream method for streaming large documents as a ReadableStream<Uint8Array> to save memory.
Install the tinypdf library using npm to start creating minimal PDFs with zero dependencies.
npm install tinypdfTo create a basic PDF, import pdf from tinypdf, initialize a document, and use doc.page() to define a drawing context. Within the callback, you can use methods like ctx.rect, ctx.text, and ctx.line to draw elements. Finally, call doc.build() to get a Uint8Array of the PDF content.
import { pdf } from 'tinypdf'
import { writeFileSync } from 'fs'
const doc = pdf()
doc.page((ctx) => {
ctx.rect(50, 700, 200, 40, '#2563eb') // blue rectangle
ctx.text('Hello PDF!', 60, 712, 24, { color: '#ffffff' })
ctx.line(50, 680, 250, 680, '#000000', 1) // black line
})
writeFileSync('output.pdf', doc.build())For documents that are too large to fit in memory, use doc.buildStream() instead of doc.build(). This returns a ReadableStream<Uint8Array> that emits the PDF data one object at a time, making it suitable for writing to disk or serving via HTTP.
import { pdf } from 'tinypdf'
const doc = pdf()
for (let i = 0; i < 10_000; i++) {
doc.page((ctx) => ctx.text(`Page ${i + 1}`, 50, 750, 12))
}
// Write to disk (Bun)
await Bun.write('huge.pdf', doc.buildStream())
// Or serve as an HTTP response
return new Response(doc.buildStream(), {
headers: { 'Content-Type': 'application/pdf' },
})To add a clickable URL, use ctx.link(url, x, y, w, h, options?). A common pattern is to use measureText to determine the width of the text being linked to ensure the clickable area matches the text size.
import { pdf, measureText } from 'tinypdf'
doc.page((ctx) => {
const text = 'Visit Example.com'
const y = 700
ctx.text(text, 50, y, 14, { color: '#0066cc' })
ctx.link('https://example.com', 50, y - 4, measureText(text, 14), 18, { underline: '#0066cc' })
})You can add JPEG images to a page using ctx.image(). This method requires a Uint8Array of the JPEG bytes.
import { readFileSync } from 'fs'
doc.page((ctx) => {
const logo = new Uint8Array(readFileSync('logo.jpg'))
ctx.image(logo, 50, 700, 100, 50)
})Use measureText(str, size) to calculate the width of a string in points for a given font size. This is useful for alignment and calculating link bounding boxes.
import { measureText } from 'tinypdf'
measureText('Hello', 12) // => 27.34 (points)The markdown(str, options?) function allows you to generate a PDF directly from a markdown string. It supports headers (h1, h2, h3), bullet lists, numbered lists, and horizontal rules. It includes automatic word wrapping and pagination.
Options include width, height, and margin.
import { markdown } from 'tinypdf'
import { writeFileSync } from 'fs'
const pdf = markdown(`
# Hello World
A minimal PDF from markdown.
## Features
- Headers (h1, h2, h3)
- Bullet lists
- Numbered lists
- Horizontal rules
---
Automatic word wrapping and pagination included.
`)
writeFileSync('output.pdf', pdf)Standalone utility functions.
measureText(str, size) // text width in points
markdown(str, options?) // options: { width, height, margin }Methods available within the doc.page callback to draw elements on the page.
ctx.text(str, x, y, size, options?) // options: { color, align, width }
ctx.rect(x, y, w, h, fill) // filled rectangle
ctx.line(x1, y1, x2, y2, stroke, width?) // line
ctx.image(jpegBytes, x, y, w, h) // JPEG image
ctx.link(url, x, y, w, h, options?) // options: { underline }Methods for managing the PDF document and its pages.
pdf() // create document
doc.page(callback) // add page (612×792 default)
doc.page(width, height, callback) // add page with custom size
doc.build() // returns Uint8Array
doc.buildStream() // returns ReadableStream<Uint8Array>Insert a JPEG image into the page.
Parameters:
jpegBytes: A Uint8Array containing the JPEG data.x: X-coordinate.y: Y-coordinate.w: Width.h: Height.A high-level utility to convert a Markdown string directly into a Uint8Array PDF document.
Parameters:
md: The Markdown string.opts?: { width?: number; height?: number; margin?: number }: Document dimensions and margins. Defaults are width: 612, height: 792, and margin: 72.Supported Markdown Features:
# to ######)-, *, or 1. )---, ***, or ___)