photo_compressor Turns the Browser Into an Image Pipeline

A privacy-first React app that compresses, converts, crops, and resizes images locally, then uses Supabase to preserve history without moving the heavy pixels off the user’s machine.

8 min read • View on GitHub • More from ABHIKUMAR06

A browser window acts like a workshop, taking in a paper photo on the left and sending it through crop, compression, and conversion stations before releasing a smaller file on the right. A slim cloud ledger sits off to the side, holding history and metadata while the image itself stays inside the browser. The scene explains the repo’s split architecture: local pixel processing, remote workflow memory.
The core idea is not just editing in the browser. It is keeping pixel work local while letting the backend remember the workflow.
Key Takeaways

This diagram separates the part that transforms pixels from the part that remembers work. That boundary is the whole product idea.

The browser does the heavy lifting

The interesting thing about photo_compressor is not that it edits images. Plenty of tools do that. The interesting part is where the work happens: inside the browser, with the user’s pixels staying local while Supabase handles identity, history, and metadata.

That split matters because it changes the trust model. The app is not asking users to send their files to a server just to make them smaller. It is asking the browser to do the real work, then using the backend as a thin memory layer.

ApproachWhere pixels are processedPrivacy modelLatencyBest fitTrade-off
photo_compressorIn the browserPixels stay localLowRoutine edits, quick conversions, private workflowsLess suited to massive server-grade batch jobs
Server image serviceOn remote infrastructureFiles must leave the deviceNetwork round-tripBulk optimization, centralized pipelinesMore trust, more latency
Desktop utilityOn the local machineLocal by defaultLowPower users, offline workLess convenient for web-native sharing
Developer libraryWherever the developer embeds itDepends on implementationVariesCustom pipelinesRequires wiring into an app or backend

I recently developed ImgCrush, a modern black-and-white themed image compression web application designed to make image optimization simple, fast, and distraction-free. The idea came from a very real frustration — most image compression tools online are either filled with ads, require signups, reduce quality badly, or hide features behind paywalls. I just wanted a clean, efficient solution without all the noise.

Aditya Deb, Developer of ImgCrush · ImgCrush post on LinkedIn

Why this architecture matters

The architecture solves three problems at once. It removes the upload round-trip for image processing, it lowers the risk of exposing private files, and it keeps the UI fast enough to feel like a utility instead of a cloud workflow.

That makes the app useful in a very specific way. It is built for casual, repetitive edits where users want a quick result, a clean interface, and a record of what they did without turning the whole thing into a server-side production line.

ToolsPage is the traffic controller

The central orchestrator lives in src/pages/ToolsPage.tsx. It manages the image state, tracks the original file alongside the processed version, and keeps the preview-first flow moving as each tool finishes its job.

// Inferred from ToolsPage.tsx usage
{
  file: File,
  preview: string,
  processed?: {
    file: File,
    preview: string
  }
}

The important browser detail is lifecycle management. The app uses URL.createObjectURL for instant previews, then calls URL.revokeObjectURL when state resets so blob memory does not linger. That is the kind of small discipline that keeps a browser-based editor from becoming a memory leak machine.

Compression runs off the main thread

A close-up control panel shows a slider linked by a thin mechanical rod to a spinning worker gear below a glass floor. The surface UI stays calm while the lower chamber does the strenuous work, showing how compression can run off the main thread without freezing the interface. The image explains why Web Workers matter in the compression flow.
The UI stays responsive because compression work moves off the main thread.

Compression is handled by browser-image-compression in ImageCompressor.tsx, and the repo opts into useWebWorker: true. That is the right move. It keeps the browser from freezing while the app reduces file size and computes the before-and-after delta.

const options = {
  maxSizeMB: 1,
  maxWidthOrHeight: 1920,
  useWebWorker: true,
};

The quality slider is not just a UI flourish. It exposes the trade-off directly, which makes the tool feel predictable. You can see the reduction percentage as a consequence of a setting, not as magic from a black box.

Canvas handles format conversion

Conversion is more transparent than compression. In ImageConverter.tsx, the app draws the source image onto a hidden canvas and calls toBlob in the target format. That keeps the implementation close to the browser’s native primitives instead of wrapping the job in another dependency.

canvas.toBlob((blob) => {
  if (!blob) return;
  // create file, map extension, update preview
}, targetFormat);

The small but important detail is filename correctness. The code maps the output extension manually so a converted JPEG does not keep a stale PNG suffix. That kind of polish matters because the user is not just previewing pixels. They are producing a file they will actually keep.

History makes it feel like a product

This is where the repo stops looking like a utility and starts looking like a SaaS shell. Supabase gives the app authentication and persistence, which means users can come back to previous work instead of treating every edit as a disposable one-off.

That changes the emotional contract. A browser tool usually says, “do the task and forget me.” This one says, “work here, and I will remember enough to make that work portable.”

DimensionLocal-only utilityphoto_compressor
ProcessingTemporary, session-boundLocal processing with saved workflow context
PersistenceUsually noneHistory and metadata via Supabase
TrustNo server involved, but also no continuityPixels stay local, state can sync
User experienceFast but forgetfulFast and resumable
Product shapeToolLightweight product

What this repo says about modern image tools

The broader landscape is not one-size-fits-all. Server services like TinyPNG still make sense for aggressive optimization at scale. Desktop apps like ImageOptim are great for power users. CLI libraries such as pixcompress, imagemin, or browser libraries like compressorjs serve developers who want control.

photo_compressor is choosing a different contract. It is saying that most everyday image work should happen where the file already is, and that the backend should remember the workflow rather than own the pixels. That is a neat product decision, and a credible one.

Tool typeStrengthWeaknessWhere photo_compressor fits
Server serviceAggressive optimizationLess private, more latencyUseful benchmark, not the core model
Desktop appStrong local controlLess web-nativeSimilar privacy posture, different distribution
CLI libraryAutomation and batch workRequires technical setupBetter for pipelines than casual users
Browser-first SaaSImmediate access, low frictionMust manage browser constraintsExactly where this repo aims