Skip to main content

Module options

The pdf.* configuration for font declarations, the remote allowlist, and render limits.

Module options live under the pdf key in nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@lupinum/nuxt-pdf"],
  pdf: {
    fonts: [/* entries */],
    remote: {/* options */},
    limits: {/* options */},
  },
});

Every key is optional. With none set, the module renders with built-in fonts, uses only local assets, performs zero network I/O, and bounds every render with the default render limits below.

pdf.fonts

An array of font-face declarations. Each face registers one weight/style of a font found in pdfs/fonts:

ts
export default defineNuxtConfig({
  pdf: {
    fonts: [
      { family: "Invoice Sans", src: "Regular.ttf", fontWeight: 400, fontStyle: "normal" },
      { family: "Invoice Sans", src: "Bold.ttf", fontWeight: 700, fontStyle: "normal" },
    ],
  },
})
FieldTypeRequiredDescription
familystringyesThe family name referenced in fontFamily style values
srcstringyesTTF/OTF filename relative to pdfs/fonts
fontWeightnumber | PdfFontWeightNamenoNumeric weight or a name such as "bold", "medium", or "light"
fontStyle'normal' | 'italic' | 'oblique'noThe face style

Register one entry per weight/style you use. Sources are signature- and size-checked (5 MB cap) and embedded into the build. See Images & fonts for the validation boundary.

pdf.remote

Opt-in remote fetching for images only. Absent by default, which keeps the module fully offline; when present, allow must list at least one https:// prefix.

ts
export default defineNuxtConfig({
  pdf: {
    remote: {
      allow: [
        "https://cdn.example.com/brand/",
        "https://images.example.com/logos/",
      ],
      timeoutMs: 10_000,
    },
  },
})
FieldTypeDefaultDescription
allowstring[]RequiredExact allowlisted https://host/path/ prefixes with a trailing slash
timeoutMsnumber10_000Per-hop fetch timeout

Invalid entries fail fast at module setup: non-https, credentialed, or query/fragment-bearing entries, wildcard hosts, and prefixes without a trailing slash are all rejected. The module checks each redirect, limits streamed bytes, validates signatures, and does not forward credentials. See Images & fonts.

pdf.limits

The one canonical resource budget for every render. Defaults apply even when pdf.limits is absent.

ts
export default defineNuxtConfig({
  pdf: {
    limits: {
      timeoutMs: 30_000,
      maxPages: 2_000,
      maxNodes: 50_000,
      maxOutputBytes: 67_108_864,
    },
  },
})
FieldTypeDefaultDescription
timeoutMsnumber30_000Time budget for the whole public render (metadata evaluation, mount, layout, all passes, serialization)
maxPagesnumber2_000Maximum laid-out page count
maxNodesnumber50_000Maximum mounted tree nodes
maxTreeDepthnumber128Maximum mounted tree depth
maxTextCharactersnumber2_000_000Maximum Unicode code points in text nodes
maxImagesnumber256Maximum image nodes
maxImageBytesnumber10_485_760Maximum source bytes per unique image
maxTotalImageBytesnumber33_554_432Maximum source bytes across unique images
maxImagePixelsnumber25_000_000Maximum decoded pixels per unique image
maxTotalImagePixelsnumber100_000_000Maximum decoded pixels across unique images
maxRemoteRequestsnumber32Maximum remote HTTP requests, including redirect hops
maxRemoteConcurrencynumber4Maximum simultaneous remote HTTP requests
maxOutputBytesnumber67_108_864Maximum completed PDF bytes

Every field is an optional positive safe integer; a non-positive, non-integer, or non-numeric value fails fast at module setup. Omitting one field keeps its default.

When a limit is exceeded the render fails with a PDF_LIMIT_EXCEEDED NuxtPdfError:

  • maxPages is checked right after layout (before serialization) on both the single-pass and multi-pass paths; the error names the page count, the cap, and the config key.
  • timeoutMs bounds the entire public render with a single deadline that starts before metadata evaluation. Upstream layout is not abortable mid-step, so the budget is checked between engine stages and passes. It is a deadline, not hard cancellation, and a single engine stage can overshoot it by its own duration. The error names the elapsed budget. The reported diagnostics.durationMs covers the same operation.
  • Tree, text, and image-count limits are checked on the mounted tree after Vue mount (and again after every multi-pass page-number feed). They reject excess content; they do not isolate allocation during mount. Image byte and decoded-pixel limits are checked before engine admission with one render-wide budget. Output is collected into one completed buffer and discarded atomically when its cap is exceeded.

Hard cancellation is not claimed. Vue component/setup closures are the canonical document source and are not transferable to a portable Nitro worker; introducing a worker-only bundle or second serialized schema would violate the one-tree architecture. Keep untrusted template code out of the process and use the admission limits to bound document data.