DEV Community

Cover image for Stop Fighting with PDF Libraries: Generate Dynamic PDFs Using HTML & JSON
ilyas özsaraç
ilyas özsaraç

Posted on

Stop Fighting with PDF Libraries: Generate Dynamic PDFs Using HTML & JSON

Generating PDFs in a web application is a task that almost every developer dreads. Whether it’s an invoice, a shipping label, or an event ticket, we usually find ourselves stuck between two extremes:

  1. Old-school libraries (mPDF, iText, etc.): These often feel like coding in the 90s. No Flexbox, no Grid, and very limited CSS support.
  2. Headless Browsers (Puppeteer/Playwright): They work great, but managing a headless Chromium instance in production is a DevOps nightmare. It’s memory-heavy, hard to scale, and slow to set up.

I wanted a middle ground. Something that lets me design with modern CSS and populate data with a simple JSON call. That’s why I built HookPDF.


The Problem: Decoupling Design from Logic

In most projects, your PDF design shouldn't be hardcoded into your backend logic. If you want to change the color of a button or the font size of a header, you shouldn't have to redeploy your entire API.

The ideal workflow should look like this:

  1. Design: Create a template using HTML/CSS.
  2. Define: Mark areas where dynamic data will go (variables).
  3. Generate: Send a JSON payload to an endpoint and get a PDF back.

Enter HookPDF

HookPDF is a developer-first API that handles the heavy lifting of PDF generation. You host your templates (or use ours), send your data via API, and we return a high-quality PDF.

How it works in 3 steps

1. Create your template (HTML/CSS)
Forget about weird coordinate systems. Use what you already know.

<div class="invoice-box">
    <h1>Invoice for {{customer_name}}</h1>
    <p>Amount Due: {{amount}}</p>
</div>
Enter fullscreen mode Exit fullscreen mode

2. Send the data (JSON)
HookPDF maps your JSON keys directly to your template variables.

{
    "customer_name": "John Doe",
    "amount": "$450.00"
}
Enter fullscreen mode Exit fullscreen mode

3. Get your PDF
Using a simple POST request (here is a Node.js example):

const response = await fetch("https://api.hookpdf.com/render", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer YOUR_API_KEY",
    },
    body: JSON.stringify({
        template_id: "your-template-uuid",
        payload: {
            customer_name: "John Doe",
            amount: "$450.00",
        },
        options: {
            page_size: "A4",
            orientation: "portrait",
        },
    }),
});

const job = await response.json();
// job => { job_id, status, is_preview, created_at }
Enter fullscreen mode Exit fullscreen mode

Then fetch the result from /reports/{job_id} to get output_url when the render is completed.

const reportResponse = await fetch(`https://api.hookpdf.com/reports/${job.job_id}`, {
    headers: {
        Authorization: "Bearer YOUR_API_KEY",
    },
});

const report = await reportResponse.json();
// report.output_url contains the signed PDF download link when status is "completed"
Enter fullscreen mode Exit fullscreen mode

Why this approach?

  • Modern CSS support: Since HookPDF uses a modern rendering engine, you can use Flexbox and Grid without issues.
  • Scalability: You don't have to worry about your server's RAM spiking because of 10 concurrent Puppeteer instances. The API handles the scaling.
  • Speed: HookPDF is optimized for low-latency generation.

What’s next?

I’ve recently launched the beta and I'm looking for developers to break it. If you’re tired of fighting with PDF layouts or managing heavy libraries, give it a try.

Check it out here: HookPDF.com

I’d love to hear your thoughts. What’s the biggest pain point you face when generating PDFs? Let’s discuss in the comments!

Top comments (0)