If you’ve ever had to build a dynamic PDF report in PHP, Node, or Python, you probably know the exact moment the nightmare begins.
It usually starts like this: "We just need a simple invoice/report PDF."
So you install a library like mPDF, wkhtmltopdf, or Dompdf. You write clean HTML and modern CSS, hit render... and everything breaks:
- Flexbox and Grid aren't supported.
- Page breaks split tables mid-row.
- Custom fonts fail to render.
- Memory usage spikes every time two users request a document simultaneously.
After spending 8 hours tweaking inline CSS and table borders, you end up with code that feels fragile and hard to maintain.
The Problem with "HTML-to-PDF" Libraries
Most legacy HTML-to-PDF converters rely on outdated browser rendering engines (often stripped-down forks from 10+ years ago).
When you build complex document structures — like multi-page financial statements, dynamic invoices with varying line items, or clean visual charts — you run into three main roadblocks:
- Broken Layouts: Modern CSS specs simply don't translate correctly to print/PDF view.
- Server Overhead: Rendering PDFs on your application server steals RAM and CPU cycles away from your core API logic.
- Endless Code Revisions: Every time marketing or accounting wants to change a logo, color, or table header, a developer has to modify code, re-test, and deploy.
A Better Approach: Separate Design from Data
What if your backend didn't have to care about fonts, CSS, or page boundaries at all?
What if your code only did what it does best — passing JSON data — while the layout lived safely in a visual builder designed specifically for print media?
That’s the exact workflow we designed with QuartzAPI.
Here is how the architecture looks:
[ Your Backend / DB ] ---> ( Sends JSON Payload ) ---> [ QuartzAPI ] ---> ( Returns PDF / Image )
Step 1: Design the Template Visually
Instead of fighting CSS in code, you build your document template in a drag-and-drop editor.
- Drag in dynamic text, tables, QR codes, images, and headers.
- Bind elements to variable names (e.g., {{invoice.number}}, {{customer.name}}).
- Set page break rules and repeating table headers with a single click.
Because the editor is built strictly for document layouts, what you see in the builder is exactly what gets rendered in the PDF.
Step 2: Render via a Simple REST API Call
Once your template is saved, generating a PDF from your application is just a single HTTP POST request.
Here is an example using cURL:
curl -X POST "https://api.quartzapi.com/v1/render" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "tpl_invoice_2026",
"data": {
"invoice_number": "INV-2026-001",
"client_name": "Acme Corp",
"items": [
{ "description": "API Integration", "price": 450.00 },
{ "description": "Cloud Hosting Setup", "price": 150.00 }
],
"total": 600.00
}
}'
Or in JavaScript (Node.js / Fetch):
const response = await fetch('https://api.quartzapi.com/v1/render', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
template_id: 'tpl_invoice_2026',
data: {
invoice_number: 'INV-2026-001',
client_name: 'Acme Corp',
items: [
{ description: 'API Integration', price: 450.00 }
]
}
})
});
const pdfBuffer = await response.arrayBuffer();
Your server stays lightweight, you save server resources, and you never have to debug mPDF line height bugs again.
Key Benefits of Using a Dedicated Document API
- Zero Layout Code in Backend: Your controllers remain clean and focused on business logic.
- Instant Design Updates: Non-developers (or developers wanting to save time) can update the document layout in the visual builder without requiring a new software release.
- Consistent Output: Built-in handling for page numbers, dynamic table pagination, and high-resolution rendering.
How do you handle PDF generation?
I’m curious to know how other developers in the community tackle this:
- Are you still using libraries like mPDF, PDFKit, or Puppeteer?
- Have you moved to headless Chrome or external APIs?
Let’s discuss in the comments below! If you'd like to test the visual builder workflow, feel free to check out QuartzAPI.

Top comments (0)