Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

25 Commits

Repository files navigation

tinypdf

npmsizelicense

Minimal PDF creation library. <400 LOC, zero dependencies, makes real PDFs.

npm install tinypdf
Executive reportEvent ticket
Executive reportEvent ticket
KPI dashboard and chartBold landscape admission ticket
CertificateInvoice
CertificateInvoice
Formal award certificateEditorial studio invoice

Run any example with Bun, for example: bun examples/executive-report.ts.


Why tinypdf?

tinypdfjsPDF
Size3.3 KB229 KB
Dependencies02

~70x smaller. We removed TTF fonts, PNG/SVG, HTML-to-PDF, forms, encryption, and compression. What's left is the 95% use case: put text and images on a page.

Build with it

Invoices, receipts, reports, shipping labels, tickets, certificates, contracts, data exports

Features

FeatureDescription
TextHelvetica (WinAnsi), any size, hex colors, align left/center/right
ShapesRectangles and lines
ImagesJPEG (photos, logos, signatures)
LinksClickable URLs with optional underline
PagesMultiple pages, custom sizes
MarkdownConvert markdown to PDF with headers, lists, rules

Not included

Unicode/custom fonts, PNG/GIF/SVG, vector graphics, forms, encryption, compression, HTML-to-PDF

Need those? Use jsPDF or pdf-lib.


Quick start

import{pdf}from'tinypdf'import{writeFileSync}from'fs'constdoc=pdf()doc.page((ctx)=>{ctx.rect(50,700,200,40,'#2563eb')// blue rectanglectx.text('Hello PDF!',60,712,24,{color: '#ffffff'})ctx.line(50,680,250,680,'#000000',1)// black line})writeFileSync('output.pdf',doc.build())

Add images

import{readFileSync}from'fs'doc.page((ctx)=>{constlogo=newUint8Array(readFileSync('logo.jpg'))ctx.image(logo,50,700,100,50)})

Add links

import{pdf,measureText}from'tinypdf'doc.page((ctx)=>{consttext='Visit Example.com'consty=700ctx.text(text,50,y,14,{color: '#0066cc'})ctx.link('https://example.com',50,y-4,measureText(text,14),18,{underline: '#0066cc'})})

Measure text width

import{measureText}from'tinypdf'measureText('Hello',12)// => 27.34 (points)

Markdown to PDF

import{markdown}from'tinypdf'import{writeFileSync}from'fs'constpdf=markdown(`# Hello WorldA 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)

Stream large PDFs

Use buildStream() to emit a ReadableStream<Uint8Array> incrementally. Page content and image inputs are retained until the stream reaches them, but stream bodies are emitted directly and the final PDF is not assembled into one additional full-size buffer.

import{pdf}from'tinypdf'constdoc=pdf()for(leti=0;i<10_000;i++){doc.page((ctx)=>ctx.text(`Page ${i+1}`,50,750,12))}// Write to disk (Bun)awaitBun.write('huge.pdf',doc.buildStream())// Or serve as an HTTP responsereturnnewResponse(doc.buildStream(),{headers: {'Content-Type': 'application/pdf'},})

API

pdf()// create documentdoc.page(callback)// add page (612×792 default)doc.page(width,height,callback)// add page with custom sizedoc.build()// returns Uint8Arraydoc.buildStream()// returns ReadableStream<Uint8Array>ctx.text(str,x,y,size,options?)// options: { color, align, width }ctx.rect(x,y,w,h,fill)// filled rectanglectx.line(x1,y1,x2,y2,stroke,width?)// linectx.image(jpegBytes,x,y,w,h)// JPEG imagectx.link(url,x,y,w,h,options?)// options: { underline }measureText(str,size)// text width in pointsmarkdown(str,options?)// options: { width, height, margin }

Full example

See the complete invoice generator for a production-style layout using only tinypdf's core text, rectangle, and line primitives.


License

MIT

About

Minimal PDF creation library. <400 LOC, zero dependencies, makes real PDFs.

Topics

Resources

Stars

1.9k stars

Watchers

12 watching

Forks

Releases

Packages

Contributors

Languages