@inteli.city/node-red-contrib-latex-pdf 1.0.0
A Node-RED node that renders LaTeX using Nunjucks and compiles it to PDF using Tectonic.
node-red-contrib-latex-pdf
A Node-RED node that renders LaTeX using Nunjucks and compiles it to PDF using Tectonic.
Table of Contents
- Overview
- When to Use
- Mental Model
- Contract
- Installation
- How It Works
- Template Context
- Rendering Data
- Inline Assets (asset helper)
- Error Handling
- Queue / Concurrency
- Examples
- Limitations
Overview
This node renders a Nunjucks template into a LaTeX document and compiles it to PDF using Tectonic.
The result is a PDF Buffer in msg.payload.
Requirements: Tectonic must be installed and available in PATH.
Install Tectonic: https://tectonic-typesetting.github.io/en-US/install.html
When to Use
Use this node when you need:
- dynamic PDF generation
- structured reports (logs, invoices, summaries)
- embedding binary data (images, diagrams) into documents
Do not use this node for:
- simple text formatting (use the built-in template node)
- high-frequency, low-latency flows (PDF compilation is expensive)
- very large documents (Tectonic runs per message)
Mental Model
This node executes a template as a document generation program.
payload→ input data- template → logic + layout
asset()→ converts Buffers into files for LaTeX
Think of it as:
data → template → files → PDF
The template controls rendering. The node does not transform data implicitly.
Contract
The node expects:
msg.payload— any data (including Buffers)- A valid Nunjucks template that produces valid LaTeX after rendering
- No external file inputs — all files must be created via
asset()
The node guarantees:
- PDF output as a
Bufferinmsg.payload - Isolated execution per message (temporary directory)
- Cleanup of all temporary files after execution
The node will fail if:
- The template uses
msg.*syntax asset()receives a non-Buffer value- LaTeX compilation fails (Tectonic error)
Installation
cd ~/.node-red
npm install node-red-contrib-latex-pdf
How It Works
Nunjucks template → LaTeX → Tectonic → PDF → msg.payload
Each message is processed in an isolated temporary directory. All files (.tex, assets, output .pdf) are deleted after compilation.
Template Context
Message properties are exposed at the root of the template context. Reference them directly — do not use msg.*.
| Variable | Value |
|---|---|
{{ payload }} |
msg.payload |
{{ topic }} |
msg.topic |
{{ flow.get("key") }} |
Flow context variable |
{{ global.get("key") }} |
Global context variable |
{{ env.MY_VAR }} |
OS environment variable |
Using
msg.inside a template triggers a node error. Use{{ payload }}style instead.
Rendering Data
msg.payload is passed to the template as-is — no automatic stringification.
To render objects as text, use the dump filter:
{{ payload | dump }}
This is required to preserve Buffers and binary data. Passing a raw object to LaTeX without dump will render as [object Object].
Inline Assets (asset helper)
asset() is the only supported way to embed files. It writes a Buffer to a temporary file and returns the filename for LaTeX to reference:
\includegraphics{ {{ asset(payload.image, "png") }} }
Each call generates a unique filename (asset-0.png, asset-1.png, …).
Loops are supported:
{% for img in payload.images %}
\includegraphics{ {{ asset(img, "png") }} }
{% endfor %}
Constraints:
- First argument must be a
Buffer— anything else throws an error - Extension is sanitized (alphanumeric only); defaults to
bin - Files are not persisted after execution
Error Handling
The node fails fast on invalid input. Errors are reported via node.error() and attached to msg.error.
| Situation | Error message |
|---|---|
Template uses msg.* |
Use {{ payload }} style, not {{ msg.* }}. |
asset() receives non-Buffer |
asset() expects a Buffer |
| Tectonic compilation fails | Tectonic stderr output |
The queue continues processing subsequent messages after a failure.
Queue / Concurrency
The node processes messages using a FIFO queue with configurable concurrency.
Set the Queue field in the node editor to control how many compilations can run in parallel. Default is 1 (fully sequential).
Status format:
<queued> (<running>/<max>)
Examples:
0 (0/1) → idle
0 (1/1) → one compiling
3 (5/5) → saturated, 3 waiting
Examples
Basic — render text payload
\documentclass{article}
\begin{document}
{{ payload | dump }}
\end{document}
Report with image
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\section*{ {{ payload.title }} }
{{ payload.description }}
\includegraphics{ {{ asset(payload.image, "png") }} }
\end{document}
Multiple images
\documentclass{article}
\usepackage{graphicx}
\begin{document}
{% for img in payload.images %}
\includegraphics{ {{ asset(img, "png") }} }
{% endfor %}
\end{document}
Limitations
Templates are rendered from a single string. The following Nunjucks features are not supported:
{% include "file.njk" %}{% extends "base.njk" %}{% import "macros.njk" %}
Templates must be self-contained. Macros can be defined and used within a single template.
- Files must be provided as Buffers inside the template via
asset()
Full Nunjucks documentation (not all features are supported): https://mozilla.github.io/nunjucks/templating.html