All guides
GlassCompressWeb

How I Built GlassCompress

After GlassPad, I kept hearing the same request: “Can you shrink this photo before I email it?” Most online compressors want an upload. Many strip EXIF in ways you cannot see. Passport and social sizes are buried behind paywalls. GlassCompress is my answer — a free tool at glasscompress.madushka.com that runs entirely in your browser. Nothing leaves your device.

The problem

Travel clients send me huge JPEGs from phones. Job applications need passport-size crops. Social posts want exact aspect ratios. Desktop tools work, but not everyone has one installed — and uploading personal photos to a random website feels wrong.

  • No server upload — decode and encode in-memory only
  • Live output size while you drag quality or crop
  • Presets for passport, Instagram, Facebook, YouTube, OG images, and common ratios
  • HEIC/HEIF decode so phone photos work without a desktop converter
  • Flip/mirror, Help modal, GlassPad handoff, and installable PWA
  • Batch ZIP and image→PDF for paperwork

Stack and architecture

Same philosophy as GlassPad: static HTML, CSS, and vanilla JavaScript. No React, no build step for the tool itself. It ships inside madushka.com on a Cloudflare Worker that routes glasscompress.madushka.com to the same assets as the legacy /tools/compress/ path (301 redirect to the subdomain).

The encode path uses a dedicated Web Worker with OffscreenCanvas so heavy JPEG/WebP/PNG (and AVIF where supported) work stays off the main thread. HEIC lands via a client-side decoder before that pipeline. The main script handles UI, debounced re-encode, crop/flip overlay, Help, and downloads.

Pipeline: decode → crop → resize → encode

Each dropped file becomes an in-memory item: original dimensions, blob URL for preview, optional per-item rotation and crop rectangle. On every settings change, the pipeline:

  1. Draws the source image to a canvas (EXIF orientation handled at decode)
  2. Applies the crop region in pixel space
  3. Resizes to preset output or max-edge cap
  4. Encodes with quality slider or binary-searches toward a target KB
Preview gotcha

Revoking blob URLs too early blanked the preview on first ship. Keep object URLs alive until the item is removed — a small lifecycle detail that matters a lot in UX.

Crop UX (v1 → v2)

Early feedback: the crop frame felt “stuck” — users could drag but had no obvious save path and on mobile the stage sat below the fold. Fixes shipped in layers:

  • Toolbar with Reset frame and Download selection under the crop stage
  • Compact hero when images are loaded; scroll crop into view on mobile
  • Use full image one-click, arrow-key nudge, pinch-to-zoom, double-tap to reset zoom

Presets lock aspect ratio (passport mm/cm with DPI, 1080×1350 posts, story, covers). Free mode keeps all handles. The crop math lives in one module; the overlay is pure DOM + pointer events.

Presets and batch

Presets are data, not hard-coded UI branches — passport sizes, social templates, and ratio locks (1:1, 4:5, 16:9). Batch mode reuses the same settings per item, caps at 20 images, and zips with JSZip. PDF export uses pdf-lib for A4 sheets when clients need print-ready pages.

Privacy as architecture

No analytics on file contents. No upload endpoint. The Worker only serves static files and SEO feeds — the compression never hits my server.

Branding and discovery

GlassCompress follows the GlassPad pattern: product subdomain, glass UI, shared madushka.com footer links, tools hub card, command palette entry, case study at /projects/glasscompress/, and its own robots.txt + sitemap.xml on the subdomain for Search Console.

What I'd do differently

  • Ship crop toolbar in v1 — users need an obvious “done” affordance
  • Treat HEIC as day-one scope — most phone photos arrive as HEIC, not JPEG
  • Automated visual tests for crop overlay on narrow viewports
  • Document GlassPad ↔ GlassCompress handoff in the first Help pass, not as a later footnote

If you build your own

  1. Keep files on-device and say so loudly.
  2. Show output bytes before download — trust beats mystery.
  3. Invest in crop on mobile; compression is the easy part.
  4. Use a Worker for routing and SEO, not for user images.

That is the GlassCompress playbook: constrain the stack, decode HEIC early, encode in a worker, polish crop and flip, hand off to GlassPad when needed, never upload the photo.

Try it at glasscompress.madushka.com — or read How I Built GlassPad for the sibling story.