Compress images without compromise.
Compreso is a lightweight, privacy-first image compression tool — no uploads to third-party servers, no disk writes, just fast in-memory compression powered by sharp.
Built by Viswanath Bodasakurthi under OneMark.
- Drag-and-drop, click-to-browse, or paste with ⌘V
- JPEG and PNG support
- Quality slider (1–100) with live before/after size estimates (single-file mode)
- Target size input — type a desired file size (
200 KB,1.5 MB) per image; quality auto-adjusts via binary search over/estimate(~7 calls) - Slider syncs in real-time as you type a target size (single-file mode, debounced 600ms)
- Per-image independent quality — each card compresses at its own quality level
- Re-compress button appears on already-compressed cards
- ZIP download for batch compression
- Total savings summary across all files
- GSAP animations on cards, controls, and the /health dashboard
- All compression happens in-memory — nothing is ever written to disk
compreso/
├── server/ Node.js + Express compression API (port 3001)
│ ├── index.js
│ ├── .env
│ └── package.json
└── client/ React + Vite frontend (port 5173)
├── src/
│ ├── App.jsx Router (/ and /compress)
│ ├── Landing.jsx Landing page (GSAP animated)
│ ├── Landing.css
│ ├── Compressor.jsx Image compression tool
│ ├── App.css
│ └── main.jsx
├── vercel.json SPA routing for Vercel
└── package.json
cd server
npm install
npm run dev # node --watch, restarts on file changeAPI listens on http://localhost:3001.
cd client
npm install
npm run dev # Vite dev server
npm run build # production bundleApp runs at http://localhost:5173.
| Path | Description |
|---|---|
/ |
Landing page — showcases Compreso and CompresoClean |
/compress |
The image compression tool |
Returns a styled HTML status page in browsers, or { "status": "ok", "service": "compreso" } for API clients (based on Accept header).
| Parameter | Type | Description |
|---|---|---|
file |
multipart/form-data |
JPEG or PNG image (max 50 MB) |
quality |
query param, integer 1–100 | Compression quality (default: 80) |
Response headers:
| Header | Description |
|---|---|
X-Original-Size |
Original file size in bytes |
X-Compressed-Size |
Compressed file size in bytes |
X-Format |
Output MIME type (image/jpeg or image/png) |
Response body is the compressed image binary.
Same parameters as /compress. Returns { originalSize, estimatedSize } in bytes without transferring the image. Used for live estimates and the target-size binary search.
| Layer | Technology |
|---|---|
| API | Node.js, Express, multer, sharp |
| Frontend | React 18, Vite, React Router |
| Animations | GSAP + ScrollTrigger |
| Batch download | JSZip |
| Compression | sharp (libvips) |
- Push the repo to GitHub.
- Import the repo in vercel.com/new.
- Set Root Directory to
client/. - Framework preset: Vite (auto-detected).
- Add environment variable:
VITE_API_URL=https://your-server-url.com - Deploy. The
vercel.jsonrewrites handle SPA routing.
If
VITE_API_URLis not set the client falls back tohttp://localhost:3001.
InCompressor.jsxchange theAPI_URLconstant or read fromimport.meta.env.VITE_API_URL.
brew install flyctl
fly auth signup # or fly auth login if you have an account
cd server
fly launch # auto-detects Node.js, generates fly.toml
fly secrets set ALLOWED_ORIGIN=https://your-vercel-app.vercel.app
fly deployServer URL: https://server-green-snowflake-4095.fly.dev
Note: Fly.io free tier includes 3 always-on shared VMs — no cold starts, no GitHub linking required.
-
ALLOWED_ORIGINon server matches exact Vercel URL (no trailing slash) -
VITE_API_URLin Vercel points to server URL (no trailing slash) - Verify
/healthreturns 200 athttps://your-server-url/health - Test compress + download end-to-end on the live URL
Compreso — OneMark