Docs
PDF

PDF

Utils for PDF generation.

Installation

Install the following dependencies:

pnpm add @react-pdf

Create lib/pdf/pdf.tsx

import { Document, Page, View } from "@react-pdf/renderer";
 
export const Pdf = ({
  children,
  title,
  padding = {
    left: "2.2cm",
    right: "2.2cm",
    top: "1.69cm",
    bottom: "1.69cm",
  },
}: {
  children: React.ReactNode;
  title: string;
  padding?: {
    left?: string;
    right?: string;
    bottom?: string;
    top?: string;
  };
}) => {
  return (
    <Document title={title}>
      <Page
        size="A4"
        style={{
          fontFamily: "Helvetica",
          paddingBottom: padding.bottom,
          paddingTop: padding.top,
          paddingLeft: padding.left,
          paddingRight: padding.right,
        }}
      >
        <View
          style={{
            display: "flex",
            flexDirection: "column",
            justifyContent: "flex-start",
          }}
        >
          {children}
        </View>
      </Page>
    </Document>
  );
};

Create lib/pdf/utils.ts

import { renderToStream } from "@react-pdf/renderer";
 
export const streamToBuffer = async (
  stream: NodeJS.ReadableStream,
): Promise<Buffer> => {
  return new Promise((resolve, reject) => {
    const chunks: Buffer[] = [];
    stream.on("data", (data) => {
      chunks.push(data as Buffer);
    });
    stream.on("end", () => {
      resolve(Buffer.concat(chunks));
    });
    stream.on("error", reject);
  });
};
 
export const generatePdfFromComponent = async (component: JSX.Element) => {
  // convert react component to stream
  const pdfStream = await renderToStream(component);
  // create buffer from stream
  const pdfBuffer = await streamToBuffer(pdfStream);
  return pdfBuffer;
};

Usage in route handler

PDF as instant download
export function GET() {
  const pdfBuffer = await generatePdfFromComponent(<Pdf />);
  const response = new Response(pdfBuffer);
  response.headers.set("Content-Type", "application/pdf");
  return response;
}