Getting started
Generate PDFs from HTML templates.
A Next.js service that renders modular templates through Puppeteer. Send a JSON payload, get a styled PDF back. Built-in Sentry tagging scopes errors by project.
Components are composed by passing a blocks array. Themes are plain CSS strings that override CSS custom properties used by every component.
Install & run
Clone the repo, install dependencies, and start the dev server. The endpoint comes up at /api/template-pdf.
Prerequisites
- Node 20 LTS or later
Local development
# Clone the repo
git clone https://github.com/FluxBelgium/pdf-generator_next
cd pdf-generator_next
# Install & run
npm install
npm run dev # → http://localhost:3000API request
POST to /api/template-pdf with a JSON body. The response is a binary PDF stream.
Endpoint
curl -X POST https://pdf-generator.3dconfig.io/api/template-pdf \
-H "Content-Type: application/json" \
-d '{
"appID": "1234567890",
"templateId": "invoice",
"theme": "@import url(https://fonts.googleapis.com/css2?family=Manrope:wght@200..800); :root { --primary: #436414; --font-primary: Manrope, sans-serif; }",
"data": {
"header": {
"name": "Flux",
"email": "contact@flux.be",
"phone": "0485 40 26 71",
"address": "Frankrijklei 67, 2000 Antwerpen",
"logo": "https://flux.be/wp-content/uploads/2025/06/flux_logo_navy.svg"
},
"blocks": [
{
"type": "table",
"data": {
"title": "Items",
"description": "These are the items that you have purchased",
"header": ["Description", "Quantity", "Price", "Total"],
"items": [["Website Design", 1, 500, 500], ["Hosting", 1, 100, 100]],
"footer": ["", "", "Total", 600]
}
}
],
"footer": {
"address": "Frankrijklei 67, 2000 Antwerpen",
"footerText": "Thank you for your business!"
}
}
}' \
--output ~/Downloads/invoice.pdfRequest body
| Field | Type | Required | Description |
|---|---|---|---|
appID | string | no | Tenant identifier. Recommended for Sentry error tagging per project. |
templateId | string | yes | One of the registered templates (e.g. invoice). |
theme | string | no | Raw CSS defining --primary, font, radius, etc. |
data | object | yes | Payload consumed by the template. |
Response
200 OK with Content-Type: application/pdf. On failure: 400 for validation errors, 503 if the browser pool is exhausted, 500 for generation failures. All return a JSON error body.
Themes
Plain CSS strings. Set your brand color, font, and border radius. It cascades into every template component automatically.
CSS custom properties
@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200..800');
:root {
/* Brand color */
--primary: rgb(25, 32, 59);
--primary-light: rgb(210, 220, 246);
--primary-lightest: rgb(227, 234, 250);
--primary-dark: rgb(10, 13, 24);
/* Neutral grays */
--gray: #474747;
--gray-light: #e5e5e5;
--gray-lightest: #f5f5f5;
/* Typography & shape */
--font-primary: "Manrope", sans-serif;
--border-radius: 0.25rem;
}Presets
Pick a preset, then generate a sample PDF to see it in action.
Available templates
View invoice templateError tracking
Pass appID on any request and it flows into Sentry, so you can filter and route issues per project without a separate tenant.
- Tagging: all errors are tagged with the
appIDon capture. - Filtering: use Sentry's
tags:appIDquery to isolate a client. - Routing: wire alerts per
appIDto the right team.