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.
- photo_compressor treats the browser as the processing engine and the backend as a memory layer, not a file factory.
- The app keeps image pixels local while using Supabase for auth, history, and metadata, which makes privacy a product feature instead of a disclaimer.
- ToolsPage acts as the traffic controller, while blob URLs, Canvas, and Web Workers keep the UI responsive during real image work.
- The repo’s real differentiator is not compression itself, but the contract it offers: local editing first, sync second.
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.
| Approach | Where pixels are processed | Privacy model | Latency | Best fit | Trade-off |
|---|---|---|---|---|---|
| photo_compressor | In the browser | Pixels stay local | Low | Routine edits, quick conversions, private workflows | Less suited to massive server-grade batch jobs |
| Server image service | On remote infrastructure | Files must leave the device | Network round-trip | Bulk optimization, centralized pipelines | More trust, more latency |
| Desktop utility | On the local machine | Local by default | Low | Power users, offline work | Less convenient for web-native sharing |
| Developer library | Wherever the developer embeds it | Depends on implementation | Varies | Custom pipelines | Requires 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.
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
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.”
| Dimension | Local-only utility | photo_compressor |
|---|---|---|
| Processing | Temporary, session-bound | Local processing with saved workflow context |
| Persistence | Usually none | History and metadata via Supabase |
| Trust | No server involved, but also no continuity | Pixels stay local, state can sync |
| User experience | Fast but forgetful | Fast and resumable |
| Product shape | Tool | Lightweight 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 type | Strength | Weakness | Where photo_compressor fits |
|---|---|---|---|
| Server service | Aggressive optimization | Less private, more latency | Useful benchmark, not the core model |
| Desktop app | Strong local control | Less web-native | Similar privacy posture, different distribution |
| CLI library | Automation and batch work | Requires technical setup | Better for pipelines than casual users |
| Browser-first SaaS | Immediate access, low friction | Must manage browser constraints | Exactly where this repo aims |





