DEV Community

KinetiNode
KinetiNode

Posted on • Edited on

I got tired of Puppeteer crashing my server, so I built a JSON-to-PDF engine using CSS Grid.

 Generating PDFs programmatically is a rite of passage for backend developers, and it is almost always a miserable experience.

If you are building a SaaS app, eventually a user is going to want an invoice, a monthly analytics report, or an ID badge. When that ticket hits your desk, you usually have two choices, and they both suck:

  1. The Headless Browser Nightmare (Puppeteer / Playwright)
    You wire up a headless instance of Chrome to screenshot a hidden webpage. Suddenly, your lightweight server needs 500MB of RAM just to boot, cold-starts take 4 seconds, and your Docker container size triples. It is absolute overkill just to print a table and a logo.

  2. The Low-Level PDF Library (pdf-lib)
    You decide to skip the browser and use a raw PDF library. But because PDFs are basically digital paper, these libraries don't understand HTML or CSS. You are forced to manually calculate X and Y coordinates for every single line of text.

If a user's name is too long? It doesn't wrap. It just bleeds over your pricing table.

I was building a reporting dashboard and got so fed up with debugging overlapping text that I decided to build a third option: A modular layout engine that compiles raw JSON into W3C-compliant PDFs.

Here is how I built it, and how you can use it.

The Architecture: Lego Blocks for Documents
I realized that 90% of business documents are just combinations of the exact same UI components:

A massive Header

A 2-column Metadata Grid (Dates, Invoice #, etc.)

A Data Table

A KPI summary

Instead of writing custom HTML for every new document, I built a routing engine that treats these components as pre-styled modules.

The engine receives a JSON array of "blocks". It reads the array from top to bottom, matches the block type to a pre-defined CSS template, injects the data, and stacks them together.

The JSON Payload
Instead of writing this:

// The old, painful way
pdfDoc.drawText('Total Due: $49.00', { x: 450, y: 120, size: 12 }); 
// Pray that the Y coordinate doesn't overlap the row above it...
Enter fullscreen mode Exit fullscreen mode

The engine just takes this:

{
  "filename": "invoice.pdf",
  "type": "modular",
  "blocks": [
    {
      "type": "hero_header",
      "data": { "title": "Invoice #1042", "subtitle": "Acme Corp" }
    },
    {
      "type": "invoice_table",
      "data": {
        "items": [
          { "description": "API Subscription", "qty": 1, "price": "49.00", "total": "49.00" }
        ],
        "subtotal": "49.00",
        "grand_total": "49.00"
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

How the Rendering Works
To avoid the bloat of Puppeteer, I bypassed browsers entirely. The backend maps the JSON directly into Jinja2 templates.

Those templates are styled using modern CSS features—including Flexbox and CSS Grid—and then passed through a native compiler (like WeasyPrint).

Because it uses real CSS, the engine automatically handles the heavy lifting that low-level libraries fail at:

Dynamic Word Wrapping: If a product description is 4 lines long, the row height expands automatically.

Page Breaks: Using page-break-inside: avoid, the engine knows exactly when a table is about to spill off the bottom of the page, and cleanly moves that row to the next page instead of cutting it in half.

Native Vector Charts: I built modules for Bar Charts and Line Graphs that render as raw SVGs, meaning they load in milliseconds and scale infinitely without pixelating.

Try It Out: The KinetiPDF API
Building the engine was a massive undertaking, but it completely solved my document generation bottlenecks.

If you are interested in the architecture, I highly recommend trying to build a JSON-router for your own templates! But if you have a deadline on Friday and just want to generate a PDF without fighting with server configs or headless Chrome, I packaged the entire engine into a serverless API.

It's called KinetiPDF.

It runs on edge infrastructure, has zero third-party dependencies, and handles all the CSS Flexbox math for you.

----> https://rapidapi.com/velocityproductsdigital/api/kineticpdf

You can test out the free tier right now. Let me know what you think of the JSON module approach, or if there are any specific layout blocks (like Gantt charts or Kanban boards) you'd want to see added to the engine!

Top comments (0)