Building browser-only PDF tools — merge, split, and canvas builder without touching a server
Source: Dev.to
Most PDF processing tools upload your files to a server, but modern browser APIs let you handle PDFs entirely client‑side. Below is a concise guide to building three browser‑only PDF tools—merger, splitter, and canvas builder—using pdf‑lib, pdfjs‑dist, jszip, and Fabric.js.
PDF Merging with pdf-lib
pdf-lib works in both the browser and Node and provides a clean API for merging, splitting, and manipulating pages.
import { PDFDocument } from "pdf-lib";
async function mergePDFs(files) {
const merged = await PDFDocument.create();
for (const file of files) {
const src = await PDFDocument.load(file.bytes);
const indices = parseRanges(file.ranges, src.getPageCount());
const copied = await merged.copyPages(src, indices);
copied.forEach(page => merged.addPage(page));
}
return await merged.save(); // Uint8Array
}Page‑range selection
Users can specify ranges like "1-3,5,7-9" to pick specific pages from each file before merging.
function parseRanges(input: string, pageCount: number): number[] {
if (!input.trim()) return Array.from({ length: pageCount }, (_, i) => i);
const pages = new Set();
const parts = input.split(",").map(s => s.trim());
for (const part of parts) {
if (part.includes("-")) {
const [a, b] = part.split("-").map(Number);
for (let i = a; i = 1 && n a - b);
}Generating Thumbnails with pdfjs-dist
pdfjs-dist (Mozilla’s PDF renderer) can render pages to a canvas, which you can then turn into image thumbnails.
const pdfjsLib = await import("pdfjs-dist");
pdfjsLib.GlobalWorkerOptions.workerSrc =
`https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.mjs`;
const pdf = await pdfjsLib.getDocument({ data: new Uint8Array(bytes) }).promise;
const page = await pdf.getPage(1);
const viewport = page.getViewport({ scale: 0.3 });
const canvas = document.createElement("canvas");
canvas.width = viewport.width;
canvas.height = viewport.height;
await page.render({
canvasContext: canvas.getContext("2d"),
viewport,
}).promise;
const thumb = canvas.toDataURL("image/jpeg", 0.7);Packaging Split PDFs with jszip
When splitting a PDF into multiple files, jszip lets you bundle the results into a single ZIP download.
import JSZip from "jszip";
async function zipSplitPages(src, pageCount) {
const zip = new JSZip();
for (let i = 0; i import("@/components/pdf/PdfBuilderClient"),
{ ssr: false }
);Apply the same pattern to any component that relies on browser‑only libraries (e.g., the merger or splitter).
Privacy Benefits of Browser‑Only Processing
When all work happens in the browser, no data ever leaves the user’s device. This eliminates accidental leaks of sensitive documents such as:
- Contracts & NDAs
- Financial statements
- Medical records
- Personal identification
Open DevTools → Network tab while using the tools: you’ll see no upload requests—everything stays local.
Available Tools
- PDF Merger – combine PDFs with per‑file page‑range selection.
- PDF Splitter – split by pages, custom ranges, or visual selection.
- PDF Canvas Builder – design PDFs from scratch with a contextual Fabric.js UI.
If you’re building browser‑based file‑processing utilities, the pdf-lib + pdfjs-dist combo (plus jszip and Fabric.js when needed) covers the majority of PDF workflows without any server infrastructure.