Skip to main content

Document / PDF Node

Flow node

The Document node has two modes:

  • parse -- PDF in, structured rows out. Each input row that carries a PDF payload produces one output row with { name, source, pageCount, text, meta, ai_ready }.
  • render -- template + rows in, PDF blob out. One output row per input row: { name, source, pdfBase64, sizeBytes, pages, blobRef }.

Both modes optionally read from and write to a file connection (S3, Drive, SharePoint, Dropbox) via a resolver DI'd into the runtime executor.

When to use

  • You need to pull structured content out of PDFs (invoices, contracts, resumes) so a downstream AI or Compute node can act on it.
  • You need to generate branded PDFs from row data (receipts, statements, work orders) and either return them inline as base64 or upload them to a file connection.
  • Both directions land in one node type so a "process an inbound PDF and emit a branded confirmation PDF" flow is two Document nodes chained end to end.

Parse mode

Real text extraction uses pdfjs-dist in its legacy build so no canvas native dependency is needed. Font hydration is disabled -- only text extraction runs -- which is why the runtime logs a harmless standardFontDataUrl warning per call.

Config

FieldDefaultMeaning
modeparse
pdfSourceColumnpdfBufferRow column carrying the PDF payload (Buffer, Uint8Array, or base64 string).
sourceConnectionIdnull(Optional) When rows carry sourceConnectionId + sourcePath, the executor fetches each PDF from the file connection before extraction.

Input row shape (parse)

FieldNotes
pdfBufferNode Buffer or Uint8Array of the raw PDF bytes.
pdfBase64Base64-encoded string of the raw PDF bytes.
sourceConnectionId(Optional) File-connection ID to fetch the PDF from.
sourcePath(Required with sourceConnectionId) Path inside the connection.
name, sourcePassed through to the output row.

Output row shape (parse)

ColumnTypeNotes
namestring | nullPassed through.
sourcestring | nullPassed through (or the fetched sourcePath when the file-connection resolver was used).
pageCountnumberNumber of pages in the PDF.
textstringExtracted text content, page-joined by \n.
metaobject | null{ byteLength, producer, creator, title } where available.
ai_readybooleanMarker for AI-node chaining. Currently false (raw text only).

Render mode

Two rendering paths are available:

Text templates (in-process)

Uses pdf-lib inside the runtime process. Each input row is rendered onto an A4 page with a Helvetica font. Template tokens are {{ column }} -- dotted paths are supported, missing columns become empty strings. Fast, cheap, no external service.

HTML templates (Puppeteer sidecar)

templateType: "html" forwards the rendered HTML to a Puppeteer sidecar at DLR_PDF_SIDECAR_URL. The sidecar's POST /render endpoint accepts { html } and returns the raw PDF bytes. Use this when you need real typography, brand assets, CSS grids, or embedded images.

When templateType: "html" is set but no sidecar is configured, the row lands on the error port with error: "html_renderer_not_configured" -- a clear signal to point at a sidecar or drop back to templateType: "text".

Config

FieldDefaultMeaning
modeSet to render.
templateTemplate string. {{ column }} tokens substituted per row.
templateTypetexttext -> pdf-lib in-process. html -> Puppeteer sidecar.
targetConnectionIdnull(Optional) File-connection ID to upload the rendered PDF to.
targetPath(Required with targetConnectionId) Path template (also supports {{ column }} tokens).

Output row shape (render)

ColumnNotes
namePassed through, or document_<n>.pdf when the row didn't set one.
sourcePassed through.
pdfBase64Base64-encoded raw PDF bytes. Downstream notification nodes can attach this directly.
sizeBytesUploaded size (falls back to raw byte length when no upload happens).
pagesReserved for a future refinement. Currently null.
blobRefString returned by the file-connection resolver when the target was configured. null otherwise.

Sidecar env vars

VarDefaultMeaning
DLR_PDF_SIDECAR_URL(unset)Base URL of the Puppeteer sidecar. Presence toggles HTML render on.
DLR_PDF_SIDECAR_TIMEOUT_MS30000Per-render HTTP timeout.

Failure modes

ReasonWhere the row lands
Row has neither pdfBuffer nor pdfBase64 and no sourceConnectionId + sourcePatherror port with error: "no_pdf_payload"
Row asks for a file connection but no resolver is wirederror port with error: "file_resolver_not_configured"
Resolver throwserror port with the fetch/upload error message (capped at 500 chars)
Extractor throws (parse) or renderer throws (render)error port with the underlying message
mode: "render" with an empty templateerror port with error: "missing_template"
mode: "render" + templateType: "html" but no sidecar wirederror port with error: "html_renderer_not_configured"
Any other mode valueerror port with error: "unsupported_mode:<mode>"

Inspector UI

The right-rail Document inspector exposes:

  • Mode tiles (Parse / Render).
  • Parse: PDF source column + optional file-connection source config.
  • Render: template textarea + template-type tiles (Text / HTML) + substitution preview toggle + file-connection target config.

Example flow fixture

qa/fixtures/document-node-example-flow.json shows two complete chains:

  • Source -> Document (parse) -> AI (extract) -> Load -- the classic "intelligent document processing" pattern.
  • Source -> Document (render) -> Notification -- generate branded receipts and email the blob-ref link.