Skip to content

PDF Microservice

URL: https://pdf.microservices.hexlabs.co.uk

This allows us to rapidly build pdfs.

Overview

This uses puppeteer that visits a page and saves the pdf template. Any data passed into the request body will be added to localStorage for use in the pdf template.

PDF design features are added to the page using the ~/layouts folder. All elements to show up on every file should be using position fixed.

Multiple pages can be grouped and will be merged before being stored in firebase storage.

How it works

  1. Request is sent to server specifying the pages to be used.
  2. A puppeteer client is started.
  3. Any data recieved by the server is loaded into the puppeteer clients localStorage.
  4. Puppeteer loads the appropriate page.
  5. The localStorage is put into a reactive variable store to be used by the page.
  6. Page breaks are dynamically added to the page.
  7. The PDF is saved by puppeteer.
  8. All pages are concatanated in order and uploaded to firebase storage.
  9. A return value is sent back.

Adding new templates

  1. Create a layout. The layout should have #footer and #header items with fixed positioning.
  2. Create ~/pages/<new-layout-name>/<pdf-name>
  3. Write in <pdf-name>.vue the content of the document.
  4. Create a ~/pages/<layout-name>/dev-data/<pdf-name>.json file with the data that will be added to the page. This will automatically populate the page in DEV mode. (specify in ~/flags.ts)

Note

  • The header and footer should be visible and be fixed.
  • Line breaks will be auto added
  • Its important to make a ~/pages/<folder-name> folder for each layout so they can be picked from the api.

This needs to be added to every page to expose data and dynamically add page breaks.

typescript
const { data } = await pdfOnMount({
    path: useRoute().path,
})

Development

  • In your dev tools make the screen size 800px x 1125px to mimic the pdf size.

Note: You can make a custom screen size in Chrome Dev Tools for ease of use.

Endpoints

POST: /api/pdf

For now this is the only endpoint.

All pages passed here will be concatanated into a single document.

typescript
interface RequestBody {
    pages: {
        page: string
        layout: string
        data: any
    }[]

    fileName: string // what the file will be named
}

The return object will be:

typescript
interface ProjectFile {
    id: string
    name: string
    size: number
    mime: "application/pdf"
    timestamp: number
    lastModified: number
    previewUrl: string
    downloadUrl: string
}

POST: /api/dev/pdf

Does the same as the above but uses the <dev-data>.json file instead.

typescript
interface RequestBody {
    pages: {
        page: string
        layout: string
    }[]
}