I Built a 100% Client-Side File Converter (No Server Uploads) — Here's What I Learned
Hey dev.to! 👋
I recently built Easy2Convert.xyz, a file converter that runs entirely in the browser. No servers, no uploads, no privacy concerns.
Here is the story of how I built it, the architecture behind it, and what I learned about browser-based file manipulation.
TL;DR: Built a privacy-first file converter using Next.js + pdf.js + Canvas API. Zero server uploads, works offline via Service Workers, handles HEIC/WebP via WASM. Try it: easy2convert.xyz
Why I Built This
Most online converters upload your files to their servers. For sensitive documents (contracts, IDs, financial records, family photos), this is a massive privacy risk.
Many security researchers have highlighted that free online tools often retain uploaded files longer than their stated retention policies — sometimes indefinitely. Even if they claim to delete files after an hour, you have no way to verify it.
I wanted to build a tool that gives users 100% control and ownership of their data by processing everything locally in the client-side sandbox.
Tech Stack & Architecture
To achieve serverless file conversion, the project is built on:
- Next.js 14 (App Router) for a fast, responsive UI with SSR benefits
- pdf.js for client-side PDF rendering, text extraction, and manipulation
- HTML5 Canvas API for client-side image decoding, scaling, and compression
- Web Workers to offload heavy computations from the main thread, keeping the UI smooth
- WebAssembly (WASM) libraries for HEIC decoding on non-Apple devices
+-----------------------------------------------------------------+
| LOCAL BROWSER SANDBOX (Client-Side Architecture) |
| |
| 📁 File Read → Local RAM ArrayBuffer |
| ⚙️ WebAssembly / Canvas Engine Decodes Binary Locally |
| 📦 Instant Output Blob Generated |
| 🔒 ZERO bytes uploaded to external servers |
| |
+-----------------------------------------------------------------+
Key Learnings & Challenges
1. Browser Memory Limits
Web browsers aren't designed to load gigabytes of data into RAM. We ran into memory issues when dealing with files larger than 50MB.
The biggest culprit? Forgetting to release object URLs after download:
// ❌ Memory leak - object URL never released
const url = URL.createObjectURL(blob);
downloadLink.href = url;
// ✅ Proper cleanup - prevents memory leaks
const url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.addEventListener('click', () => {
setTimeout(() => URL.revokeObjectURL(url), 1000);
});
Using Blob objects efficiently and releasing object URLs immediately after download helped optimize garbage collection significantly.
2. HEIC and WebP Decoding
Browsers do not natively support all image formats — especially HEIC on non-Apple devices. We integrated lightweight decoding libraries compiled to WebAssembly to bridge this gap at near-native speeds.
The tradeoff? WASM binaries add ~2-3MB to the initial bundle. We solved this with dynamic imports:
// Load HEIC decoder only when user uploads a .heic file
const convertHEIC = async (file) => {
const { default: heic2any } = await import('heic2any');
return heic2any({ blob: file, toType: 'image/jpeg' });
};
3. Service Workers for Offline Support
Since no server is involved in the conversion, once the assets are loaded, the converter can function fully offline. Service Workers cache the core engines so users can convert files even mid-flight (literally — tested on airplane WiFi mode ✈️).
We used next-pwa with a CacheFirst strategy for static assets and Google Fonts. Once cached, the entire conversion pipeline works without any network connection.
4. The "Trust" Problem
Even with 100% client-side processing, users were skeptical. "How do I know you're not uploading my files?"
Our solution:
- Open architecture explanation on the homepage
- Network tab verification instructions in our FAQ
- Brand disclaimer separating us from legacy desktop software with similar names
Lesson: Privacy isn't just about what you do — it's about proving it to users.
Performance Optimization Journey
Initial Lighthouse scores were rough (Mobile: 62, Desktop: 78). Here's how we got to Mobile: 85+, Desktop: 90+:
| Optimization | Impact |
|---|---|
| Dynamic imports for heavy libs (pdf.js, heic2any) | +12 pts |
| Canvas animations disabled on mobile | +8 pts |
| AdSense script → lazyOnload strategy | +5 pts |
| Image optimization with Next.js Image component | +3 pts |
| Font preconnect + display=swap | +2 pts |
Check It Out
The site is fully responsive, free, and has no annoying download timers:
Features:
- 🖼️ Image Converter (HEIC, WebP, PNG, JPG)
- 📄 PDF to Word / Word to PDF
- ✏️ In-Browser PDF Editor (erase, redact, sign)
- ⚡ Base64 Encoder/Decoder
- 🧮 Developer Calculators Suite
What's Next
- [ ] Batch conversion support (multiple files at once)
- [ ] OCR for scanned PDFs (using Tesseract.js WASM)
- [ ] PWA install prompt for true offline-first experience
- [ ] Dark mode (because every dev tool needs one 😄)
- [ ] Open-source the core conversion engine on GitHub
If you have feature requests, architectural suggestions, or want to contribute, drop a comment below! 👇
Would love feedback from the community on local binary processing patterns! 🙏
Built with ❤️ using Next.js, pdf.js, and a stubborn belief that your files should never leave your device.
Top comments (0)