How to Generate PDF Reports Using Node-RED in FlowFuse
Learn how to automate the generation of dynamic PDF reports within Node-RED and FlowFuse.

Generating PDF reports is a common need in many workflows—whether you're logging data, sharing results, or creating summaries. With Node-RED and FlowFuse, you can easily automate turning your data into well-structured PDF files. This guide will show you how to set up step-by-step PDF report generation using simple tools and flows.
Generating reports allows you to capture snapshots of critical data, summarize system activities, and distribute insights in an easy-to-read and stored format. PDF is one of the most universally accepted formats for sharing documents, making it ideal for delivering structured information from your Node-RED flows.
# Prerequisites
Before you begin, make sure the following requirements are met:
- You have an active FlowFuse account and a running FlowFuse instance.
- You are familiar with creating and deploying basic flows in Node-RED. If not, consider taking the Node-RED Fundamentals Course sponsored by FlowFuse.
- Ensure you have installed
flowfuse/node-red-dashboard
@flowfuse/node-red-dashboard-2-ui-iframe
andnode-red-contrib-sqlite
(The SQLite node is required for the demo data generation flow we provided. If you're not using that flow, you can skip this.).
# Setting Up PDF Generation in Node-RED
Once the prerequisites are in place, the next step is setting up your Node-RED environment to generate PDF reports. In this section, we will go over how to install the necessary Node-RED node and configure a flow to generate PDF reports.
# Step 1: Install the @platmac/node-red-pdfbuilder
The platmac/node-red-pdfbuilder node is the primary node for creating PDF reports in Node-RED. To install this node:
- Open your Node-RED editor.
- Navigate to the "Manage palette" section from the top-right menu.
- Click on the "Install" tab and search for
@platmac/node-red-pdfbuilder
. - Click "Install" to add the node to your palette.
This node allows you to dynamically generate PDFs from various inputs, which is exactly what you will need to generate reports.
If you haven't installed the @flowfuse/node-red-dashboard
, @flowfuse/node-red-dashboard-2-ui-iframe
and node-red-contrib-sqlite
nodes, you can install them similarly.
# Step 2: Understanding How to Use the Pdfbuilder Node
Now that the required node is installed, let's dive into how to use it and how to leverage the different attributes to customize your PDF reports. The pdfbuilder node in Node-RED simplifies generating PDFs by allowing you to define content, layout, and styling directly in your flow.
The key advantage of using pdfbuilder node is that it operates server-side, meaning PDFs can be generated automatically without a browser or manual interaction. This makes it ideal for automated workflows where consistent, programmatically created documents are needed.
When working with this node, you can use various attributes to customize the content and layout of the PDF, such as text, tables, images, page sizes, margins, headers, footers, and more. Below are the most commonly used attributes:
Attribute | Description | Example |
---|---|---|
content |
Defines the content of the PDF (text, tables, images, etc.). | { "content": "Hello, World!" } |
style |
Specifies the style for content (font size, font family, etc.). | { "style": "headerStyle" } |
layout |
Defines the layout of a table (e.g., 'lightHorizontalLines', 'noBorders'). | { "layout": "lightHorizontalLines" } |
pageSize |
Defines the page size for the PDF. | { "pageSize": "A4" } |
pageMargins |
Sets the margins for the PDF (left, top, right, bottom). | { "pageMargins": [40, 60, 40, 60] } |
header |
Specifies a header for the PDF. Can be a static text or dynamic content. | { "header": "My PDF Report" } |
footer |
Specifies a footer for the PDF. Can be a static text or dynamic content. | { "footer": "Page {PAGE_NUM} of {PAGE_COUNT}" } |
defaultStyle |
Defines the default style for all content in the PDF. | { "defaultStyle": { "font": "Helvetica", "fontSize": 12 } } |
background |
Adds a background to the page or content area. | { "background": { "image": "imageData" } } |
width |
Sets the width of table cells or other elements. | { "width": 150 } |
height |
Sets the height of table cells or other elements. | { "height": 50 } |
alignment |
Specifies the text alignment (left, center, right). | { "alignment": "center" } |
border |
Defines the border for tables or table cells (style, width, and color). | { "border": [true, true, true, true] } |
For additional attributes and information, refer to the pdfmake documentation, as pdfbuilder-node uses this library to generate PDFs.
Here’s a simple example of how you can use these attributes to create a basic PDF:
{
"content": [
{
"svg": "logoDataHere",
"width": 150,
"alignment": "center",
"margin": [0, 0, 0, 20]
},
{
"text": "Production Report - 2025",
"style": "header"
},
{
"text": "Daily Production Summary with Operator Performance",
"style": "subheader",
"alignment": "center",
"margin": [0, 10, 0, 20]
},
{
"layout": "lightHorizontalLines",
"table": {
"headerRows": 1,
"widths": ["auto", "auto", "*", "auto", "auto", "*"],
"body": [
["Date", "Shift", "Product", "Units Produced", "Defective Units", "Operator"],
["2025-01-01", "Morning", "Product A", "1000", "20", "John Doe"],
["2025-01-01", "Afternoon", "Product B", "950", "15", "Jane Smith"],
["2025-01-02", "Morning", "Product A", "1050", "10", "James Brown"],
["2025-01-02", "Afternoon", "Product C", "800", "30", "Emily Clark"],
["2025-01-03", "Morning", "Product B", "1100", "25", "Michael Green"],
["2025-01-03", "Afternoon", "Product A", "980", "18", "Sarah White"]
]
}
},
{
"text": "This table summarizes the daily production output across different shifts and operators. It includes total units produced and defective units recorded for quality analysis.",
"fontSize": 12,
"alignment": "justify",
"margin": [0, 10, 0, 20]
},
{
"text": "Internal Use Only - Manufacturing Co.",
"style": "footer",
"alignment": "center",
"margin": [0, 20, 0, 0]
}
],
"styles": {
"header": {
"fontSize": 20,
"bold": true,
"alignment": "center",
"margin": [0, 20, 0, 10]
},
"subheader": {
"fontSize": 14,
"italics": true,
"color": "grey",
"margin": [0, 10, 0, 20]
},
"footer": {
"fontSize": 10,
"color": "grey"
}
},
"pageSize": "A4",
"pageMargins": [40, 60, 40, 60]
}
This example creates a simple PDF featuring a centered logo, a title, a subtitle, a table with a light horizontal line layout, a paragraph of text, and a footer at the end. The following screenshot shows how it looks. You can customize it by adjusting the styles, layout, and content.
# Step 3: Creating a Flow to Generate a PDF
Let's learn how to generate a PDF using dynamic inputs. For this, we’ll use the same example PDF report shown earlier—but this time, we’ll replace the hardcoded values with dynamic input data.
- For this guide's practical example, we will use the following SQLite flow that generates simulated production data. If you don't have the data source, you can import the flow below to follow along. After importing, deploy the flow and click the Inject node button to generate and insert the data.
When generating PDFs for your specific data, start by creating a flow to collect the information you want in the report. This data can come from sensors, databases, APIs, or even manual inputs.
- Drag an Inject node onto the canvas.
- Drag an SQLite node and connect it to the Inject node. Configure the SQLite node with the same database to generate the simulated data. Set the SQL Query type to "fixed statement" and use the following query:
SELECT * FROM production_report;
- Drag a Function node onto the canvas and paste the following JavaScript code. When generating PDFs for your specific data, make sure to adjust the code to match your data structure.
// Initialize table body with headers
const tableBody = [
['Date', 'Shift', 'Product', 'Units Produced', 'Defective Units', 'Operator']
];
const logo = `<replace-this-your-logo-svg`
// Loop through data rows from SQLite (msg.payload)
for (const row of msg.payload) {
tableBody.push([
row.date,
row.shift,
row.product,
row.units_produced.toString(),
row.defective_units.toString(),
row.operator
]);
}
const docDefinition = {
content: [
{
svg: logo,
width: 150, // Adjust the logo size as needed
alignment: 'center',
margin: [0, 0, 0, 20]
},
// Header
{
text: 'Production Report - 2025',
style: 'header'
},
// Subheader
{
text: 'Daily Production Summary with Operator Performance',
style: 'subheader',
alignment: 'center',
margin: [0, 10, 0, 20]
},
// Table
{
layout: 'lightHorizontalLines',
table: {
headerRows: 1,
widths: ['auto', 'auto', '*', 'auto', 'auto', '*'],
body: tableBody
}
},
// Description
{
text: 'This table summarizes the daily production output across different shifts and operators. It includes total units produced and defective units recorded for quality analysis.',
fontSize: 12,
alignment: 'justify',
margin: [0, 10, 0, 20]
},
// Footer
{
text: 'Internal Use Only - Manufacturing Co.',
style: 'footer',
alignment: 'center',
margin: [0, 20, 0, 0]
}
],
styles: {
header: {
fontSize: 20,
bold: true,
alignment: 'center',
margin: [0, 20, 0, 10]
},
subheader: {
fontSize: 14,
italics: true,
color: 'grey',
margin: [0, 10, 0, 20]
},
footer: {
fontSize: 10,
color: 'grey'
}
},
pageSize: 'A4',
pageMargins: [40, 60, 40, 60]
};
msg.payload = docDefinition;
return msg;
- Drag a pdfbuilder node onto the canvas. Set the input property to
msg.payload
, set output type to Buffer, and output property tomsg.payload
. - Drag a Write File node, configure it with:
- Filename: test.pdf
- Action: Overwrite file
- Add newline (\n) to each payload?: Checked
- Connect the SQLite node to the Function node, then to the pdfbuilder node, and finally to the Write File node.
- Deploy the flow and click inject node to generate the pdf.
Once the PDF is generated, you can find it in the .node-red
directory.
However, if you want to share the PDF with others, display it on the dashboard, and provide a download button, you can use the HTTP API, an iframe, and a few supporting nodes. Let's walk through how to do that next.
# Step 4: Serving the PDF via HTTP and Previewing It on the Dashboard
In this step, we’ll make the generated PDF accessible through a web interface. You’ll be able to preview the PDF directly in the browser and embed it in your FlowFuse dashboard for a smooth, integrated experience. We’ll also add a download button so users can easily save the report. Instead of manually retrieving the file, we’ll create an HTTP endpoint to serve the PDF and use an iframe to display it.
# Exposing the PDF via HTTP
-
Drag the ** http-in ** node onto the canvas. Set the method to 'GET' and the URL to
/report.pdf
. This will create an HTTP endpoint for retrieving the generated PDF. -
Connect the ** http-in ** node to the ** SQLite ** node. This ensures that when a request is made to this endpoint, the necessary data is fetched from the database.
-
After the Write File node in your flow, add a Change node. Connect it to the Write File node, and configure it to set the following headers for the HTTP response:
- Set
msg.headers
to:
{
'Content-Type': 'application/pdf',
'Content-Disposition': 'inline; filename="report.pdf"'
} - Set
-
Drag the HTTP-response node onto the canvas and connect it to the Change node.
-
Deploy the flow
Now, this will send the generated PDF as a response to the incoming HTTP request, allowing it to be previewed in the browser. You can check by entering the URL:
https://<your-instance-name>.flowfuse.cloud/report.pdf
# Embedding the PDF on the Dashboard and Adding the Download Button
Now, let's embed the PDF into the dashboard:
-
Drag a ui-event node onto the canvas and configure it with the appropriate UI base settings.
-
Next, drag an iframe node onto the canvas.
- Select the correct group where the PDF should be displayed.
- Adjust the size according to your preferences.
- In the URL field, enter:
https://<your-instance-name>.flowfuse.cloud/report.pdf
-
Click Done and Deploy the flow.
Once deployed, when you open the dashboard, the generated PDF will be embedded and displayed directly on the dashboard page.
Now, let's add a download button:
- Drag a ui-template widget onto the canvas and paste the following HTML code into it:
<div style="text-align:center; margin-top: 20px;">
<a href="https://<your-instance-name>.flowfuse.cloud/report.pdf" download="report.pdf"
style="display: inline-block; background-color: #4f7a28; color: white; padding: 14px 20px; text-align: center; text-decoration: none; font-size: 16px; border-radius: 5px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); transition: background-color 0.3s ease;">
Download Report
</a>
</div>
- Deploy the flow.
# Final thought
Automating PDF report generation in Node-RED is a great way to save time and effort. Using tools like the node-red-contrib-pdfmake node, you can quickly turn your data into well-designed PDFs without manual work. If you want to save time and avoid the setup process, you can directly use our ready-made PDF generation blueprint. It’s an easy way to get started and generate professional reports quickly.
Written By:
Published on:
Related Articles:
- Part 3: Building an OEE Dashboard with FlowFuse
- FlowFuse 2.16: Git Integration, improved log retention and more
- Part 2: Building an OEE Dashboard with FlowFuse
- Part 1: Building an OEE Dashboard with FlowFuse
- Managing MQTT Connections at Scale in FlowFuse