Every time I needed to compress an image or merge a PDF, I'd end up on some random website, uploading sensitive files to a server I didn't control. It always felt wrong.
So I built FileWash — a suite of free file tools where everything runs in your browser. Your files never leave your device.
The Problem
Tools like TinyPNG, iLovePDF, and remove.bg work great. But they all share the same architecture: upload your file to a server, process it there, download the result.
This means:
- Your files pass through someone else's server
- You're trusting their privacy policy (which you didn't read)
- There are usually file size limits, watermarks, or account requirements
- It doesn't work offline
For personal photos with EXIF location data? For company documents? For legal PDFs? The upload model feels like a compromise we shouldn't have to make.
The Architecture: Client-Side Everything
FileWash processes files entirely in the browser using JavaScript APIs. Here's how each tool works under the hood:
Image Compression
Uses the Canvas API with quality adjustment. Drop a JPEG in, and the browser re-encodes it at a lower quality setting:
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0, width, height)
// Quality 0.0-1.0 controls compression
const compressed = canvas.toDataURL('image/jpeg', 0.7)
The browser-image-compression library wraps this with smart defaults — resizing, WebWorker support, and format detection.
Format Conversion
HEIC to JPG uses the heic2any library which decodes Apple's HEIC format in JavaScript. SVG to PNG uses canvas rasterization. WebP/PNG/JPG conversions use the Canvas API's built-in codec support.
PDF Processing
PDF merge, split, and compress use pdf-lib (for manipulation) and pdfjs-dist (for rendering). These are the same libraries that power Firefox's PDF viewer — battle-tested and fast.
Background Removal
This was the most impressive one to get working client-side. It uses @imgly/background-removal, which loads an ONNX neural network model via WebAssembly. The model runs inference directly in the browser — no API calls.
QR Code Generation
Uses the qrcode library with error correction level H (30% redundancy), which means you can embed a logo in the center and the code still scans.
Tech Stack
- React 19 + TypeScript + Vite — fast builds, great DX
- Tailwind CSS — styling without the CSS bloat
- Pre-rendered to static HTML — 464 pages across 16 languages, built at compile time
- Lazy-loaded tool pages — the homepage bundle is 275KB, tool-specific code loads on demand
- All deployed as static files behind Cloudflare CDN
Performance: The Lazy Loading Story
The first version had a 1.4MB main bundle — every tool's dependencies loaded on every page. The homepage took 8+ seconds to become interactive on slow connections (India, mobile).
The fix was simple: React.lazy() for every tool page.
// Before: everything in one bundle
import ImageCompress from './pages/ImageCompress'
import PdfMerge from './pages/PdfMerge'
import BackgroundRemover from './pages/BackgroundRemover'
// After: each tool loads on demand
const ImageCompress = lazy(() => import('./pages/ImageCompress'))
const PdfMerge = lazy(() => import('./pages/PdfMerge'))
const BackgroundRemover = lazy(() => import('./pages/BackgroundRemover'))
Result: 1.4MB to 275KB main bundle (80% reduction). The heic2any library (1.3MB) now only loads when someone visits the HEIC converter. The ONNX runtime (381KB) only loads for background removal.
SEO for a Static SPA
FileWash supports 16 languages with 29 tool pages each = 464 URLs. All pre-rendered to static HTML at build time.
Each page has unique title tags, meta descriptions, FAQ schema markup, and breadcrumb structured data. The sitemap is generated automatically from the route definitions.
The pre-rendering script launches a local server, visits each route with a headless browser, and saves the rendered HTML. This gives Google fully crawlable content without needing SSR infrastructure.
Privacy as a Feature
The key insight: privacy isn't a restriction, it's a feature. When files never leave the device:
- No server costs for file processing
- No storage or bandwidth bills
- No GDPR compliance complexity
- No data breach risk
- Works offline (after first load)
- No file size limits
- No account required
The only analytics is Cloudflare's cookieless Web Analytics beacon — no cookies, no consent banner needed.
What I Learned
Client-side processing is surprisingly capable. Canvas API handles most image operations. WebAssembly unlocks AI models in the browser. PDF libraries are mature.
Bundle size is your LCP. Lazy loading isn't optional for tool-heavy SPAs. One
React.lazy()change cut our LCP P90 from 8 seconds to under 2.Pre-rendering beats SSR for static content. No server runtime, no edge functions, just HTML files on a CDN. Simpler, cheaper, faster.
Privacy sells itself. The "100% private — files never leave your browser" badge in the header isn't just marketing. Users mention it in every positive interaction.
Try It
FileWash is free, no account required. Compress images, merge PDFs, convert formats, remove backgrounds, generate QR codes with custom logos, strip metadata — all in your browser.
Available in 16 languages: English, Spanish, Chinese, German, French, Japanese, Portuguese, Korean, Italian, Russian, Dutch, Polish, Turkish, Arabic, Hindi, Romanian.
I'd love feedback — especially on compression quality, background removal accuracy, and any tools you'd want to see added.
Built with React, TypeScript, Vite, and Tailwind CSS. No servers were harmed in the processing of your files.
Top comments (0)