PB Image Compressor — how it works
The PB Image Compressor is a tool we developed to make large images web-ready quickly and efficiently. No magic, no shortcuts — just a solid technical setup that performs as expected. Below, we explain how it is constructed and why we made these choices.
The technology
Sharp.js — the heart of the compressor
For image processing, we use Sharp, a fast Node.js library based on libvips. In practice, this is several times faster than ImageMagick or GraphicsMagick, and much more memory-efficient.
Sharp supports JPEG, PNG, WebP, AVIF, and TIFF, offering everything you need: resizing, cropping, rotating, sharpening, blurring.
Why Sharp:
Fast — C++ core with Node.js bindings
Memory-efficient — works with streams, no heavy buffers
Comprehensive — one API for all operations
mozJPEG — better JPEGs, smaller files
For JPEG output, we use mozJPEG, Mozilla's encoder. It delivers files that are on average 10–15% smaller with the same visual quality.
Our default settings:
{
quality: 85,
mozjpeg: true,
chromaSubsampling: '4:4:4',
trellisQuantisation: true,
overshootDeringing: true
}
In short: maximum colour information, minimal artefacts, without visible quality loss.
Backend architecture
Express API
The compression runs via a single POST endpoint:
/api/image-compressor/compress
The flow is simple and deliberately linear:
Multer receives the upload (multipart/form-data)
Validation checks type and size (max. 15 MB)
Sharp processes the image entirely in memory
Response sends back the compressed data
All in-memory
Important design decision: we never write files to disk.
const inputBuffer = req.file.buffer;
const outputBuffer = await sharp(inputBuffer)
.jpeg({ quality: 85, mozjpeg: true })
.toBuffer();
Advantages:
Privacy — nothing remains on the server
Speed — no disk I/O
Scalable — no cleanup, no temporary storage
Frontend
React + TypeScript
The frontend is built with React 18 and TypeScript. No over-engineering, just type-safe and predictable.
Drag & drop
Native HTML5 drag & drop, directly linked to the workflow:
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (validateFile(file)) {
compressAndDownload(file);
}
};
Upload = start. No extra buttons, no steps in between.
Fully automatic flow
Upload automatically starts compression
After validation, everything proceeds
Download begins automatically
Visual feedback shows when it's done
Minimal thinking, maximum efficiency.
Live system logs
During the process, we display real-time logs, so it's visible what is happening:
const addLog = (message: string) => {
setDisplayedLogs(prev => [...prev, > ${message}]);
};
Transparent and useful for testing or debugging.
Data fetching with TanStack Query
Configuration and server state are managed via TanStack Query:
useQuery({
queryKey: ["/api/image-compressor/config"],
staleTime: 1000 * 60 * 5
});
Smart caching, few requests, stable behaviour.
CMS & configuration
Database (Drizzle + PostgreSQL)
Settings are stored in PostgreSQL via Drizzle ORM:
export const imageCompressorConfig = pgTable(
"image_compressor_config",
{
id: varchar("id").primaryKey(),
title: varchar("title", { length: 255 }),
description: text("description"),
maxFileSizeMb: integer("max_file_size_mb").default(15)
}
);
CMS page
Via /cms/image-compressor labels, texts, and limits can be adjusted. Save = live instantly. No deployment needed.
Theming
Dark / light mode
The tool follows the global PB theme and supports dark and light mode:
function getColors(isLight: boolean) {
return {
bg: isLight ? '#fdfcfb' : '#050505',
surface: isLight ? '#f4f2ef' : 'rgba(23,23,23,0.3)',
text: isLight ? '#1a1a1a' : '#e5e5e5'
};
}
Consistent, calm, no loose styles.
Performance
In production, we see stable:
93–95% smaller files
< 2 seconds processing up to ±10 MB
No visible quality loss
Exactly what we wanted.
Conclusion
The PB Image Compressor is not a gimmick but a solid tool built on proven technology. Sharp and mozJPEG do the heavy lifting, React and TypeScript keep the frontend sleek, and the in-memory design ensures speed and privacy.
Want to try it:
/image-compressor
No explanation needed. Upload → done.
X Peet