Building a Serverless PDF Merger & Editor using React and pdf-lib (No Backend!)

Published: (December 22, 2025 at 04:33 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Introduction

I merge PDFs about twice a week. Not enough to pay for an Adobe subscription, but enough to be annoyed by online tools.

You know the drill:

  • Google “merge pdf free”.
  • Upload your private bank statement to a random server.
  • Get hit with a “Daily Limit Reached” popup just when you need to download the result.

I got tired of this. Modern browsers and WebAssembly are fast enough to handle PDF manipulation client‑side, so a backend isn’t necessary anymore. I built Simple VaultPDF to solve this.

The Tech Stack

  • Framework: React (Vite)
  • PDF Engine: pdf-lib (for merging/splitting) & pdf.js (for rendering)
  • OCR: tesseract.js
  • State Management: Just React hooks, kept it simple.

The Code (How it works)

import { PDFDocument } from 'pdf-lib';

const mergeFiles = async (files) => {
  const mergedPdf = await PDFDocument.create();

  for (const file of files) {
    const fileBuffer = await file.arrayBuffer();

    const pdf = await PDFDocument.load(fileBuffer);

    const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());

    copiedPages.forEach((page) => mergedPdf.addPage(page));
  }

  const pdfBytes = await mergedPdf.save();
  return pdfBytes;
};

Why Local‑First?

  • Zero Server Costs: No processing on AWS or cloud functions.
  • Privacy: Data never leaves the user’s machine, so there’s no need to trust a third‑party server.
  • Speed: Eliminates upload/download latency.

The Result

I just published the extension to the Chrome Web Store. If you’re tired of paywalls or want to see how pdf-lib performs in a real extension, give it a try.

Simple VaultPDF on Chrome Web Store

Let me know if you find any bugs—I’m still optimizing memory usage for large files.

Happy coding!

Back to Blog

Related posts

Read more »