DEV Community

Cover image for I built a free image compressor that never uploads your images — everything runs in the browser
Tech & Craving
Tech & Craving

Posted on

I built a free image compressor that never uploads your images — everything runs in the browser

TL;DR

I built ImageSqueeze — a free, privacy-first image compressor that runs 100% in your browser. No images are ever sent to any server.

  • Drag & drop batch compression
  • Resize with SNS presets
  • WebP conversion
  • EXIF auto-removal
  • ZIP download

The Problem

Every time I needed to compress images for a blog post or client project, I'd reach for TinyPNG or Compressor.io. They work great, but there's always that nagging thought:

"Am I really okay uploading these client images to a third-party server?"

For personal blog images, it's fine. But for:

  • Client work under NDA — can't risk it
  • Internal company docs — policy says no
  • Personal photos with GPS data — definitely not

I wanted a tool that compresses images without sending them anywhere.


The Solution: Canvas API

Here's the key insight: browsers already have a built-in image processing engine — the Canvas API.

// The core of ImageSqueeze in ~15 lines
const img = new Image();
img.onload = () => {
  const canvas = document.createElement("canvas");
  canvas.width = targetWidth;
  canvas.height = targetHeight;

  const ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0, targetWidth, targetHeight);

  canvas.toBlob(
    (blob) => {
      // blob is your compressed image!
      // Original file never left the browser
    },
    "image/webp",
    0.8 // quality: 80%
  );
};
img.src = URL.createObjectURL(file);
Enter fullscreen mode Exit fullscreen mode

When you draw an image onto a Canvas and export it with toBlob(), the browser re-encodes it at your specified quality. EXIF metadata is automatically stripped in this process — it's a free privacy win.


Features

1. Batch Processing

Drop multiple images at once. Free tier handles 10 images, PRO is unlimited.

2. Smart Compression

  • Quality slider (1–100%)
  • PNG files auto-convert to WebP for better compression
  • If the compressed file is somehow larger than the original, the original is returned

3. Resize with Presets

Preset Size
Blog 800px width
OGP 1200 × 630
Instagram 1080 × 1080
Twitter Header 1500 × 500
Thumbnail 300 × 300

With "Lock Aspect Ratio" on, images fit within the target dimensions without upscaling.

4. Format Conversion

Convert between JPG, PNG, and WebP. When converting PNG (with transparency) to JPEG, the background is automatically filled with white.

5. EXIF Removal

GPS coordinates, camera model, timestamps — all stripped automatically via Canvas re-rendering. Toggle it on/off in the Compress tab.

6. Re-compress Without Re-uploading

Changed your mind about the quality setting? Click "Apply & Re-compress" — no need to drag & drop again.

7. ZIP Download

Download all compressed images as a single ZIP file via JSZip (dynamically imported to keep the initial bundle small).


How It Compares

Feature ImageSqueeze TinyPNG Squoosh
Processing Browser Server Browser
Batch 10 (free) 20/month 1 at a time
Resize SNS presets No Yes
ZIP download Yes No No
Re-compress Yes No No
EXIF removal Yes No No
Price Free / $9.99 PRO Free / API paid Free

Trade-offs

I want to be honest about the limitations:

1. Compression quality
Canvas toBlob() uses the browser's built-in encoder. It's decent but not as sophisticated as TinyPNG's server-side AI compression. You might get slightly larger files for the same visual quality.

2. No AVIF support (yet)
Most browsers can't encode AVIF via Canvas. WebP is the best client-side option right now.

3. Large images eat memory
Since everything runs in the browser, processing fifty 20MB RAW files will consume significant RAM. The tool works best with web-sized images.


Tech Stack

  • Next.js 16 + TypeScript + Tailwind CSS v4
  • Canvas API for all image processing
  • JSZip for ZIP generation (dynamic import)
  • FileSaver.js for download handling
  • Vercel for hosting
  • Google Stitch for UI design (generated the design system)
  • i18n — auto-detects Japanese/English from browser language

What I Learned

Google Stitch for UI Design

This was my first time using Google Stitch to generate UI designs. I connected it via MCP (Model Context Protocol) to Claude Code, which let me:

  1. Generate the initial UI from a text prompt
  2. Get the HTML/CSS code directly
  3. Convert it to React components

The design system it generated ("The Digital Sanctuary" concept) gave me a complete color palette, typography rules, and component specifications. Saved hours of design work.

Canvas API Gotchas

  • JPEG + transparency = black background. You need to fill the canvas with white before drawing.
  • toBlob() can return null on memory pressure. Always handle it.
  • Object URLs leak memory. Always call URL.revokeObjectURL() when done.
  • PNG "compression" can increase file size. PNG is lossless, so Canvas re-encoding at quality 1.0 can actually produce a larger file. That's why I auto-convert PNG to WebP.

Try It

Live: image-squeeze-blush.vercel.app

Source: github.com/bbtc3453/image-squeeze

Free for 10 images. No account needed. No data sent anywhere.

If you find it useful, a GitHub star would mean a lot. Feedback and PRs are welcome!


Built in a day with Claude Code + Google Stitch. The entire process — from idea to deployment to this article — was completed in a single session.

Top comments (0)