Create a PDF
You can use Medplum Bots to create a PDF file as an attachment.
There are always two steps:
- Create the PDF as a FHIR Binaryresource
- Use the Binaryresource as an attachment or content
To create PDFs, Medplum Bots use pdfmake. pdfmake uses a "Document Definition" model. You create a JSON object that defines paragraphs, styles, tables, etc. Medplum converts the document definition into a FHIR Binary resource with the PDF contents.
To learn more about pdfmake, check out the playground and examples.
FHIR Media
This bot creates a PDF as a Binary and then creates a Media with the PDF as the content.
export async function handler(medplum: MedplumClient, _event: BotEvent): Promise<any> {
  // Create the PDF
  const binary = await medplum.createPdf({
    docDefinition: {
      content: ['Hello world'],
    },
  });
  console.log('Binary result', binary);
  // Create a Media, representing an attachment
  const media = await medplum.createResource({
    resourceType: 'Media',
    status: 'completed',
    content: {
      contentType: 'application/pdf',
      url: 'Binary/' + binary.id,
      title: 'report.pdf',
    },
  });
  console.log('Media result', media);
}
Custom fonts
Medplum has prebuilt support for the following fonts:
- Helvetica
- Roboto
- Avenir
You can set the default font in the pdfmake defaultStyle:
const docDefinition = {
  content: { ... },
  defaultStyle: {
    font: 'yourFontName'
  }
}
You can also use inline styles:
const docDefinition = {
  content: [
    // If you don't need styles, you can use a simple string to define a paragraph
    'This is a standard paragraph, using default style',
    // Using a { text: '...' } object lets you set styling properties
    {
      text: 'Hello world',
      font: 'yourFontName',
    },
  ],
};
See the pdfmake styling page for more details.
Embedded images
You can load an image by URL and embed it in the PDF.
import type { BotEvent, MedplumClient } from '@medplum/core';
import fetch from 'node-fetch';
export async function botHandler(medplum: MedplumClient, _event: BotEvent): Promise<any> {
  // Load the image
  const image = await medplum.readResource('DocumentReference', YOUR_DOCUMENT_ID);
  const response = await fetch(image.content?.[0]?.attachment?.url as string);
  const buffer = await response.buffer();
  const imageData = `data:${response.headers.get('content-type')};base64,${buffer.toString('base64')}`;
  // Create the PDF
  const binary = await medplum.createPdf({
    docDefinition: {
      content: ['Hello world', { image: imageData }],
    },
  });
  console.log('Binary result', binary);
  // Create a Media, representing an attachment
  const media = await medplum.createResource({
    resourceType: 'Media',
    status: 'completed',
    content: {
      contentType: 'application/pdf',
      url: 'Binary/' + binary.id,
      title: 'report.pdf',
    },
  });
  console.log('Media result', media);
  return media;
}
See the pdfmake images page for more details.