Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/bpampuch/pdfmake/llms.txt

Use this file to discover all available pages before exploring further.

pdfmake’s declarative API means you can go from zero to a styled, multi-section PDF in just a few steps. This guide walks through installation, font configuration, building a document definition, and delivering the finished file — in both browser and Node.js.
1

Install pdfmake

Add pdfmake to your project with your preferred package manager.
npm install pdfmake
For browser-only usage without a bundler, see the Installation guide for CDN and prebuilt bundle options.
2

Import pdfmake and configure fonts

pdfmake requires at least one font to be registered before it can render text. The package ships with the Roboto family.Browser (with a bundler like webpack or Vite)In the browser, import the pre-built singleton and attach the bundled virtual file system, which contains Roboto as base64-encoded data:
import pdfmake from 'pdfmake/build/pdfmake';
import vfsFonts from 'pdfmake/build/vfs_fonts';

// Register the bundled Roboto font data in the virtual file system
pdfmake.addVirtualFileSystem(vfsFonts);
Node.js (CommonJS)In Node.js, require the package and point addFonts() at the actual font files. The fonts/Roboto helper module exports the correct path map for you:
const pdfmake = require('pdfmake');
const Roboto = require('pdfmake/fonts/Roboto');

pdfmake.addFonts(Roboto);

// Recommended: declare access policies for URLs and local paths
pdfmake.setUrlAccessPolicy((url) => url.startsWith('https://'));
pdfmake.setLocalAccessPolicy((_path) => true);
The virtual file system (vfs) is pdfmake’s in-memory store for binary assets. In the browser there is no real file system, so font files must be pre-loaded into the vfs as base64 strings. The vfs_fonts.js bundle does this automatically for Roboto. For custom fonts, see the Custom Fonts guide.
3

Create a document definition

Everything about your PDF is described in a single plain JavaScript object. The content array holds the document’s body — strings, styled text objects, tables, lists, images, and more.Here is a meaningful example combining styled text, an ordered list, and a simple table:
const docDefinition = {
  content: [
    // Styled heading
    { text: 'Quarterly Report', fontSize: 22, bold: true, margin: [0, 0, 0, 10] },

    // Plain paragraph
    'This report summarises the activity for Q1. All figures are preliminary.',

    // Ordered list
    { text: 'Key highlights:', bold: true, margin: [0, 10, 0, 4] },
    {
      ol: [
        'Revenue increased by 12% year-over-year.',
        'Operating costs reduced through process automation.',
        'Three new enterprise customers onboarded in March.'
      ]
    },

    // Table with a header row and styled cells
    { text: 'Regional breakdown', bold: true, margin: [0, 14, 0, 4] },
    {
      style: 'tableStyle',
      table: {
        headerRows: 1,
        widths: ['*', 'auto', 'auto'],
        body: [
          [
            { text: 'Region',   style: 'tableHeader' },
            { text: 'Revenue',  style: 'tableHeader' },
            { text: 'Growth',   style: 'tableHeader' }
          ],
          ['North America', '$4.2 M', '+14%'],
          ['Europe',        '$2.8 M', '+9%'],
          ['Asia-Pacific',  '$1.6 M', '+21%']
        ]
      },
      layout: 'lightHorizontalLines'
    }
  ],

  styles: {
    tableStyle: { margin: [0, 5, 0, 15] },
    tableHeader: { bold: true, fontSize: 12, color: 'black' }
  },

  defaultStyle: {
    fontSize: 11
  }
};
Every node in content is either a plain string (rendered with the default style) or an object with explicit properties. Style inheritance flows from defaultStyle through named styles to inline properties, so you only override what you need.
4

Generate the PDF

Pass the document definition to createPdf(), which returns an output document object. Call the delivery method that matches your environment.Browser — trigger a file download
pdfmake.createPdf(docDefinition).download('quarterly-report.pdf');
You can also open the PDF in a new tab or get the raw data:
// Open in a new browser tab
pdfmake.createPdf(docDefinition).open();

// Retrieve a Blob (e.g. to upload to a server)
const blob = await pdfmake.createPdf(docDefinition).getBlob();

// Retrieve a base64 data URL (e.g. to embed in an <img>)
const dataUrl = await pdfmake.createPdf(docDefinition).getDataUrl();
Node.js — write to disk
const pdf = pdfmake.createPdf(docDefinition);

// Write a file to disk
pdf.write('output/quarterly-report.pdf').then(() => {
  console.log('PDF written successfully.');
}).catch((err) => {
  console.error(err);
});
You can also get the binary buffer directly — useful for HTTP responses or further processing:
const buffer = await pdf.getBuffer();
// e.g. res.end(buffer) in an Express handler

Complete working example

Below is a self-contained Node.js script you can run immediately after installing pdfmake. It combines every step above into a single file.
const pdfmake = require('pdfmake');
const Roboto   = require('pdfmake/fonts/Roboto');

// 1. Configure fonts
pdfmake.addFonts(Roboto);
pdfmake.setUrlAccessPolicy((url) => url.startsWith('https://'));
pdfmake.setLocalAccessPolicy((_path) => true);

// 2. Build the document definition
const docDefinition = {
  content: [
    { text: 'Quarterly Report', fontSize: 22, bold: true, margin: [0, 0, 0, 10] },
    'This report summarises the activity for Q1. All figures are preliminary.',
    { text: 'Key highlights:', bold: true, margin: [0, 10, 0, 4] },
    {
      ol: [
        'Revenue increased by 12% year-over-year.',
        'Operating costs reduced through process automation.',
        'Three new enterprise customers onboarded in March.'
      ]
    },
    { text: 'Regional breakdown', bold: true, margin: [0, 14, 0, 4] },
    {
      style: 'tableStyle',
      table: {
        headerRows: 1,
        widths: ['*', 'auto', 'auto'],
        body: [
          [
            { text: 'Region',   style: 'tableHeader' },
            { text: 'Revenue',  style: 'tableHeader' },
            { text: 'Growth',   style: 'tableHeader' }
          ],
          ['North America', '$4.2 M', '+14%'],
          ['Europe',        '$2.8 M', '+9%'],
          ['Asia-Pacific',  '$1.6 M', '+21%']
        ]
      },
      layout: 'lightHorizontalLines'
    }
  ],
  styles: {
    tableStyle:  { margin: [0, 5, 0, 15] },
    tableHeader: { bold: true, fontSize: 12, color: 'black' }
  },
  defaultStyle: { fontSize: 11 }
};

// 3. Generate and save
pdfmake.createPdf(docDefinition)
  .write('quarterly-report.pdf')
  .then(() => console.log('Done — quarterly-report.pdf written.'))
  .catch((err) => console.error(err));
If you see a warning such as “No URL access policy defined” or “No local access policy defined” when running in Node.js, add setUrlAccessPolicy() and setLocalAccessPolicy() calls as shown above. These guards prevent pdfmake from inadvertently fetching remote resources or reading arbitrary local files — they are required in production Node.js usage.

Build docs developers (and LLMs) love