“man wearing white top using MacBook” by Tim Gouw on Unsplash

Oh boy, what a struggle this is…

If you’ve ever tried to create a PDF file with JavaScript, you might have found yourself swearing occasionally and laying restlessly in bed at nights.

TL;DR

Tea-School.js is a package I made for creating a dynamic PDF file using HTML+CSS in Node.js

Example — A Complex Invoice PDF File

Let’s together walk together through a process of creating an invoice PDF file.

First let’s describe our invoice model (Using TypeScript):

Quite simple and straight forward.

Now let’s define our criteria for the PDF file generator:

Dynamic.

It’s not about creating a static brochure with known, solid information.

We want to generate different data for every invoice ID.

It’s not about creating a static brochure with known, solid information. We want to generate different data for every invoice ID. Internationalization (I18N).

Having a business in a non-English speaking country requires you to create invoices in the local language, including RTL support.

(I18N). Having a business in a non-English speaking country requires you to create invoices in the local language, including RTL support. Simple.

No one wants to write complex code, where they don’t understand most of the things they do, but the snippet shows it should work.

No one wants to write complex code, where they don’t understand most of the things they do, but the snippet shows it should work. HTML + CSS.

Creating a template with HTML and CSS is way way easier than building a PDF file using PDF specific method (e.g pdfFile.rectangle(0, 0, 100, 200) ).

Tea-School.js

There are several libraries who answer some of our criteria, yet I have not yet seen one who answers for all of them — Especially simplicity.

Struggling with this issue for several weeks, I finally found a possible solution:

Using the combination of Puppeteer and Pug.js.

For those who are not familiar with these two, Puppeteer is a headless Chrome JS library with all the functionality of a Chrome browser — including PDF creation out of a web page (HTML 👍), and pug.js a library for creating HTML templates and compiling them with dynamic data.

I went ahead and created a library to abstract most of the basic usage for creating a PDF with these two, and also adding node-sass to be able to use SASS as a dynamic CSS content.

Result: tea-school.js

ANECDOTE: In my native language (Hebrew) tea-school (tiscool) means FRUSTRATION. That was my state after trying to find a pretty solution for creating PDF files.

Usage

Let’s use this new lib to generate a simple looking invoice:

Beautifully, easily done

HTML Template

Our template file invoice-pdf.template.pug :

If you do not have experience with pug, don’t worry. They have a nice documentation so you could easily pick up what you need to create your template.

Notice the special compiledStyle key. This key is reserved for embedding the SASS style the lib compiles with the style file we provide

SASS Style File

invoice-pdf.scss

Generate The PDF

index.ts

You can check the example here as well.

Now this is not a that a short snippet, but it covers everything we need, and offers us flexibility.

The good thing here is that this is as simple as it can be:

You use the Node-Sass options to define what you need for your styling

You pass the path for the Pug template

You may also pass additional Pug data to be interpolated in the template

You use the Puppeteer options to define what you need for the PDF file

We’re missing the Invoice data, but you can fill it, and run the script (compile it first, or use ts-node ).

You will notice that you now have an invoice.pdf file in output folder (the folder must be created manually beforehand)

I hope I’ve helped some of you guys who struggled with this the same as I did.

Again, here is the link to the tea-school.js package.

If you like this post, please follow me on Medium and on Twitter