A minimal-dependency, minimal-configuration image optimizer with a Go API backend and a Next.js web frontend.
- Hybrid Optimization — Compresses WebP directly in the browser via Canvas APIs, and delegates JPEG/PNG compression and scaling to the Go backend.
- Go API Backend — Fast, low-overhead REST API server written in Go utilizing native codecs and Catmull-Rom interpolation for resizing.
- Modern Next.js Frontend — Beautiful, responsive user interface featuring drag-and-drop uploads, clipboard pasting, bulk downloads, and an interactive comparison slider.
- Zero Heavy Runtime Dependencies — No external C-libraries, GraphicsMagick, or libvips required to compile or run the backend.
- Monorepo Ready — Structured as a Turborepo monorepo powered by Bun for fast builds and workspace package management.
- Backend: Go (1.26+),
chirouter,golang.org/x/image/draw - Frontend: Next.js (16.2+), React 19, Tailwind CSS v4, Lucide Icons, JSZip
- Tooling: Bun, Turborepo, Ultracite (Oxlint + Oxfmt), Air (Go hot-reloading)
pigo/
├── apps/
│ ├── api/ # Go REST API backend (Port 3001)
│ └── web/ # Next.js web frontend (Port 3000)
├── packages/
│ └── typescript-config/ # Shared TypeScript configs
└── package.json # Workspace configuration
Make sure you have the following installed:
-
Clone the repository:
git clone https://github.com/PunGrumpy/pigo.git cd pigo -
Install dependencies:
bun install
Run both the Go API backend and the Next.js frontend concurrently:
bun dev- Frontend: http://localhost:3000
- API Backend: http://localhost:3001
This project uses Ultracite (Oxlint + Oxfmt) to enforce strict code standards and formatting:
- Check for code issues:
bun run check
- Automatically fix code formatting and linting issues:
bun run fix
Optimizes and resizes a JPEG/PNG image.
- Content-Type:
multipart/form-data
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file |
File | Yes | - | The image file to optimize (Max size: 10MB). Supported formats: JPEG, PNG, WebP. |
quality |
Integer | No | 82 |
Target image quality from 1 to 100. |
outputFormat |
String | No | "same" |
Target image format: "same", "jpeg", or "png". |
resizeWidth |
Integer | No | - | Target width in pixels (1-16384). |
resizeHeight |
Integer | No | - | Target height in pixels (1-16384). |
maintainAspect |
Boolean | No | true |
Maintain aspect ratio when resizing ("true" or "false"). |
| Header | Type | Description |
|---|---|---|
X-Original-Size |
Integer | Size of the original image in bytes. |
X-Compressed-Size |
Integer | Size of the optimized image in bytes. |
X-Elapsed-Ms |
Integer | Processing duration in milliseconds. |
X-Width |
Integer | Resized width of the output image in pixels. |
X-Height |
Integer | Resized height of the output image in pixels. |
Returns the health status of the API backend.
Response:
{
"status": "ok"
}