Image compression thatnever leaves your device.
A browser-based image optimizer: six codecs, side-by-side comparison with a diff view and histograms, a target-size optimizer, batch export, and zero uploads. Live at snapwap.vercel.app.
-69%on the poster in the screenshot, WebP at quality 80, no visible loss

The problem
Every image compressor on the web asks you to upload the photo first. For a product screenshot, a contract scan, or a family picture, that is a trust problem before it is a technical one. SnapWap does the whole job on your own device, and shows you the original and the result side by side so you can judge the trade-off yourself.
The engineering version
What was hard, and what I did about it
Encoding without freezing the page
An AVIF encode can take seconds. Run it on the main thread and every slider feels broken, because the page cannot paint until the encoder returns.
What I did. Moved all encoding into a background worker and made every new change cancel the one before it, so the interface always answers the latest input, not the oldest.
Implementation notes
Hitting an exact file size
People have hard limits: under 100 KB for a marketplace upload, under 2 MB for a form. Dragging a slider and re-checking the size is guesswork.
What I did. Built a target-size optimizer: type the number of kilobytes and it finds the highest quality that fits, and if no quality fits it scales the image down step by step until one does.
Implementation notes
Getting the licence right
The best palette quantizer available is GPL. Serving that WebAssembly to a browser is conveying it, which has consequences for the whole product.
What I did. Chose GPL-3.0 for the product on purpose, wrote down why, and built the quantizer behind an interface so it can be swapped for a permissive one later without a rewrite.
Implementation notes
Measuring before claiming
The first release felt slow. The tempting answer was to say GPU, or to quote frame rates. Neither would have been true.
What I did. Checked the shipped codec binaries against the upstream Squoosh builds and found they were the baseline versions, without SIMD or threads. Swapped in the SIMD WebP build, staged the threaded AVIF and JPEG XL builds, and wrote down what was measured and what was not.
Implementation notes


Ask me about
- Why cancelling stale encodes mattered more than which codec I picked
- How the target-size search converges, and when it has to downscale instead
- What the GPL decision cost and what it bought
- What I found when I compared the shipped codec binaries with upstream
Built with Next.js, React, TypeScript, WebAssembly, Web Workers, MozJPEG, libwebp, libaom, libjxl, OxiPNG.