DEV Community

Cover image for How We Built a Zero-Upload, Client-Side PDF Signer Using WebAssembly and Modern Web APIs
Suprabhat Mondal
Suprabhat Mondal

Posted on

How We Built a Zero-Upload, Client-Side PDF Signer Using WebAssembly and Modern Web APIs

When building browser-based file utilities, one of the biggest architectural challenges is handling sensitive documents. Traditionally, if a user wanted to digitally sign a PDF online, they had to upload their sensitive contracts, tax forms, or agreements to a remote server.

That means trusting a third-party backend with private keys, signatures, and confidential payloads. Even if files are deleted after processing, the mere act of uploading private documents over the network introduces an unnecessary security vector.

To solve this, we built a zero-upload utility to handle PDF signatures entirely client-side.

Sign PDF Online Free — Draw, Type or Upload a Signature

Sign a PDF online free: draw your signature, type it in a handwriting style or upload a photo of it, then place it, add the date and save. No account, no watermark, nothing uploaded.

favicon fixmypdfs.cc

Here is a deep dive into the technical architecture, why client-side processing outperforms traditional server-side pipelines, and how we engineered it for performance.


The Architecture: Why Client-Side Processing Wins

Most mainstream PDF manipulation tools rely on heavy backend stacks (Python with PyPDF2/ReportLab, Node.js with pdf-lib running in serverless functions, or complex Java/C++ microservices).

While servers have immense compute power, they introduce massive friction:

  • Network Overhead: Uploading large multi-megabyte PDFs over cellular or slow broadband connections wastes bandwidth and introduces latency.
  • Server Costs & Rate Limiting: Processing PDFs server-side requires CPU scaling, storage buckets, and aggressive rate-limiting or paywalls to manage infrastructure costs.
  • Privacy Risks: Documents traverse public networks, hitting load balancers, reverse proxies, and ephemeral disks before final cleanup.

The Zero-Upload Approach

With modern browsers acting as fully capable operating systems, we can shift the entire execution pipeline to the client.

  1. Zero Network Roundtrips: The PDF never leaves the user’s local machine.
  2. Instant Execution: Without network transfer times, file rendering and signing happen instantly.
  3. Absolute Privacy: Because execution happens in a sandboxed client environment, even if a user is offline, the tool continues to function seamlessly.

Under the Hood: Technical Implementation

To achieve native desktop-like performance inside a web browser, FixMyPDFs PDF Signer leverages a combination of Web APIs, Canvas rendering, and low-level binary manipulation libraries.

1. High-Performance PDF Rendering with PDF.js

Before a user can sign a document, they need to preview it. Instead of rendering heavy server-side rasters, we use PDF.js to parse the PDF structure directly in the browser's JavaScript engine.

  • The PDF file buffer (ArrayBuffer) is loaded directly into memory.
  • Pages are rendered onto an HTML5 <canvas> element using asynchronous rendering tasks (page.render()), ensuring smooth UI scrolling and zero main-thread blocking.

2. Precise Signature Placement via Pointer Events

Capturing signatures requires smooth vector tracking. We utilize the HTML5 Canvas API combined with pointer events (pointerdown, pointermove, pointerup) to support both mouse inputs on desktop and stylus/touch inputs on tablets or mobile devices.

const canvas = document.getElementById('signature-pad');
const ctx = canvas.getContext('2d');

let isDrawing = false;

canvas.addEventListener('pointerdown', (e) => {
    isDrawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX, e.offsetY);
});

canvas.addEventListener('pointermove', (e) => {
    if (!isDrawing) return;
    ctx.lineTo(e.offsetX, e.offsetY);
    ctx.stroke();
});

canvas.addEventListener('pointerup', () => {
    isDrawing = false;
});
Enter fullscreen mode Exit fullscreen mode

The resulting signature is exported as a transparent PNG data URL '(canvas.toDataURL('image/png'))' ready to be stamped onto the document coordinates.

3. Binary Modification with pdf-lib

Once the user positions their signature and hits export, the raw PDF byte array is modified using 'pdf-lib'. Rather than rewriting the entire document from scratch, 'pdf-lib' allows us to inject the signature image directly into the specified page's content stream at precise '(x, y)' coordinate mappings.

import { PDFDocument } from 'pdf-lib';

async function embedSignature(existingPdfBytes, signatureImageBytes, pageIndex, x, y, width, height) {
    // Load the existing PDF into memory
    const pdfDoc = await PDFDocument.load(existingPdfBytes);

    // Embed the PNG signature
    const pngImage = await pdfDoc.embedPng(signatureImageBytes);

    // Get the target page
    const pages = pdfDoc.getPages();
    const targetPage = pages[pageIndex];

    // Draw the image at the exact user-defined coordinates
    targetPage.drawImage(pngImage, {
        x,
        y,
        width,
        height,
    });

    // Serialize the PDF to bytes
    const pdfBytes = await pdfDoc.save();
    return pdfBytes;
}
Enter fullscreen mode Exit fullscreen mode

4. Triggering Local Downloads via Blob URLs

Once the modified byte array is generated, we package it into a Blob and create a temporary object URL, allowing the user to download the signed file instantly without any server intervention:

const pdfBytes = await embedSignature(...);
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'signed-document.pdf';
link.click();
Enter fullscreen mode Exit fullscreen mode

Conclusion & Try It Out

Modern web standards make it entirely unnecessary to send sensitive personal and professional documents to remote servers just to sign them. By combining Web APIs, Canvas, and client-side PDF manipulation libraries, we can build tools that are faster, more private, and entirely free to run.

If you want to test out the implementation or need a quick way to sign documents without uploading them anywhere, check out the live tool at fixmypdfs.cc/sign-pdf.

Have you experimented with 'pdf-lib' or client-side binary processing in your own web apps? Let me know your thoughts or optimization tips in the comments below!

Top comments (0)