Easy beautiful PDF generation with — or without — Meteor

When we were developing EducationLink, we saw the need to generate PDFs, nothing unusual, right?

Our “technical” requirements

We started trying different options, our requirements were:

  • High quality HTML to PDF
  • Fast to generate the file
  • Reliably consistent
  • Support for full HTML5 tags and CSS3 (and even JS)
  • If possible, inexpensive operation to do it.

In an era that everything is an API, or at least we have a NPM package to help. It was interestingly difficult to find an easy, high quality, and reliable HTML to PDF generation.

Our product requirements

In our software, we generate quotes. We wanted to allow our users to just upload an HTML with a custom template, and the system would generate the quote exactly how they wanted it.

Every single option we’ve tried didn’t have the quality we were expecting. When you generate a PDF from a Google Sheets, it’s masterfully done, so why couldn’t we find something?

Then we discovered DocRaptor and PrinceXML. We also discovered that Google Docs uses PrinceXML to do HTML to PDF, interesting…

DocRaptor API and PrinceXML

As it turns out, PrinceXML is the go-to solution for HTML to PDF conversion. It’s beautiful; the parser is great, and you get exactly your HTML, but in PDF format and with some nice features to manipulate, header, footer, pages, etc.

Via DocRaptor we have an easy API to generate PDFs, which uses PrinceXML as the engine. It’s dead easy.

People from PrinceXML know they have basically the only product in the market with such quality, so they are a little pricey. For a startup to spend USD 3k just for a PDF engine was not worth it (with dev-ops to keep it running).

And they sell just the software, you have to do all the heavy lifting of implementing and managing it.

We’ve managed to abstract PDF syntax, engine, dev-ops and focus in providing the best product, when we start using DocRaptor. Here it is what takes:

import request from 'request';
const data = {
url: 'https://docraptor.com/docs',
encoding: null, // Binary body response instead of text.
headers: {
'Content-Type': 'application/json',
},
json: {
user_credentials: apiKey, // Your API key
doc: {
document_content: content,
type: 'pdf',
test: false,
prince_options: {
media: 'screen',
},
},
},
};
request.post(data, (error, response) => {
// And... done.
});

That’s literally what takes.

We send a HTML, and we get a high quality PDF. That’s what we wanted from the start.

We provide a B2B software where the PDF generation is a key part of our users daily workflow. So reliability was a key point for us, and I’m happy to say, it never failed. After one year using it, it’s just works.

Meteor

As we use Meteor, we had to adapt it to use a method and to be sync instead of async.


import { Meteor } from 'meteor/meteor';
import
{ ValidatedMethod } from 'meteor/mdg:validated-method';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import request from 'request';
export const create = new ValidatedMethod({
name: 'pdf.create',

validate: new SimpleSchema({
content: {
type: String,
},
}).validator(),

run({ content }) {
const settings = Meteor.settings.private;
const apiKey = settings.docRaptor.apiKey;

const config = {
url: 'https://docraptor.com/docs',
encoding: null, // Binary body response instead of text.
headers: {
'Content-Type': 'application/json',
},
json: {
user_credentials: apiKey,
doc: {
document_content: content,
type: 'pdf',
test: true,
prince_options: {
media: 'screen',
},
},
},
};
    // If it's not PROD, mark the PDF as a test
if (settings.env === 'PROD') {
config.json.doc.test = false;
}
    // Create a sync request.post function
const
createPDF = Meteor.wrapAsync(request.post, request);

try {
const response = createPDF(config);
      return response.body;
} catch (error) {
throw new Meteor.Error('pdf-generation');
}
},
});

Done.

I love Meteor for it’s simplicity and powerful possibilities. So with this piece of code we’ve just got a just as simple and powerful PDF engine.

No dev-ops. It just works.

New PrinceXML version

Every license of PrinceXML is USD 3k. With DocRaptor we have automatic (controlled) updates, which is also great.

Price

Not expensive, but not that inexpensive either if you have to generate tons of PDFs. But if you consider the amount of time saved, it’s definitely worth it.

Cheers.