config/projects/business/memory/devto-draft.md

203 lines
5.8 KiB
Markdown

---
title: "Stop Wrestling with Puppeteer: Generate PDFs with One API Call"
published: false
description: "How to generate invoices, reports, and documents as PDFs from HTML, Markdown, or JSON data — without managing headless browsers."
tags: webdev, api, node, tutorial
cover_image: # (add a cover image URL)
---
Every developer has the same PDF story. It starts innocently:
> "Can we add a 'Download as PDF' button?"
Three days later, you're debugging Chrome memory leaks in production, your Puppeteer instance is eating 2GB of RAM, and the PDFs look different on every server.
I got tired of this cycle, so I built [DocFast](https://docfast.dev) — a PDF API that takes HTML, Markdown, or structured data and returns a PDF. No headless browser setup, no dependencies.
Here's what I learned, and how you can generate PDFs in about 30 seconds.
## The Simple Version
```bash
curl -X POST https://docfast.dev/v1/convert/html \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Hello World</h1><p>This is a PDF.</p>"}' \
-o hello.pdf
```
That's it. JSON in, PDF out.
## Three Ways to Generate PDFs
DocFast has three conversion endpoints, each for a different use case:
### 1. HTML → PDF
You have full control. Pass any HTML with optional CSS:
```javascript
const response = await fetch('https://docfast.dev/v1/convert/html', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: `
<h1 style="color: navy;">Monthly Report</h1>
<p>Revenue: <strong>$12,345</strong></p>
<table>
<tr><td>Users</td><td>1,234</td></tr>
<tr><td>MRR</td><td>$5,670</td></tr>
</table>
`,
css: 'body { font-family: Georgia, serif; padding: 40px; }',
format: 'A4'
})
});
const pdf = await response.arrayBuffer();
fs.writeFileSync('report.pdf', Buffer.from(pdf));
```
### 2. Markdown → PDF
This is my favorite endpoint. Write Markdown, get a styled PDF with syntax highlighting:
```javascript
const markdown = `
# Project Proposal
## Overview
We propose building a **real-time dashboard** for monitoring API usage.
## Timeline
| Phase | Duration | Cost |
|-------|----------|------|
| Design | 2 weeks | $3,000 |
| Build | 4 weeks | $8,000 |
| Test | 1 week | $1,500 |
## Code Sample
\`\`\`javascript
const analytics = new Analytics({ key: 'abc123' });
analytics.track('pdf_generated', { format: 'A4' });
\`\`\`
`;
const response = await fetch('https://docfast.dev/v1/convert/markdown', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ markdown })
});
```
Tables, code blocks, images — it all renders beautifully.
### 3. URL → PDF
Need to snapshot a webpage? Just pass the URL:
```bash
curl -X POST https://docfast.dev/v1/convert/url \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "waitUntil": "networkidle0"}' \
-o page.pdf
```
It handles JavaScript-rendered pages too (SPAs, dashboards, etc).
## The Killer Feature: Invoice Templates
This is what I wish existed years ago. Instead of building invoice HTML from scratch, you pass JSON data and get a professional invoice:
```javascript
const response = await fetch('https://docfast.dev/v1/templates/invoice/render', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: {
invoiceNumber: 'INV-2026-042',
date: '2026-02-14',
dueDate: '2026-03-14',
from: {
name: 'Your Company',
address: '123 Main St',
email: 'billing@yourco.com'
},
to: {
name: 'Client Corp',
address: '456 Oak Ave',
email: 'ap@client.com'
},
items: [
{ description: 'Web Development', quantity: 40, unitPrice: 95, taxRate: 20 },
{ description: 'Hosting', quantity: 1, unitPrice: 29 }
],
currency: '€',
notes: 'Payment due within 30 days.',
paymentDetails: 'IBAN: AT12 3456 7890 1234 5678'
}
})
});
```
No HTML. No CSS. Just data → PDF.
## Integrating Into Your App
Here's a minimal Express.js endpoint that generates and returns an invoice:
```javascript
app.get('/api/invoice/:id', async (req, res) => {
const invoice = await db.getInvoice(req.params.id);
const pdfResponse = await fetch('https://docfast.dev/v1/templates/invoice/render', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.DOCFAST_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ data: invoice })
});
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', `attachment; filename=invoice-${invoice.invoiceNumber}.pdf`);
pdfResponse.body.pipe(res);
});
```
12 lines. Your users can download invoices.
## Why Not Just Use Puppeteer?
You can! But here's what you're signing up for:
- **Memory:** Each Chrome instance uses 200-500MB RAM
- **Cold starts:** Launching a browser takes 1-3 seconds
- **Stability:** Chrome crashes, zombie processes, OOM kills
- **DevOps:** Managing Chrome versions, fonts, dependencies in Docker
- **Concurrency:** Need multiple PDFs at once? Now you're managing a browser pool
DocFast handles all of this. Persistent browser pool, sub-second generation, no infrastructure to manage.
## Pricing
- **Free:** 100 PDFs/month, all endpoints, all templates
- **Pro:** $9/month for 10,000 PDFs/month
No per-page fees. No credit card for the free tier. [Get your API key here](https://docfast.dev).
---
If you have questions about the API or want to see specific templates added, drop a comment. I'm actively building based on user feedback.
Happy PDF-ing! 📄