Generate PDFs in Node.js¶
Fullbleed's optional Node package renders static HTML/CSS into PDFs using a bundled WebAssembly build of the Rust engine. It includes fonts and runs locally; you do not need Python, Rust, or a browser to use the installed package.
To compose documents without HTML strings, use the JavaScript component and JSX workflow, introduced in Node package 0.6.0. Version 0.7.0 also supports static HTML export with or without styles. The pinned HTML/CSS example below remains available.
The quickstart and downloadable invoice use Node package 0.7.1, powered by Fullbleed 2.5.29. The integration and core engine have separate versions.
Version 0.7.1 brings the stable engine's SVG stylesheet and inset-shadow fixes to Node and browser rendering. It retains component/JSX authoring, static HTML export, the shared render queue, optional process isolation and bundled fonts. See the focused paint checks and the server guidance below for queue limits and failure handling.
Use the actual family name for normal/italic CSS selection, or a PostScript name for an explicit face. Review appearance and line breaks when upgrading; the font-family guide explains font selection.
For rendering inside a web page, use the browser entry and starter. For Cloudflare Workers, use the Workers adapter and invoice endpoint introduced in package 0.8.0. This guide's invoice download remains pinned to 0.7.1.
Create your first PDF¶
With Node.js 22 or newer, install the npm package:
To pin this guide's version, use npm install --save-exact fullbleed@0.7.1.
The npm package contains the same verified bytes as the GitHub release.
Save this as invoice.mjs and run node invoice.mjs:
import { writeFile } from 'node:fs/promises';
import { renderPdf } from 'fullbleed';
const result = await renderPdf({
html: '<h1>Invoice NS-1042</h1><p>Consulting: USD 1,200.00</p>',
css: '@page { size: A4; margin: 20mm } h1 { color: #175c52 }',
previewDpi: 96,
});
await writeFile('invoice.pdf', result.pdf);
await writeFile('invoice.png', result.previews[0]);
console.log(`${result.pages} page; engine ${result.engineVersion}`);
Open invoice.pdf or invoice.png. Inter is the default font, and previews come
from the finalized PDF. result.pdf is a Node Buffer that you can also return
from an HTTP handler or write to your storage.
CommonJS applications can use const { renderPdf } = require('fullbleed').
TypeScript declarations are included for both module styles.
Export a design from the playground¶
Open the playground, edit an invoice, report, or notice,
choose Node.js under Project language, and select Download project.
The ZIP contains your current HTML/CSS, font files and licenses, a locked npm
dependency, and render.mjs. Extract it and run:
Open output/document.pdf and the previews in output/preview/. Edit
input.html or style.css and run the renderer again. These playground exports
use Node package 0.5.0 with the same 2.5.22 engine. Their renderer sets
defaultStyles: false
to preserve font inheritance and CSS layers exactly as entered in the playground.
Start with a designed invoice¶
Download the Node invoice project Open its generated PDF
Extract the project and run these commands in its directory:
Open output/invoice/invoice.pdf and output/invoice/page-1.png. Edit the
customer value in render.mjs or change the HTML/CSS. The script escapes the
customer name before inserting it into the document. All example data is fictional.
The lockfile pins the npm package version and its integrity hash.
The layout uses the bundled Inter, DM Serif Display, and Bebas Neue families.
Style a report with gradients¶
This retained sample comes from package 0.4.1's three-page report. The chart uses CSS
linear-gradient(180deg, #d9bc77, #a9b884); the image above is a native preview
of the finalized PDF. Fullbleed 2.5.5 fixes gradient fills that were missing from
these PNG previews in earlier releases.
Open the report PDF Explore its HTML and CSS
Bring fonts and image assets¶
Pass additional font bytes through fonts, and use their actual family names
in CSS. Pass images through assets, mapping relative names to Buffer or
Uint8Array values. For example, an asset named brand/logo.svg is available as
assets/brand/logo.svg in your HTML.
The engine uses an in-memory filesystem for the supplied inputs and does not fetch remote URLs. Data URIs also work for document images. The package API reference includes a complete font and asset example.
Unembedded PDF Standard 14 faces now have bundled substitutes for native PNG previews. The PDF keeps its original font resources, text, and advances; a PDF reader can use a different substitute design. Register your chosen font when the exact branded appearance matters. See the preview comparison and font limits.
Use it in an application¶
For a working web-app integration, use the Next.js PDF download starter. It includes an App Router handler, designed invoice, bundled-asset configuration and an isolated check of the production standalone server.
By default, rendering runs in a worker, with separate document state for concurrent calls.
The promise waits for its worker to exit, including after failure, timeout, or
cancellation. Sequential await renderPdf() calls therefore do not overlap
worker lifetimes. A timeout or abort starts termination; the promise settles
after the worker stops.
Use timeoutMs, maxPages, and an AbortSignal to bound a job. Limit concurrent
calls to fit your server's memory; each worker's WebAssembly memory ceiling is
512 MiB. Preview images can use more memory than PDF-only rendering.
Node package 0.4.0 adds a shared render queue with active and waiting limits, deadlines that include queue time, cancellation, and shutdown. The guide includes a runnable six-invoice batch. Use one queue per application process to share the limits across request handlers.
Rendering errors reject with a FullbleedError and a code such as INVALID_INPUT,
MISSING_GLYPHS, PAGE_LIMIT, TIMEOUT, or ABORTED. Invalid font data is
rejected. Use registered font families: unavailable CSS families can fall back,
and the engine's glyph report does not establish visual correctness. Review the
final PDF and previews when adapting a design.
Contain render-process failures¶
On a Node host that permits child processes, use isolation: 'process' to run
each request's engine and worker in a fresh process:
const result = await renderPdf({
html: '<h1>Monthly statement</h1>',
isolation: 'process',
timeoutMs: 10_000,
maxPages: 20,
});
The caller does not compile WebAssembly or create render workers in this mode.
The promise waits for process exit and IPC disconnection before settling, even
after success. A failed child exit rejects with PROCESS_FAILED; available
exitCode and signal fields describe the exit. Timeouts and aborts terminate
the child before rejecting. A PDF received before a failed shutdown is not
returned as a successful result.
Process startup adds latency and memory use. There is no process pool or
automatic retry; keep concurrency bounded. Application startup flags and
NODE_OPTIONS are not replayed in the child. This option requires a normal
Node executable and is not an operating-system security sandbox. See the
process isolation guide
for deployment details and the tested failure paths. The Next.js starter uses
this mode for its PDF route.
An intermittent process crash on Linux with Node 24.21.0 was observed with
fullbleed@0.1.2; issue #7
remains open. Version 0.1.3 fixes worker shutdown timing, but has not established
that this native crash is resolved. See the
runtime investigation
for the observed scope and synthetic diagnostic. A process crash can occur
before JavaScript can return an error in worker mode. Process isolation contains
tested child failures; it does not establish a fix for that native crash.
This first Node API covers ordinary PDF rendering and previews. Use the Python API or Rust crate for profiles, template overlays, and compiled variable-data workflows. Unknown Node options are rejected. For JavaScript execution or live website behavior, use a browser.
Verification and source¶
The package checks real document output, failure recovery, ESM/CommonJS, and TypeScript. Its release evidence compares retained native and WebAssembly fixtures and installs the same tarball across Node 22, 24, and 26 on Windows, Linux, and macOS. These are scoped engineering checks, not PDF standards certification.
The public-install verification records the registry tarball hash, audits npm signatures and provenance, and executes the queue lifecycle checks from a fresh registry install. Its queued PDF and PNG match the CI output. The release verification retains 45 native/Wasm comparisons, fourteen queue checks in each of nine installed Node/platform combinations, and 144 checks in each of Chrome, Firefox, and Playwright WebKit, including browser downloads and failure recovery. Thirteen focused engine fixtures also pass independent text, color, and retained Chrome geometry expectations in Node and downloaded browser PDFs. The invoice and report on this page retain the reviewed PDF bytes and preview pixels with engine 2.5.22; the download manifest records their exact hashes.
Package source and API · npm package · Versioned release and evidence · CSS coverage · Examples

