DEV Community

resizekb
resizekb

Posted on

How I Built a Browser-Based File Compression Tool for India Using Canvas API and pdf-lib — No Backend Needed

I built ResizeKB — a free image and PDF resizer built specifically for Indian users. 25+ tools. Zero server uploads. Pure HTML, CSS, JavaScript. Here's how and why.

The Problem
Every Indian applying for government jobs, exams, or bank accounts hits the same wall — portals with strict KB limits rejecting documents.
UPSC wants photo under 300KB. SSC wants under 50KB. Banks need Aadhaar PDF under 500KB. Every portal is different. Every rejection wastes someone's time and opportunity.
Most people have no idea how to resize to an exact KB. They either give up or use random tools that upload their Aadhaar and PAN card to unknown servers.
I built a tool that solves this in one click — with zero server upload.

The Tech Stack
No framework. No backend. No database.

Canvas API for image processing
pdf-lib for PDF compression
Vanilla JavaScript only
Cloudflare Pages for hosting — free, global CDN, auto deploys from GitHub

Total infrastructure cost: ₹1,162 per year for the domain. Everything else free.

Image Compression — The Binary Search Algorithm
The core challenge is compressing to an exact KB target without over-compressing. Most tools use a fixed quality setting like 60% which destroys image quality.
The right approach is binary search on JPEG quality:
javascriptasync function compressToTargetSize(file, targetKB) {
const targetBytes = targetKB * 1024;
let low = 0.1;
let high = 1.0;
let result = null;

const img = await loadImage(file);
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);

while (high - low > 0.01) {
const mid = (low + high) / 2;
const blob = await canvasToBlob(canvas, 'image/jpeg', mid);
if (blob.size <= targetBytes) {
result = blob;
low = mid;
} else {
high = mid;
}
}
return result;
}
This finds the highest quality setting that still hits your target KB. Result is the sharpest possible image at that file size — never over-compressed.

PDF Compression — How It Works
pdf-lib is an open source JavaScript library that manipulates PDFs entirely in the browser. No server needed.
javascriptimport { PDFDocument } from 'pdf-lib';

async function compressPDF(file, targetKB) {
const arrayBuffer = await file.arrayBuffer();
const pdfDoc = await PDFDocument.load(arrayBuffer);
const pages = pdfDoc.getPages();
const totalPages = pages.length;

// Calculate target KB per page
const targetPageKb = (targetKB / totalPages) * 0.9;

// Rasterize each page to canvas at calculated DPI
// Recompress as JPEG at target quality
// Embed back into PDF structure

const compressed = await pdfDoc.save();
return new Blob([compressed], { type: 'application/pdf' });
}
Works best on image-heavy PDFs like scanned documents. Text-only PDFs are already compressed at the font layer — browser tools can't reduce them further, so ResizeKB detects this and tells the user instead of pretending it worked.

Privacy — Why It Matters
Most online tools upload your file to their servers. For Indian users this is a real risk — Aadhaar contains biometric data, address, 12-digit identity number. PAN card contains financial identity.
ResizeKB processes everything locally. You can verify this yourself — open browser developer tools → Network tab → upload a file → you'll see zero outgoing file transfer requests.
When you close the tab, everything is gone.

Browser Compatibility Considerations
A few things I ran into building this:
Canvas API toBlob() is async but older browsers handle it differently — use a Promise wrapper for consistency.
pdf-lib works well for image-heavy PDFs but has limitations with encrypted PDFs. Password-protected Aadhaar PDFs need to be unlocked first — I handle this with a user-facing message rather than silently failing.
Mobile performance — Canvas operations are CPU-intensive. For large images on low-end Android phones, I added a progress indicator so users don't think it crashed.
File size detection — always compare compressed size to original before downloading. If compressed is larger than original (happens with already-optimized files), return the original with a clear message.

What I'd Do Differently
WebAssembly-based PDF compression would be significantly faster and produce better results than pure JavaScript pdf-lib. MozJPEG via WASM produces 20-30% smaller files at the same visual quality. Future upgrade.
WebP output support — WhatsApp and modern browsers handle WebP well. Smaller files, better quality. Added to roadmap.

Results — Week 1

212 pages discovered by Google within 24 hours of sitemap submission
Live on resizekb.com
Listed on Product Hunt and SaaSHub on launch day
Referral traffic coming in from Quora answers on day 1

Try It
resizekb.com — free, no account, no watermark, works on mobile.
Source is private for now but happy to answer technical questions in the comments.

Top comments (0)